Import Cobalt 21.master.0.253153
diff --git a/src/third_party/skia/tools/AndroidSkDebugToStdOut.cpp b/src/third_party/skia/tools/AndroidSkDebugToStdOut.cpp
index 9dc9911..ad8c949 100644
--- a/src/third_party/skia/tools/AndroidSkDebugToStdOut.cpp
+++ b/src/third_party/skia/tools/AndroidSkDebugToStdOut.cpp
@@ -7,7 +7,7 @@
// Need to include SkTypes before checking SK_BUILD_FOR_ANDROID, so it will be
// set in the Android framework build.
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
#ifdef SK_BUILD_FOR_ANDROID
extern bool gSkDebugToStdOut;
diff --git a/src/third_party/skia/tools/AutoreleasePool.h b/src/third_party/skia/tools/AutoreleasePool.h
new file mode 100644
index 0000000..0582404
--- /dev/null
+++ b/src/third_party/skia/tools/AutoreleasePool.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAutoreleasePool_DEFINED
+#define SkAutoreleasePool_DEFINED
+
+/*
+ * Helper class for managing an autorelease pool for Metal. On other platforms this will
+ * do nothing so there's no need to #ifdef it out.
+ */
+#ifdef SK_METAL
+class AutoreleasePool {
+public:
+ AutoreleasePool();
+ ~AutoreleasePool();
+
+ void drain();
+
+private:
+ void* fPool;
+};
+#else
+class AutoreleasePool {
+public:
+ AutoreleasePool() {}
+ ~AutoreleasePool() = default;
+
+ void drain() {}
+};
+#endif
+
+#endif
diff --git a/src/third_party/skia/tools/AutoreleasePool.mm b/src/third_party/skia/tools/AutoreleasePool.mm
new file mode 100644
index 0000000..6116115
--- /dev/null
+++ b/src/third_party/skia/tools/AutoreleasePool.mm
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkTypes.h"
+#include "tools/AutoreleasePool.h"
+
+#import <Foundation/NSAutoreleasePool.h>
+
+AutoreleasePool::AutoreleasePool() {
+ fPool = (void*)[[NSAutoreleasePool alloc] init];
+}
+
+AutoreleasePool::~AutoreleasePool() {
+ [(NSAutoreleasePool*)fPool release];
+ fPool = nullptr;
+}
+
+void AutoreleasePool::drain() {
+ [(NSAutoreleasePool*)fPool drain];
+ fPool = (void*)[[NSAutoreleasePool alloc] init];
+}
diff --git a/src/third_party/skia/tools/CrashHandler.cpp b/src/third_party/skia/tools/CrashHandler.cpp
index f141e55..5a2186f 100644
--- a/src/third_party/skia/tools/CrashHandler.cpp
+++ b/src/third_party/skia/tools/CrashHandler.cpp
@@ -5,24 +5,19 @@
* found in the LICENSE file.
*/
-#include "CrashHandler.h"
+#include "tools/CrashHandler.h"
-#include "../private/SkLeanWindows.h"
+#include "src/core/SkLeanWindows.h"
#include <stdlib.h>
-// Disable SetupCrashHandler() unless SK_CRASH_HANDLER is defined.
-#ifndef SK_CRASH_HANDLER
- void SetupCrashHandler() { }
-
-#elif defined(GOOGLE3)
+#if defined(SK_BUILD_FOR_GOOGLE3)
#include "base/process_state.h"
void SetupCrashHandler() { InstallSignalHandlers(); }
#else
#if defined(SK_BUILD_FOR_MAC)
-
// We only use local unwinding, so we can define this to select a faster implementation.
#define UNW_LOCAL_ONLY
#include <libunwind.h>
@@ -55,18 +50,34 @@
}
#elif defined(SK_BUILD_FOR_UNIX)
-
// We'd use libunwind here too, but it's a pain to get installed for
// both 32 and 64 bit on bots. Doesn't matter much: catchsegv is best anyway.
+ #include <cxxabi.h>
+ #include <dlfcn.h>
#include <execinfo.h>
+ #include <string.h>
static void handler(int sig) {
- static const int kMax = 64;
- void* stack[kMax];
- const int count = backtrace(stack, kMax);
+ void* stack[64];
+ const int count = backtrace(stack, SK_ARRAY_COUNT(stack));
+ char** symbols = backtrace_symbols(stack, count);
SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig));
- backtrace_symbols_fd(stack, count, 2/*stderr*/);
+ for (int i = 0; i < count; i++) {
+ Dl_info info;
+ if (dladdr(stack[i], &info) && info.dli_sname) {
+ char demangled[256];
+ size_t len = SK_ARRAY_COUNT(demangled);
+ int ok;
+
+ abi::__cxa_demangle(info.dli_sname, demangled, &len, &ok);
+ if (ok == 0) {
+ SkDebugf(" %s\n", demangled);
+ continue;
+ }
+ }
+ SkDebugf(" %s\n", symbols[i]);
+ }
// Exit NOW. Don't notify other threads, don't call anything registered with atexit().
_Exit(sig);
@@ -84,6 +95,7 @@
SIGFPE,
SIGILL,
SIGSEGV,
+ SIGTRAP,
};
for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
@@ -95,9 +107,10 @@
}
}
- #elif defined(SK_CRASH_HANDLER) && defined(SK_BUILD_FOR_WIN)
+ #elif defined(SK_BUILD_FOR_WIN)
#include <DbgHelp.h>
+ #include "include/private/SkMalloc.h"
static const struct {
const char* name;
@@ -143,6 +156,11 @@
frame.AddrStack.Offset = c->Rsp;
frame.AddrFrame.Offset = c->Rbp;
const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
+ #elif defined(_M_ARM64)
+ frame.AddrPC.Offset = c->Pc;
+ frame.AddrStack.Offset = c->Sp;
+ frame.AddrFrame.Offset = c->Fp;
+ const DWORD machineType = IMAGE_FILE_MACHINE_ARM64;
#endif
while (StackWalk64(machineType,
@@ -184,9 +202,9 @@
SetUnhandledExceptionFilter(handler);
}
- #else // We asked for SK_CRASH_HANDLER, but it's not Mac, Linux, or Windows. Sorry!
+ #else
void SetupCrashHandler() { }
#endif
-#endif // SK_CRASH_HANDLER
+#endif // SK_BUILD_FOR_GOOGLE3?
diff --git a/src/third_party/skia/tools/DDLPromiseImageHelper.cpp b/src/third_party/skia/tools/DDLPromiseImageHelper.cpp
new file mode 100644
index 0000000..5cfbb6e
--- /dev/null
+++ b/src/third_party/skia/tools/DDLPromiseImageHelper.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/DDLPromiseImageHelper.h"
+
+#include "include/core/SkDeferredDisplayListRecorder.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkSerialProcs.h"
+#include "include/core/SkYUVAIndex.h"
+#include "include/core/SkYUVASizeInfo.h"
+#include "include/gpu/GrContext.h"
+#include "src/core/SkCachedData.h"
+#include "src/image/SkImage_Base.h"
+#include "src/image/SkImage_GpuYUVA.h"
+
+DDLPromiseImageHelper::PromiseImageCallbackContext::~PromiseImageCallbackContext() {
+ SkASSERT(fDoneCnt == fNumImages);
+ SkASSERT(!fUnreleasedFulfills);
+ SkASSERT(fTotalReleases == fTotalFulfills);
+ SkASSERT(!fTotalFulfills || fDoneCnt);
+
+ if (fPromiseImageTexture) {
+ fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
+ }
+}
+
+void DDLPromiseImageHelper::PromiseImageCallbackContext::setBackendTexture(
+ const GrBackendTexture& backendTexture) {
+ SkASSERT(!fPromiseImageTexture);
+ fPromiseImageTexture = SkPromiseImageTexture::Make(backendTexture);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<SkData> DDLPromiseImageHelper::deflateSKP(const SkPicture* inputPicture) {
+ SkSerialProcs procs;
+
+ procs.fImageCtx = this;
+ procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> {
+ auto helper = static_cast<DDLPromiseImageHelper*>(ctx);
+
+ int id = helper->findOrDefineImage(image);
+ if (id >= 0) {
+ SkASSERT(helper->isValidID(id));
+ return SkData::MakeWithCopy(&id, sizeof(id));
+ }
+
+ return nullptr;
+ };
+
+ return inputPicture->serialize(&procs);
+}
+
+static GrBackendTexture create_yuva_texture(GrContext* context, const SkPixmap& pm,
+ const SkYUVAIndex yuvaIndices[4], int texIndex) {
+ SkASSERT(texIndex >= 0 && texIndex <= 3);
+
+#ifdef SK_DEBUG
+ int channelCount = 0;
+ for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
+ if (yuvaIndices[i].fIndex == texIndex) {
+ ++channelCount;
+ }
+ }
+ if (2 == channelCount) {
+ SkASSERT(kR8G8_unorm_SkColorType == pm.colorType());
+ }
+#endif
+
+ return context->createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo);
+}
+
+void DDLPromiseImageHelper::uploadAllToGPU(GrContext* context) {
+ for (int i = 0; i < fImageInfo.count(); ++i) {
+ const PromiseImageInfo& info = fImageInfo[i];
+
+ // DDL TODO: how can we tell if we need mipmapping!
+ if (info.isYUV()) {
+ int numPixmaps;
+ SkAssertResult(SkYUVAIndex::AreValidIndices(info.yuvaIndices(), &numPixmaps));
+ for (int j = 0; j < numPixmaps; ++j) {
+ const SkPixmap& yuvPixmap = info.yuvPixmap(j);
+
+ sk_sp<PromiseImageCallbackContext> callbackContext(
+ new PromiseImageCallbackContext(context));
+
+ callbackContext->setBackendTexture(create_yuva_texture(context, yuvPixmap,
+ info.yuvaIndices(), j));
+ SkASSERT(callbackContext->promiseImageTexture());
+
+ fImageInfo[i].setCallbackContext(j, std::move(callbackContext));
+ }
+ } else {
+ sk_sp<PromiseImageCallbackContext> callbackContext(
+ new PromiseImageCallbackContext(context));
+
+ const SkBitmap& bm = info.normalBitmap();
+
+ GrBackendTexture backendTex = context->createBackendTexture(
+ &bm.pixmap(), 1, GrRenderable::kNo,
+ GrProtected::kNo);
+
+ callbackContext->setBackendTexture(backendTex);
+
+ // The GMs sometimes request too large an image
+ //SkAssertResult(callbackContext->backendTexture().isValid());
+
+ fImageInfo[i].setCallbackContext(0, std::move(callbackContext));
+ }
+ }
+}
+
+sk_sp<SkPicture> DDLPromiseImageHelper::reinflateSKP(
+ SkDeferredDisplayListRecorder* recorder,
+ SkData* compressedPictureData,
+ SkTArray<sk_sp<SkImage>>* promiseImages) const {
+ PerRecorderContext perRecorderContext { recorder, this, promiseImages };
+
+ SkDeserialProcs procs;
+ procs.fImageCtx = (void*) &perRecorderContext;
+ procs.fImageProc = PromiseImageCreator;
+
+ return SkPicture::MakeFromData(compressedPictureData, &procs);
+}
+
+// This generates promise images to replace the indices in the compressed picture. This
+// reconstitution is performed separately in each thread so we end up with multiple
+// promise images referring to the same GrBackendTexture.
+sk_sp<SkImage> DDLPromiseImageHelper::PromiseImageCreator(const void* rawData,
+ size_t length, void* ctxIn) {
+ PerRecorderContext* perRecorderContext = static_cast<PerRecorderContext*>(ctxIn);
+ const DDLPromiseImageHelper* helper = perRecorderContext->fHelper;
+ SkDeferredDisplayListRecorder* recorder = perRecorderContext->fRecorder;
+
+ SkASSERT(length == sizeof(int));
+
+ const int* indexPtr = static_cast<const int*>(rawData);
+ SkASSERT(helper->isValidID(*indexPtr));
+
+ const DDLPromiseImageHelper::PromiseImageInfo& curImage = helper->getInfo(*indexPtr);
+
+ if (!curImage.promiseTexture(0)) {
+ SkASSERT(!curImage.isYUV());
+ // We weren't able to make a backend texture for this SkImage. In this case we create
+ // a separate bitmap-backed image for each thread.
+ SkASSERT(curImage.normalBitmap().isImmutable());
+ return SkImage::MakeFromBitmap(curImage.normalBitmap());
+ }
+ SkASSERT(curImage.index() == *indexPtr);
+
+ sk_sp<SkImage> image;
+ if (curImage.isYUV()) {
+ GrBackendFormat backendFormats[SkYUVASizeInfo::kMaxCount];
+ void* contexts[SkYUVASizeInfo::kMaxCount] = { nullptr, nullptr, nullptr, nullptr };
+ SkISize sizes[SkYUVASizeInfo::kMaxCount];
+ // TODO: store this value somewhere?
+ int textureCount;
+ SkAssertResult(SkYUVAIndex::AreValidIndices(curImage.yuvaIndices(), &textureCount));
+ for (int i = 0; i < textureCount; ++i) {
+ const GrBackendTexture& backendTex = curImage.promiseTexture(i)->backendTexture();
+ backendFormats[i] = backendTex.getBackendFormat();
+ SkASSERT(backendFormats[i].isValid());
+ contexts[i] = curImage.refCallbackContext(i).release();
+ sizes[i].set(curImage.yuvPixmap(i).width(), curImage.yuvPixmap(i).height());
+ }
+ for (int i = textureCount; i < SkYUVASizeInfo::kMaxCount; ++i) {
+ sizes[i] = SkISize::MakeEmpty();
+ }
+
+ image = recorder->makeYUVAPromiseTexture(
+ curImage.yuvColorSpace(),
+ backendFormats,
+ sizes,
+ curImage.yuvaIndices(),
+ curImage.overallWidth(),
+ curImage.overallHeight(),
+ GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+ curImage.refOverallColorSpace(),
+ DDLPromiseImageHelper::PromiseImageFulfillProc,
+ DDLPromiseImageHelper::PromiseImageReleaseProc,
+ DDLPromiseImageHelper::PromiseImageDoneProc,
+ contexts,
+ SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+ for (int i = 0; i < textureCount; ++i) {
+ curImage.callbackContext(i)->wasAddedToImage();
+ }
+
+#ifdef SK_DEBUG
+ {
+ // By the peekProxy contract this image should not have a single backing proxy so
+ // should return null. The call should also not trigger the conversion to RGBA.
+ SkImage_GpuYUVA* yuva = reinterpret_cast<SkImage_GpuYUVA*>(image.get());
+ SkASSERT(!yuva->peekProxy());
+ SkASSERT(!yuva->peekProxy()); // the first call didn't force a conversion to RGBA
+ }
+#endif
+ } else {
+ const GrBackendTexture& backendTex = curImage.promiseTexture(0)->backendTexture();
+ GrBackendFormat backendFormat = backendTex.getBackendFormat();
+ SkASSERT(backendFormat.isValid());
+
+ // Each DDL recorder gets its own ref on the promise callback context for the
+ // promise images it creates.
+ // DDL TODO: sort out mipmapping
+ image = recorder->makePromiseTexture(
+ backendFormat,
+ curImage.overallWidth(),
+ curImage.overallHeight(),
+ GrMipMapped::kNo,
+ GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+ curImage.overallColorType(),
+ curImage.overallAlphaType(),
+ curImage.refOverallColorSpace(),
+ DDLPromiseImageHelper::PromiseImageFulfillProc,
+ DDLPromiseImageHelper::PromiseImageReleaseProc,
+ DDLPromiseImageHelper::PromiseImageDoneProc,
+ (void*)curImage.refCallbackContext(0).release(),
+ SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+ curImage.callbackContext(0)->wasAddedToImage();
+ }
+ perRecorderContext->fPromiseImages->push_back(image);
+ SkASSERT(image);
+ return image;
+}
+
+int DDLPromiseImageHelper::findImage(SkImage* image) const {
+ for (int i = 0; i < fImageInfo.count(); ++i) {
+ if (fImageInfo[i].originalUniqueID() == image->uniqueID()) { // trying to dedup here
+ SkASSERT(fImageInfo[i].index() == i);
+ SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].index()));
+ return i;
+ }
+ }
+ return -1;
+}
+
+int DDLPromiseImageHelper::addImage(SkImage* image) {
+ SkImage_Base* ib = as_IB(image);
+
+ SkImageInfo overallII = SkImageInfo::Make(image->width(), image->height(),
+ image->colorType() == kBGRA_8888_SkColorType
+ ? kRGBA_8888_SkColorType
+ : image->colorType(),
+ image->alphaType(),
+ image->refColorSpace());
+
+ PromiseImageInfo& newImageInfo = fImageInfo.emplace_back(fImageInfo.count(),
+ image->uniqueID(),
+ overallII);
+
+ SkYUVASizeInfo yuvaSizeInfo;
+ SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount];
+ SkYUVColorSpace yuvColorSpace;
+ const void* planes[SkYUVASizeInfo::kMaxCount];
+ sk_sp<SkCachedData> yuvData = ib->getPlanes(&yuvaSizeInfo, yuvaIndices, &yuvColorSpace, planes);
+ if (yuvData) {
+ newImageInfo.setYUVData(std::move(yuvData), yuvaIndices, yuvColorSpace);
+
+ // determine colortypes from index data
+ // for testing we only ever use A8, RG_88
+ SkColorType colorTypes[SkYUVASizeInfo::kMaxCount] = {
+ kUnknown_SkColorType, kUnknown_SkColorType,
+ kUnknown_SkColorType, kUnknown_SkColorType
+ };
+ for (int yuvIndex = 0; yuvIndex < SkYUVAIndex::kIndexCount; ++yuvIndex) {
+ int texIdx = yuvaIndices[yuvIndex].fIndex;
+ if (texIdx < 0) {
+ SkASSERT(SkYUVAIndex::kA_Index == yuvIndex);
+ continue;
+ }
+ if (kUnknown_SkColorType == colorTypes[texIdx]) {
+ colorTypes[texIdx] = kAlpha_8_SkColorType;
+ } else {
+ colorTypes[texIdx] = kR8G8_unorm_SkColorType;
+ }
+ }
+
+ for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
+ if (yuvaSizeInfo.fSizes[i].isEmpty()) {
+ SkASSERT(!yuvaSizeInfo.fWidthBytes[i] && kUnknown_SkColorType == colorTypes[i]);
+ continue;
+ }
+
+ SkImageInfo planeII = SkImageInfo::Make(yuvaSizeInfo.fSizes[i].fWidth,
+ yuvaSizeInfo.fSizes[i].fHeight,
+ colorTypes[i],
+ kUnpremul_SkAlphaType);
+ newImageInfo.addYUVPlane(i, planeII, planes[i], yuvaSizeInfo.fWidthBytes[i]);
+ }
+ } else {
+ sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
+
+ SkBitmap tmp;
+ tmp.allocPixels(overallII);
+
+ if (!rasterImage->readPixels(tmp.pixmap(), 0, 0)) {
+ return -1;
+ }
+
+ tmp.setImmutable();
+ newImageInfo.setNormalBitmap(tmp);
+ }
+ // In either case newImageInfo's PromiseImageCallbackContext is filled in by uploadAllToGPU
+
+ return fImageInfo.count()-1;
+}
+
+int DDLPromiseImageHelper::findOrDefineImage(SkImage* image) {
+ int preExistingID = this->findImage(image);
+ if (preExistingID >= 0) {
+ SkASSERT(this->isValidID(preExistingID));
+ return preExistingID;
+ }
+
+ int newID = this->addImage(image);
+ SkASSERT(this->isValidID(newID));
+ return newID;
+}
diff --git a/src/third_party/skia/tools/DDLPromiseImageHelper.h b/src/third_party/skia/tools/DDLPromiseImageHelper.h
new file mode 100644
index 0000000..99d883e
--- /dev/null
+++ b/src/third_party/skia/tools/DDLPromiseImageHelper.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef PromiseImageHelper_DEFINED
+#define PromiseImageHelper_DEFINED
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkDeferredDisplayListRecorder.h"
+#include "include/core/SkPromiseImageTexture.h"
+#include "include/core/SkYUVAIndex.h"
+#include "include/core/SkYUVASizeInfo.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/private/SkTArray.h"
+#include "src/core/SkCachedData.h"
+#include "src/core/SkTLazy.h"
+
+class GrContext;
+class SkImage;
+class SkPicture;
+struct SkYUVAIndex;
+
+// This class consolidates tracking & extraction of the original image data from an skp,
+// the upload of said data to the GPU and the fulfillment of promise images.
+//
+// The way this works is:
+// the original skp is converted to SkData and all its image info is extracted into this
+// class and only indices into this class are left in the SkData (via deflateSKP)
+//
+// Prior to replaying in threads, all the images stored in this class are uploaded to the
+// gpu and PromiseImageCallbackContexts are created for them (via uploadAllToGPU)
+//
+// Each thread reinflates the SkData into an SkPicture replacing all the indices w/
+// promise images (all using the same GrBackendTexture and getting a ref to the
+// appropriate PromiseImageCallbackContext) (via reinflateSKP).
+//
+// This class is then reset - dropping all of its refs on the PromiseImageCallbackContexts
+//
+// Each done callback unrefs its PromiseImageCallbackContext so, once all the promise images
+// are done, the PromiseImageCallbackContext is freed and its GrBackendTexture removed
+// from VRAM
+//
+// Note: if DDLs are going to be replayed multiple times, the reset call can be delayed until
+// all the replaying is complete. This will pin the GrBackendTextures in VRAM.
+class DDLPromiseImageHelper {
+public:
+ DDLPromiseImageHelper() = default;
+ ~DDLPromiseImageHelper() = default;
+
+ // Convert the SkPicture into SkData replacing all the SkImages with an index.
+ sk_sp<SkData> deflateSKP(const SkPicture* inputPicture);
+
+ void uploadAllToGPU(GrContext* context);
+
+ // reinflate a deflated SKP, replacing all the indices with promise images.
+ sk_sp<SkPicture> reinflateSKP(SkDeferredDisplayListRecorder*,
+ SkData* compressedPicture,
+ SkTArray<sk_sp<SkImage>>* promiseImages) const;
+
+ // Remove this class' refs on the PromiseImageCallbackContexts
+ void reset() { fImageInfo.reset(); }
+
+private:
+ // This class acts as a proxy for a GrBackendTexture that is part of an image.
+ // Whenever a promise image is created for the image, the promise image receives a ref to
+ // potentially several of these objects. Once all the promise images receive their done
+ // callbacks this object is deleted - removing the GrBackendTexture from VRAM.
+ // Note that while the DDLs are being created in the threads, the PromiseImageHelper holds
+ // a ref on all the PromiseImageCallbackContexts. However, once all the threads are done
+ // it drops all of its refs (via "reset").
+ class PromiseImageCallbackContext : public SkRefCnt {
+ public:
+ PromiseImageCallbackContext(GrContext* context) : fContext(context) {}
+
+ ~PromiseImageCallbackContext();
+
+ void setBackendTexture(const GrBackendTexture& backendTexture);
+
+ sk_sp<SkPromiseImageTexture> fulfill() {
+ SkASSERT(fPromiseImageTexture);
+ SkASSERT(fUnreleasedFulfills >= 0);
+ ++fUnreleasedFulfills;
+ ++fTotalFulfills;
+ return fPromiseImageTexture;
+ }
+
+ void release() {
+ SkASSERT(fUnreleasedFulfills > 0);
+ --fUnreleasedFulfills;
+ ++fTotalReleases;
+ }
+
+ void done() {
+ ++fDoneCnt;
+ SkASSERT(fDoneCnt <= fNumImages);
+ }
+
+ void wasAddedToImage() { fNumImages++; }
+
+ const SkPromiseImageTexture* promiseImageTexture() const {
+ return fPromiseImageTexture.get();
+ }
+
+ private:
+ GrContext* fContext;
+ sk_sp<SkPromiseImageTexture> fPromiseImageTexture;
+ int fNumImages = 0;
+ int fTotalFulfills = 0;
+ int fTotalReleases = 0;
+ int fUnreleasedFulfills = 0;
+ int fDoneCnt = 0;
+
+ typedef SkRefCnt INHERITED;
+ };
+
+ // This is the information extracted into this class from the parsing of the skp file.
+ // Once it has all been uploaded to the GPU and distributed to the promise images, it
+ // is all dropped via "reset".
+ class PromiseImageInfo {
+ public:
+ PromiseImageInfo(int index, uint32_t originalUniqueID, const SkImageInfo& ii)
+ : fIndex(index)
+ , fOriginalUniqueID(originalUniqueID)
+ , fImageInfo(ii) {
+ }
+ ~PromiseImageInfo() {}
+
+ int index() const { return fIndex; }
+ uint32_t originalUniqueID() const { return fOriginalUniqueID; }
+ bool isYUV() const { return SkToBool(fYUVData.get()); }
+
+ int overallWidth() const { return fImageInfo.width(); }
+ int overallHeight() const { return fImageInfo.height(); }
+ SkColorType overallColorType() const { return fImageInfo.colorType(); }
+ SkAlphaType overallAlphaType() const { return fImageInfo.alphaType(); }
+ sk_sp<SkColorSpace> refOverallColorSpace() const { return fImageInfo.refColorSpace(); }
+
+ SkYUVColorSpace yuvColorSpace() const {
+ SkASSERT(this->isYUV());
+ return fYUVColorSpace;
+ }
+ const SkYUVAIndex* yuvaIndices() const {
+ SkASSERT(this->isYUV());
+ return fYUVAIndices;
+ }
+ const SkPixmap& yuvPixmap(int index) const {
+ SkASSERT(this->isYUV());
+ SkASSERT(index >= 0 && index < SkYUVASizeInfo::kMaxCount);
+ return fYUVPlanes[index];
+ }
+ const SkBitmap& normalBitmap() const {
+ SkASSERT(!this->isYUV());
+ return fBitmap;
+ }
+
+ void setCallbackContext(int index, sk_sp<PromiseImageCallbackContext> callbackContext) {
+ SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVASizeInfo::kMaxCount : 1));
+ fCallbackContexts[index] = callbackContext;
+ }
+ PromiseImageCallbackContext* callbackContext(int index) const {
+ SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVASizeInfo::kMaxCount : 1));
+ return fCallbackContexts[index].get();
+ }
+ sk_sp<PromiseImageCallbackContext> refCallbackContext(int index) const {
+ SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVASizeInfo::kMaxCount : 1));
+ return fCallbackContexts[index];
+ }
+
+ const SkPromiseImageTexture* promiseTexture(int index) const {
+ SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVASizeInfo::kMaxCount : 1));
+ return fCallbackContexts[index]->promiseImageTexture();
+ }
+
+ void setNormalBitmap(const SkBitmap& bm) { fBitmap = bm; }
+
+ void setYUVData(sk_sp<SkCachedData> yuvData,
+ SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
+ SkYUVColorSpace cs) {
+ fYUVData = yuvData;
+ memcpy(fYUVAIndices, yuvaIndices, sizeof(fYUVAIndices));
+ fYUVColorSpace = cs;
+ }
+ void addYUVPlane(int index, const SkImageInfo& ii, const void* plane, size_t widthBytes) {
+ SkASSERT(this->isYUV());
+ SkASSERT(index >= 0 && index < SkYUVASizeInfo::kMaxCount);
+ fYUVPlanes[index].reset(ii, plane, widthBytes);
+ }
+
+ private:
+ const int fIndex; // index in the 'fImageInfo' array
+ const uint32_t fOriginalUniqueID; // original ID for deduping
+
+ const SkImageInfo fImageInfo; // info for the overarching image
+
+ // CPU-side cache of a normal SkImage's contents
+ SkBitmap fBitmap;
+
+ // CPU-side cache of a YUV SkImage's contents
+ sk_sp<SkCachedData> fYUVData; // when !null, this is a YUV image
+ SkYUVColorSpace fYUVColorSpace = kJPEG_SkYUVColorSpace;
+ SkYUVAIndex fYUVAIndices[SkYUVAIndex::kIndexCount];
+ SkPixmap fYUVPlanes[SkYUVASizeInfo::kMaxCount];
+
+ // Up to SkYUVASizeInfo::kMaxCount for a YUVA image. Only one for a normal image.
+ sk_sp<PromiseImageCallbackContext> fCallbackContexts[SkYUVASizeInfo::kMaxCount];
+ };
+
+ // This stack-based context allows each thread to re-inflate the image indices into
+ // promise images while still using the same GrBackendTexture.
+ struct PerRecorderContext {
+ SkDeferredDisplayListRecorder* fRecorder;
+ const DDLPromiseImageHelper* fHelper;
+ SkTArray<sk_sp<SkImage>>* fPromiseImages;
+ };
+
+ static sk_sp<SkPromiseImageTexture> PromiseImageFulfillProc(void* textureContext) {
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ return callbackContext->fulfill();
+ }
+
+ static void PromiseImageReleaseProc(void* textureContext) {
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ callbackContext->release();
+ }
+
+ static void PromiseImageDoneProc(void* textureContext) {
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ callbackContext->done();
+ callbackContext->unref();
+ }
+
+ static sk_sp<SkImage> PromiseImageCreator(const void* rawData, size_t length, void* ctxIn);
+
+ bool isValidID(int id) const { return id >= 0 && id < fImageInfo.count(); }
+ const PromiseImageInfo& getInfo(int id) const { return fImageInfo[id]; }
+ void uploadImage(GrContext*, PromiseImageInfo*);
+
+ // returns -1 if not found
+ int findImage(SkImage* image) const;
+
+ // returns -1 on failure
+ int addImage(SkImage* image);
+
+ // returns -1 on failure
+ int findOrDefineImage(SkImage* image);
+
+ SkTArray<PromiseImageInfo> fImageInfo;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/DDLTileHelper.cpp b/src/third_party/skia/tools/DDLTileHelper.cpp
new file mode 100644
index 0000000..eb50f4e
--- /dev/null
+++ b/src/third_party/skia/tools/DDLTileHelper.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/DDLTileHelper.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkDeferredDisplayListRecorder.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkSurfaceCharacterization.h"
+#include "src/core/SkDeferredDisplayListPriv.h"
+#include "src/core/SkTaskGroup.h"
+#include "src/image/SkImage_Gpu.h"
+#include "tools/DDLPromiseImageHelper.h"
+
+DDLTileHelper::TileData::TileData(sk_sp<SkSurface> s, const SkIRect& clip)
+ : fSurface(std::move(s))
+ , fClip(clip) {
+ SkAssertResult(fSurface->characterize(&fCharacterization));
+}
+
+void DDLTileHelper::TileData::createTileSpecificSKP(SkData* compressedPictureData,
+ const DDLPromiseImageHelper& helper) {
+ SkASSERT(!fReconstitutedPicture);
+
+ // This is bending the DDLRecorder contract! The promise images in the SKP should be
+ // created by the same recorder used to create the matching DDL.
+ SkDeferredDisplayListRecorder recorder(fCharacterization);
+
+ fReconstitutedPicture = helper.reinflateSKP(&recorder, compressedPictureData, &fPromiseImages);
+
+ std::unique_ptr<SkDeferredDisplayList> ddl = recorder.detach();
+ if (ddl->priv().numRenderTasks()) {
+ // TODO: remove this once skbug.com/8424 is fixed. If the DDL resulting from the
+ // reinflation of the SKPs contains opsTasks that means some image subset operation
+ // created a draw.
+ fReconstitutedPicture.reset();
+ }
+}
+
+void DDLTileHelper::TileData::createDDL() {
+ SkASSERT(!fDisplayList);
+
+ SkDeferredDisplayListRecorder recorder(fCharacterization);
+
+ // DDL TODO: the DDLRecorder's GrContext isn't initialized until getCanvas is called.
+ // Maybe set it up in the ctor?
+ SkCanvas* subCanvas = recorder.getCanvas();
+
+ // Because we cheated in createTileSpecificSKP and used the wrong DDLRecorder, the GrContext's
+ // stored in fReconstitutedPicture's promise images are incorrect. Patch them with the correct
+ // one now.
+ for (int i = 0; i < fPromiseImages.count(); ++i) {
+ GrContext* newContext = subCanvas->getGrContext();
+
+ if (fPromiseImages[i]->isTextureBacked()) {
+ SkImage_GpuBase* gpuImage = (SkImage_GpuBase*) fPromiseImages[i].get();
+ gpuImage->resetContext(sk_ref_sp(newContext));
+ }
+ }
+
+ subCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
+ subCanvas->translate(-fClip.fLeft, -fClip.fTop);
+
+ // Note: in this use case we only render a picture to the deferred canvas
+ // but, more generally, clients will use arbitrary draw calls.
+ if (fReconstitutedPicture) {
+ subCanvas->drawPicture(fReconstitutedPicture);
+ }
+
+ fDisplayList = recorder.detach();
+}
+
+void DDLTileHelper::TileData::draw() {
+ SkASSERT(fDisplayList);
+
+ fSurface->draw(fDisplayList.get());
+}
+
+void DDLTileHelper::TileData::compose(SkCanvas* dst) {
+ sk_sp<SkImage> img = fSurface->makeImageSnapshot();
+ dst->save();
+ dst->clipRect(SkRect::Make(fClip));
+ dst->drawImage(std::move(img), fClip.fLeft, fClip.fTop);
+ dst->restore();
+}
+
+void DDLTileHelper::TileData::reset() {
+ // TODO: when DDLs are re-renderable we don't need to do this
+ fDisplayList = nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DDLTileHelper::DDLTileHelper(SkCanvas* canvas, const SkIRect& viewport, int numDivisions)
+ : fNumDivisions(numDivisions) {
+ SkASSERT(fNumDivisions > 0);
+ fTiles.reserve(fNumDivisions*fNumDivisions);
+
+ int xTileSize = viewport.width()/fNumDivisions;
+ int yTileSize = viewport.height()/fNumDivisions;
+
+ // Create the destination tiles
+ for (int y = 0, yOff = 0; y < fNumDivisions; ++y, yOff += yTileSize) {
+ int ySize = (y < fNumDivisions-1) ? yTileSize : viewport.height()-yOff;
+
+ for (int x = 0, xOff = 0; x < fNumDivisions; ++x, xOff += xTileSize) {
+ int xSize = (x < fNumDivisions-1) ? xTileSize : viewport.width()-xOff;
+
+ SkIRect clip = SkIRect::MakeXYWH(xOff, yOff, xSize, ySize);
+
+ SkASSERT(viewport.contains(clip));
+
+ SkImageInfo tileII = SkImageInfo::MakeN32Premul(xSize, ySize);
+
+ sk_sp<SkSurface> tileSurface = canvas->makeSurface(tileII);
+
+ // TODO: this is here to deal w/ a resource allocator bug (skbug.com/8007). If all
+ // the DDLs are flushed at the same time (w/o the composition draws) the allocator
+ // feels free to reuse the backing GrSurfaces!
+ tileSurface->flush();
+
+ fTiles.push_back(TileData(std::move(tileSurface), clip));
+ }
+ }
+}
+
+void DDLTileHelper::createSKPPerTile(SkData* compressedPictureData,
+ const DDLPromiseImageHelper& helper) {
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i].createTileSpecificSKP(compressedPictureData, helper);
+ }
+}
+
+void DDLTileHelper::createDDLsInParallel() {
+#if 1
+ SkTaskGroup().batch(fTiles.count(), [&](int i) { fTiles[i].createDDL(); });
+ SkTaskGroup().wait();
+#else
+ // Use this code path to debug w/o threads
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i].createDDL();
+ }
+#endif
+
+}
+
+void DDLTileHelper::drawAllTilesAndFlush(GrContext* context, bool flush) {
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i].draw();
+ }
+ if (flush) {
+ context->flush();
+ }
+}
+
+void DDLTileHelper::composeAllTiles(SkCanvas* dstCanvas) {
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i].compose(dstCanvas);
+ }
+}
+
+void DDLTileHelper::resetAllTiles() {
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i].reset();
+ }
+}
diff --git a/src/third_party/skia/tools/DDLTileHelper.h b/src/third_party/skia/tools/DDLTileHelper.h
new file mode 100644
index 0000000..f7f45c0
--- /dev/null
+++ b/src/third_party/skia/tools/DDLTileHelper.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef DDLTileHelper_DEFINED
+#define DDLTileHelper_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceCharacterization.h"
+
+class DDLPromiseImageHelper;
+class SkCanvas;
+class SkData;
+class SkDeferredDisplayList;
+class SkPicture;
+class SkSurface;
+class SkSurfaceCharacterization;
+
+class DDLTileHelper {
+public:
+ // TileData class encapsulates the information and behavior for a single tile/thread in
+ // a DDL rendering.
+ class TileData {
+ public:
+ TileData(sk_sp<SkSurface>, const SkIRect& clip);
+
+ // This method can be invoked in parallel
+ // In each thread we will reconvert the compressedPictureData into an SkPicture
+ // replacing each image-index with a promise image.
+ void createTileSpecificSKP(SkData* compressedPictureData,
+ const DDLPromiseImageHelper& helper);
+
+ // This method can be invoked in parallel
+ // Create the per-tile DDL from the per-tile SKP
+ void createDDL();
+
+ // This method operates serially and replays the recorded DDL into the tile surface.
+ void draw();
+
+ // This method also operates serially and composes the results of replaying the DDL into
+ // the final destination surface.
+ void compose(SkCanvas* dst);
+
+ void reset();
+
+ private:
+ sk_sp<SkSurface> fSurface;
+ SkSurfaceCharacterization fCharacterization;
+ SkIRect fClip; // in the device space of the dest canvas
+ sk_sp<SkPicture> fReconstitutedPicture;
+ SkTArray<sk_sp<SkImage>> fPromiseImages; // All the promise images in the
+ // reconstituted picture
+ std::unique_ptr<SkDeferredDisplayList> fDisplayList;
+ };
+
+ DDLTileHelper(SkCanvas* canvas, const SkIRect& viewport, int numDivisions);
+
+ void createSKPPerTile(SkData* compressedPictureData, const DDLPromiseImageHelper& helper);
+
+ void createDDLsInParallel();
+
+ void drawAllTilesAndFlush(GrContext*, bool flush);
+
+ void composeAllTiles(SkCanvas* dstCanvas);
+
+ void resetAllTiles();
+
+private:
+ int fNumDivisions; // number of tiles along a side
+ SkTArray<TileData> fTiles;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/DumpRecord.cpp b/src/third_party/skia/tools/DumpRecord.cpp
index e9374fd..fb2fbb0 100644
--- a/src/third_party/skia/tools/DumpRecord.cpp
+++ b/src/third_party/skia/tools/DumpRecord.cpp
@@ -7,11 +7,12 @@
#include <stdio.h>
-#include "SkRecord.h"
-#include "SkRecordDraw.h"
+#include "src/core/SkPicturePriv.h"
+#include "src/core/SkRecord.h"
+#include "src/core/SkRecordDraw.h"
-#include "DumpRecord.h"
-#include "SkTime.h"
+#include "include/core/SkTime.h"
+#include "tools/DumpRecord.h"
namespace {
@@ -63,7 +64,7 @@
void print(const SkRecords::DrawPicture& command, double ns) {
this->printNameAndTime(command, ns);
- if (auto bp = command.picture->asSkBigPicture()) {
+ if (auto bp = SkPicturePriv::AsSkBigPicture(command.picture)) {
++fIndent;
const SkRecord& record = *bp->record();
@@ -114,8 +115,8 @@
template <typename T>
static const char* NameOf(const T&) {
#define CASE(U) case SkRecords::U##_Type: return #U;
- switch(T::kType) { SK_RECORD_TYPES(CASE); }
- #undef CASE
+ switch (T::kType) { SK_RECORD_TYPES(CASE) }
+#undef CASE
SkDEBUGFAIL("Unknown T");
return "Unknown T";
}
diff --git a/src/third_party/skia/tools/HashAndEncode.cpp b/src/third_party/skia/tools/HashAndEncode.cpp
new file mode 100644
index 0000000..76d4b76
--- /dev/null
+++ b/src/third_party/skia/tools/HashAndEncode.cpp
@@ -0,0 +1,163 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "include/core/SkICC.h"
+#include "include/core/SkString.h"
+#include "tools/HashAndEncode.h"
+#include "png.h"
+
+static sk_sp<SkColorSpace> rec2020() {
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020);
+}
+
+HashAndEncode::HashAndEncode(const SkBitmap& bitmap) : fSize(bitmap.info().dimensions()) {
+ skcms_AlphaFormat srcAlpha;
+ switch (bitmap.alphaType()) {
+ case kUnknown_SkAlphaType: return;
+
+ case kOpaque_SkAlphaType:
+ case kUnpremul_SkAlphaType: srcAlpha = skcms_AlphaFormat_Unpremul; break;
+ case kPremul_SkAlphaType: srcAlpha = skcms_AlphaFormat_PremulAsEncoded; break;
+ }
+
+ skcms_PixelFormat srcFmt;
+ switch (bitmap.colorType()) {
+ case kUnknown_SkColorType: return;
+
+ case kAlpha_8_SkColorType: srcFmt = skcms_PixelFormat_A_8; break;
+ case kRGB_565_SkColorType: srcFmt = skcms_PixelFormat_BGR_565; break;
+ case kARGB_4444_SkColorType: srcFmt = skcms_PixelFormat_ABGR_4444; break;
+ case kRGBA_8888_SkColorType: srcFmt = skcms_PixelFormat_RGBA_8888; break;
+ case kBGRA_8888_SkColorType: srcFmt = skcms_PixelFormat_BGRA_8888; break;
+ case kRGBA_1010102_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102; break;
+ case kGray_8_SkColorType: srcFmt = skcms_PixelFormat_G_8; break;
+ case kRGBA_F16Norm_SkColorType: srcFmt = skcms_PixelFormat_RGBA_hhhh; break;
+ case kRGBA_F16_SkColorType: srcFmt = skcms_PixelFormat_RGBA_hhhh; break;
+ case kRGBA_F32_SkColorType: srcFmt = skcms_PixelFormat_RGBA_ffff; break;
+
+ case kRGB_888x_SkColorType: srcFmt = skcms_PixelFormat_RGBA_8888;
+ srcAlpha = skcms_AlphaFormat_Opaque; break;
+ case kRGB_101010x_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102;
+ srcAlpha = skcms_AlphaFormat_Opaque; break;
+ case kR8G8_unorm_SkColorType: return;
+ case kR16G16_unorm_SkColorType: return;
+ case kR16G16_float_SkColorType: return;
+ case kA16_unorm_SkColorType: return;
+ case kA16_float_SkColorType: return;
+ case kR16G16B16A16_unorm_SkColorType: return;
+ }
+
+ skcms_ICCProfile srcProfile = *skcms_sRGB_profile();
+ if (auto cs = bitmap.colorSpace()) {
+ cs->toProfile(&srcProfile);
+ }
+
+ // Our common format that can represent anything we draw and encode as a PNG:
+ // - 16-bit big-endian RGBA
+ // - unpremul
+ // - Rec. 2020 gamut and transfer function
+ skcms_PixelFormat dstFmt = skcms_PixelFormat_RGBA_16161616BE;
+ skcms_AlphaFormat dstAlpha = skcms_AlphaFormat_Unpremul;
+ skcms_ICCProfile dstProfile;
+ rec2020()->toProfile(&dstProfile);
+
+ int N = fSize.width() * fSize.height();
+ fPixels.reset(new uint64_t[N]);
+
+ if (!skcms_Transform(bitmap.getPixels(), srcFmt, srcAlpha, &srcProfile,
+ fPixels.get(), dstFmt, dstAlpha, &dstProfile, N)) {
+ SkASSERT(false);
+ fPixels.reset(nullptr);
+ }
+}
+
+void HashAndEncode::write(SkWStream* st) const {
+ st->write(&fSize, sizeof(fSize));
+ if (const uint64_t* px = fPixels.get()) {
+ st->write(px, sizeof(*px) * fSize.width() * fSize.height());
+ }
+
+ // N.B. changing salt will change the hash of all images produced by DM,
+ // and will cause tens of thousands of new images to be uploaded to Gold.
+ int salt = 1;
+ st->write(&salt, sizeof(salt));
+}
+
+bool HashAndEncode::writePngTo(const char* path,
+ const char* md5,
+ CommandLineFlags::StringArray key,
+ CommandLineFlags::StringArray properties) const {
+ if (!fPixels) {
+ return false;
+ }
+
+ FILE* f = fopen(path, "wb");
+ if (!f) {
+ return false;
+ }
+
+ png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
+ if (!png) {
+ fclose(f);
+ return false;
+ }
+
+ png_infop info = png_create_info_struct(png);
+ if (!info) {
+ png_destroy_write_struct(&png, &info);
+ fclose(f);
+ return false;
+ }
+
+ SkString description;
+ description.append("Key: ");
+ for (int i = 0; i < key.count(); i++) {
+ description.appendf("%s ", key[i]);
+ }
+ description.append("Properties: ");
+ for (int i = 0; i < properties.count(); i++) {
+ description.appendf("%s ", properties[i]);
+ }
+ description.appendf("MD5: %s", md5);
+
+ png_text text[2];
+ text[0].key = (png_charp)"Author";
+ text[0].text = (png_charp)"DM unified Rec.2020";
+ text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ text[1].key = (png_charp)"Description";
+ text[1].text = (png_charp)description.c_str();
+ text[1].compression = PNG_TEXT_COMPRESSION_NONE;
+ png_set_text(png, info, text, SK_ARRAY_COUNT(text));
+
+ png_init_io(png, f);
+ png_set_IHDR(png, info, (png_uint_32)fSize.width()
+ , (png_uint_32)fSize.height()
+ , 16/*bits per channel*/
+ , PNG_COLOR_TYPE_RGB_ALPHA
+ , PNG_INTERLACE_NONE
+ , PNG_COMPRESSION_TYPE_DEFAULT
+ , PNG_FILTER_TYPE_DEFAULT);
+
+ // Fastest encoding and decoding, at slight file size cost is no filtering, compression 1.
+ png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
+ png_set_compression_level(png, 1);
+
+ static const sk_sp<SkData> profile =
+ SkWriteICCProfile(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020);
+ png_set_iCCP(png, info,
+ "Rec.2020",
+ 0/*compression type... no idea what options are available here*/,
+ (png_const_bytep)profile->data(),
+ (png_uint_32) profile->size());
+
+ png_write_info(png, info);
+ for (int y = 0; y < fSize.height(); y++) {
+ png_write_row(png, (png_bytep)(fPixels.get() + y*fSize.width()));
+ }
+ png_write_end(png, info);
+
+ png_destroy_write_struct(&png, &info);
+ fclose(f);
+ return true;
+}
+
diff --git a/src/third_party/skia/tools/HashAndEncode.h b/src/third_party/skia/tools/HashAndEncode.h
new file mode 100644
index 0000000..0447fc4
--- /dev/null
+++ b/src/third_party/skia/tools/HashAndEncode.h
@@ -0,0 +1,25 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkStream.h"
+#include "tools/flags/CommandLineFlags.h"
+
+class HashAndEncode {
+public:
+ explicit HashAndEncode(const SkBitmap&);
+
+ void write(SkWStream*) const;
+
+ bool writePngTo(const char* path,
+ const char* md5,
+ CommandLineFlags::StringArray key,
+ CommandLineFlags::StringArray properties) const;
+
+private:
+ const SkISize fSize;
+ std::unique_ptr<uint64_t[]> fPixels;
+};
+
diff --git a/src/third_party/skia/tools/LsanSuppressions.cpp b/src/third_party/skia/tools/LsanSuppressions.cpp
index c81184f..4da984b 100644
--- a/src/third_party/skia/tools/LsanSuppressions.cpp
+++ b/src/third_party/skia/tools/LsanSuppressions.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
#if !defined(__has_feature)
#define __has_feature(x) 0
@@ -17,9 +17,10 @@
const char* __lsan_default_suppressions();
const char* __lsan_default_suppressions() {
- return "leak:libfontconfig\n" // FontConfig looks like it leaks, but it doesn't.
- "leak:libGL.so\n" // For NVidia driver.
- "leak:__strdup\n" // An eternal mystery, skia:2916.
+ return "leak:libfontconfig\n" // FontConfig looks like it leaks, but it doesn't.
+ "leak:libGLX_nvidia.so\n" // For NVidia driver.
+ "leak:libnvidia-glcore.so\n" // For NVidia driver.
+ "leak:libnvidia-tls.so\n" // For NVidia driver.
;
}
diff --git a/src/third_party/skia/tools/OverwriteLine.h b/src/third_party/skia/tools/OverwriteLine.h
index e8f0504..8985a6a 100644
--- a/src/third_party/skia/tools/OverwriteLine.h
+++ b/src/third_party/skia/tools/OverwriteLine.h
@@ -3,7 +3,7 @@
// Print this string to reset and clear your current terminal line.
static const char* kSkOverwriteLine =
-#ifdef SK_BUILD_FOR_WIN32
+#ifdef SK_BUILD_FOR_WIN
"\r \r"
#elif defined(SK_BUILD_FOR_IOS)
"\r"
diff --git a/src/third_party/skia/tools/ProcStats.cpp b/src/third_party/skia/tools/ProcStats.cpp
index 51ddf55..b9eae31 100644
--- a/src/third_party/skia/tools/ProcStats.cpp
+++ b/src/third_party/skia/tools/ProcStats.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#include "ProcStats.h"
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
+#include "tools/ProcStats.h"
#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) || defined(SK_BUILD_FOR_ANDROID)
#include <sys/resource.h>
@@ -19,7 +19,7 @@
return static_cast<int>(ru.ru_maxrss / 1024); // Linux reports kilobytes.
#endif
}
-#elif defined(SK_BUILD_FOR_WIN32)
+#elif defined(SK_BUILD_FOR_WIN)
#include <windows.h>
#include <psapi.h>
int sk_tools::getMaxResidentSetSizeMB() {
@@ -59,7 +59,7 @@
return rssPages * pageSize / 1024 / 1024;
}
-#elif defined(SK_BUILD_FOR_WIN32)
+#elif defined(SK_BUILD_FOR_WIN)
int sk_tools::getCurrResidentSetSizeMB() {
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
diff --git a/src/third_party/skia/tools/Registry.h b/src/third_party/skia/tools/Registry.h
index 6a1e24a..d5731a7 100644
--- a/src/third_party/skia/tools/Registry.h
+++ b/src/third_party/skia/tools/Registry.h
@@ -8,7 +8,8 @@
#ifndef sk_tools_Registry_DEFINED
#define sk_tools_Registry_DEFINED
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkNoncopyable.h"
namespace sk_tools {
@@ -18,9 +19,7 @@
*/
template <typename T> class Registry : SkNoncopyable {
public:
- typedef T Factory;
-
- explicit Registry(T fact) : fFact(fact) {
+ explicit Registry(T value) : fValue(value) {
#ifdef SK_BUILD_FOR_ANDROID
// work-around for double-initialization bug
{
@@ -40,10 +39,22 @@
static const Registry* Head() { return gHead; }
const Registry* next() const { return fChain; }
- const Factory& factory() const { return fFact; }
+ const T& get() const { return fValue; }
+
+ // for (const T& t : sk_tools::Registry<T>::Range()) { process(t); }
+ struct Range {
+ struct Iterator {
+ const Registry* fPtr;
+ const T& operator*() { return SkASSERT(fPtr), fPtr->get(); }
+ void operator++() { if (fPtr) { fPtr = fPtr->next(); } }
+ bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; }
+ };
+ Iterator begin() const { return Iterator{Registry::Head()}; }
+ Iterator end() const { return Iterator{nullptr}; }
+ };
private:
- Factory fFact;
+ T fValue;
Registry* fChain;
static Registry* gHead;
diff --git a/src/third_party/skia/tools/ResourceFactory.h b/src/third_party/skia/tools/ResourceFactory.h
new file mode 100644
index 0000000..542989e
--- /dev/null
+++ b/src/third_party/skia/tools/ResourceFactory.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef ResourceFactory_DEFINED
+#define ResourceFactory_DEFINED
+
+#include "include/core/SkData.h"
+
+extern sk_sp<SkData> (*gResourceFactory)(const char*);
+
+#endif // ResourceFactory_DEFINED
diff --git a/src/third_party/skia/tools/Resources.cpp b/src/third_party/skia/tools/Resources.cpp
index f93cf24..89f857e 100644
--- a/src/third_party/skia/tools/Resources.cpp
+++ b/src/third_party/skia/tools/Resources.cpp
@@ -5,18 +5,22 @@
* found in the LICENSE file.
*/
-#include "Resources.h"
-#include "SkBitmap.h"
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkImage.h"
-#include "SkImageGenerator.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkStream.h"
-#include "SkTypeface.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageGenerator.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypeface.h"
+#include "src/core/SkOSFile.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/ResourceFactory.h"
+#include "tools/Resources.h"
+#include "tools/flags/CommandLineFlags.h"
-DEFINE_string2(resourcePath, i, "resources", "Directory with test resources: images, fonts, etc.");
+static DEFINE_string2(resourcePath, i, "resources",
+ "Directory with test resources: images, fonts, etc.");
+
+sk_sp<SkData> (*gResourceFactory)(const char*) = nullptr;
SkString GetResourcePath(const char* resource) {
return SkOSPath::Join(FLAGS_resourcePath[0], resource);
@@ -26,43 +30,31 @@
FLAGS_resourcePath.set(0, resource);
}
-bool GetResourceAsBitmap(const char* resource, SkBitmap* dst) {
- SkString resourcePath = GetResourcePath(resource);
- sk_sp<SkData> resourceData(SkData::MakeFromFileName(resourcePath.c_str()));
- std::unique_ptr<SkImageGenerator> gen(SkImageGenerator::MakeFromEncoded(resourceData));
- if (!gen) {
- return false;
- }
- return dst->tryAllocPixels(gen->getInfo()) &&
- gen->getPixels(gen->getInfo().makeColorSpace(nullptr), dst->getPixels(), dst->rowBytes(),
- nullptr);
+bool DecodeDataToBitmap(sk_sp<SkData> data, SkBitmap* dst) {
+ std::unique_ptr<SkImageGenerator> gen(SkImageGenerator::MakeFromEncoded(std::move(data)));
+ return gen && dst->tryAllocPixels(gen->getInfo()) &&
+ gen->getPixels(gen->getInfo().makeColorSpace(nullptr), dst->getPixels(), dst->rowBytes());
}
-sk_sp<SkImage> GetResourceAsImage(const char* resource) {
- SkString path = GetResourcePath(resource);
- sk_sp<SkData> resourceData(SkData::MakeFromFileName(path.c_str()));
- return SkImage::MakeFromEncoded(resourceData);
-}
-
-SkStreamAsset* GetResourceAsStream(const char* resource) {
- SkString resourcePath = GetResourcePath(resource);
- std::unique_ptr<SkFILEStream> stream(new SkFILEStream(resourcePath.c_str()));
- if (!stream->isValid()) {
- SkDebugf("Resource %s not found.\n", resource);
- return nullptr;
- }
- return stream.release();
+std::unique_ptr<SkStreamAsset> GetResourceAsStream(const char* resource) {
+ auto data = GetResourceAsData(resource);
+ return data ? std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data)))
+ : nullptr;
}
sk_sp<SkData> GetResourceAsData(const char* resource) {
- SkString resourcePath = GetResourcePath(resource);
- return SkData::MakeFromFileName(resourcePath.c_str());
+ if (sk_sp<SkData> data = gResourceFactory
+ ? gResourceFactory(resource)
+ : SkData::MakeFromFileName(GetResourcePath(resource).c_str())) {
+ return data;
+ }
+ SkDebugf("Resource \"%s\" not found.\n", GetResourcePath(resource).c_str());
+ #ifdef SK_TOOLS_REQUIRE_RESOURCES
+ SK_ABORT("missing resource");
+ #endif
+ return nullptr;
}
-sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource) {
- std::unique_ptr<SkStreamAsset> stream(GetResourceAsStream(resource));
- if (!stream) {
- return nullptr;
- }
- return SkTypeface::MakeFromStream(stream.release());
+sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource, int ttcIndex) {
+ return SkTypeface::MakeFromStream(GetResourceAsStream(resource), ttcIndex);
}
diff --git a/src/third_party/skia/tools/Resources.h b/src/third_party/skia/tools/Resources.h
index fa1ca45..81bdd1b 100644
--- a/src/third_party/skia/tools/Resources.h
+++ b/src/third_party/skia/tools/Resources.h
@@ -8,22 +8,32 @@
#ifndef Resources_DEFINED
#define Resources_DEFINED
-#include "SkRefCnt.h"
-#include "SkString.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkString.h"
class SkBitmap;
class SkData;
-class SkImage;
class SkStreamAsset;
class SkTypeface;
SkString GetResourcePath(const char* resource = "");
+
void SetResourcePath(const char* );
-bool GetResourceAsBitmap(const char* resource, SkBitmap* dst);
-sk_sp<SkImage> GetResourceAsImage(const char* resource);
-SkStreamAsset* GetResourceAsStream(const char* resource);
+bool DecodeDataToBitmap(sk_sp<SkData> data, SkBitmap* dst);
+
sk_sp<SkData> GetResourceAsData(const char* resource);
-sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource);
+
+inline bool GetResourceAsBitmap(const char* resource, SkBitmap* dst) {
+ return DecodeDataToBitmap(GetResourceAsData(resource), dst);
+}
+
+inline sk_sp<SkImage> GetResourceAsImage(const char* resource) {
+ return SkImage::MakeFromEncoded(GetResourceAsData(resource));
+}
+
+std::unique_ptr<SkStreamAsset> GetResourceAsStream(const char* resource);
+
+sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource, int ttcIndex = 0);
#endif // Resources_DEFINED
diff --git a/src/third_party/skia/tools/SkJSONCPP.h b/src/third_party/skia/tools/SkJSONCPP.h
deleted file mode 100644
index 6baf223..0000000
--- a/src/third_party/skia/tools/SkJSONCPP.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * A common place to put the jsoncpp library includes, as opposed to littering
- * the pragmas repeatedly through our code.
- */
-#ifndef SkJSONCPP_DEFINED
-#define SkJSONCPP_DEFINED
-
-#ifdef GOOGLE3
- #include "third_party/jsoncpp/reader.h"
- #include "third_party/jsoncpp/value.h"
- #include "third_party/jsoncpp/writer.h"
-#else
- #ifdef SK_BUILD_FOR_WIN
- // json includes xlocale which generates warning 4530 because we're
- // compiling without exceptions;
- // see https://code.google.com/p/skia/issues/detail?id=1067
- #pragma warning(push)
- #pragma warning(disable : 4530)
- #endif
- #include "json/reader.h"
- #include "json/value.h"
- #include "json/writer.h"
- #ifdef SK_BUILD_FOR_WIN
- #pragma warning(pop)
- #endif
-#endif
-
-#endif // SkJSONCPP_DEFINED
diff --git a/src/third_party/skia/tools/SkMetaData.cpp b/src/third_party/skia/tools/SkMetaData.cpp
new file mode 100644
index 0000000..ede1921
--- /dev/null
+++ b/src/third_party/skia/tools/SkMetaData.cpp
@@ -0,0 +1,231 @@
+/*
+ * 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 "tools/SkMetaData.h"
+
+#include "include/private/SkMalloc.h"
+#include "include/private/SkTo.h"
+
+void SkMetaData::reset()
+{
+ Rec* rec = fRec;
+ while (rec) {
+ Rec* next = rec->fNext;
+ Rec::Free(rec);
+ rec = next;
+ }
+ fRec = nullptr;
+}
+
+void SkMetaData::setS32(const char name[], int32_t value)
+{
+ (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
+}
+
+void SkMetaData::setScalar(const char name[], SkScalar value)
+{
+ (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
+}
+
+SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
+{
+ SkASSERT(count > 0);
+ if (count > 0)
+ return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
+ return nullptr;
+}
+
+void SkMetaData::setPtr(const char name[], void* ptr) {
+ (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
+}
+
+void SkMetaData::setBool(const char name[], bool value)
+{
+ (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
+}
+
+void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
+{
+ SkASSERT(name);
+ SkASSERT(dataSize);
+ SkASSERT(count > 0);
+
+ (void)this->remove(name, type);
+
+ size_t len = strlen(name);
+ Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
+
+#ifndef SK_DEBUG
+ rec->fType = SkToU8(type);
+#else
+ rec->fType = type;
+#endif
+ rec->fDataLen = SkToU8(dataSize);
+ rec->fDataCount = SkToU16(count);
+ if (data)
+ memcpy(rec->data(), data, dataSize * count);
+ memcpy(rec->name(), name, len + 1);
+
+ rec->fNext = fRec;
+ fRec = rec;
+ return rec->data();
+}
+
+bool SkMetaData::findS32(const char name[], int32_t* value) const
+{
+ const Rec* rec = this->find(name, kS32_Type);
+ if (rec)
+ {
+ SkASSERT(rec->fDataCount == 1);
+ if (value)
+ *value = *(const int32_t*)rec->data();
+ return true;
+ }
+ return false;
+}
+
+bool SkMetaData::findScalar(const char name[], SkScalar* value) const
+{
+ const Rec* rec = this->find(name, kScalar_Type);
+ if (rec)
+ {
+ SkASSERT(rec->fDataCount == 1);
+ if (value)
+ *value = *(const SkScalar*)rec->data();
+ return true;
+ }
+ return false;
+}
+
+const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
+{
+ const Rec* rec = this->find(name, kScalar_Type);
+ if (rec)
+ {
+ if (count)
+ *count = rec->fDataCount;
+ if (values)
+ memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
+ return (const SkScalar*)rec->data();
+ }
+ return nullptr;
+}
+
+bool SkMetaData::findPtr(const char name[], void** ptr) const {
+ const Rec* rec = this->find(name, kPtr_Type);
+ if (rec) {
+ SkASSERT(rec->fDataCount == 1);
+ void** found = (void**)rec->data();
+ if (ptr) {
+ *ptr = *found;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool SkMetaData::findBool(const char name[], bool* value) const
+{
+ const Rec* rec = this->find(name, kBool_Type);
+ if (rec)
+ {
+ SkASSERT(rec->fDataCount == 1);
+ if (value)
+ *value = *(const bool*)rec->data();
+ return true;
+ }
+ return false;
+}
+
+const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
+{
+ const Rec* rec = fRec;
+ while (rec)
+ {
+ if (rec->fType == type && !strcmp(rec->name(), name))
+ return rec;
+ rec = rec->fNext;
+ }
+ return nullptr;
+}
+
+bool SkMetaData::remove(const char name[], Type type) {
+ Rec* rec = fRec;
+ Rec* prev = nullptr;
+ while (rec) {
+ Rec* next = rec->fNext;
+ if (rec->fType == type && !strcmp(rec->name(), name)) {
+ if (prev) {
+ prev->fNext = next;
+ } else {
+ fRec = next;
+ }
+ Rec::Free(rec);
+ return true;
+ }
+ prev = rec;
+ rec = next;
+ }
+ return false;
+}
+
+bool SkMetaData::removeS32(const char name[])
+{
+ return this->remove(name, kS32_Type);
+}
+
+bool SkMetaData::removeScalar(const char name[])
+{
+ return this->remove(name, kScalar_Type);
+}
+
+bool SkMetaData::removePtr(const char name[])
+{
+ return this->remove(name, kPtr_Type);
+}
+
+bool SkMetaData::removeBool(const char name[])
+{
+ return this->remove(name, kBool_Type);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkMetaData::Iter::Iter(const SkMetaData& metadata) {
+ fRec = metadata.fRec;
+}
+
+void SkMetaData::Iter::reset(const SkMetaData& metadata) {
+ fRec = metadata.fRec;
+}
+
+const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
+ const char* name = nullptr;
+
+ if (fRec) {
+ if (t) {
+ *t = (SkMetaData::Type)fRec->fType;
+ }
+ if (count) {
+ *count = fRec->fDataCount;
+ }
+ name = fRec->name();
+
+ fRec = fRec->fNext;
+ }
+ return name;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
+ return (Rec*)sk_malloc_throw(size);
+}
+
+void SkMetaData::Rec::Free(Rec* rec) {
+ sk_free(rec);
+}
diff --git a/src/third_party/skia/tools/SkMetaData.h b/src/third_party/skia/tools/SkMetaData.h
new file mode 100644
index 0000000..4ba5d8e
--- /dev/null
+++ b/src/third_party/skia/tools/SkMetaData.h
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+#ifndef SkMetaData_DEFINED
+#define SkMetaData_DEFINED
+
+#include "include/core/SkScalar.h"
+
+/** A map from c-string keys to arrays of POD (int32_t, kScalar, void*, or bool)
+ values.
+*/
+class SkMetaData {
+public:
+ SkMetaData() {}
+ ~SkMetaData() { if (fRec) { this->reset(); } }
+ void reset();
+
+ bool findS32(const char name[], int32_t* value = nullptr) const;
+ bool findScalar(const char name[], SkScalar* value = nullptr) const;
+ const SkScalar* findScalars(const char name[], int* count,
+ SkScalar values[] = nullptr) const;
+ bool findPtr(const char name[], void** value = nullptr) const;
+ bool findBool(const char name[], bool* value = nullptr) const;
+
+ bool hasS32(const char name[], int32_t value) const {
+ int32_t v;
+ return this->findS32(name, &v) && v == value;
+ }
+ bool hasScalar(const char name[], SkScalar value) const {
+ SkScalar v;
+ return this->findScalar(name, &v) && v == value;
+ }
+ bool hasPtr(const char name[], void* value) const {
+ void* v;
+ return this->findPtr(name, &v) && v == value;
+ }
+ bool hasBool(const char name[], bool value) const {
+ bool v;
+ return this->findBool(name, &v) && v == value;
+ }
+
+ void setS32(const char name[], int32_t value);
+ void setScalar(const char name[], SkScalar value);
+ SkScalar* setScalars(const char name[], int count, const SkScalar values[] = nullptr);
+ void setPtr(const char name[], void* value);
+ void setBool(const char name[], bool value);
+
+ bool removeS32(const char name[]);
+ bool removeScalar(const char name[]);
+ bool removePtr(const char name[]);
+ bool removeBool(const char name[]);
+
+ enum Type {
+ kS32_Type,
+ kScalar_Type,
+ kPtr_Type,
+ kBool_Type,
+
+ kTypeCount
+ };
+
+ struct Rec;
+ class Iter;
+ friend class Iter;
+
+ class Iter {
+ public:
+ Iter() : fRec(nullptr) {}
+ Iter(const SkMetaData&);
+
+ /** Reset the iterator, so that calling next() will return the first
+ data element. This is done implicitly in the constructor.
+ */
+ void reset(const SkMetaData&);
+
+ /** Each time next is called, it returns the name of the next data element,
+ or null when there are no more elements. If non-null is returned, then the
+ element's type is returned (if not null), and the number of data values
+ is returned in count (if not null).
+ */
+ const char* next(Type*, int* count);
+
+ private:
+ Rec* fRec;
+ };
+
+public:
+ struct Rec {
+ Rec* fNext;
+ uint16_t fDataCount; // number of elements
+ uint8_t fDataLen; // sizeof a single element
+ uint8_t fType;
+
+ const void* data() const { return (this + 1); }
+ void* data() { return (this + 1); }
+ const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
+ char* name() { return (char*)this->data() + fDataLen * fDataCount; }
+
+ static Rec* Alloc(size_t);
+ static void Free(Rec*);
+ };
+ Rec* fRec = nullptr;
+
+ const Rec* find(const char name[], Type) const;
+ void* set(const char name[], const void* data, size_t len, Type, int count);
+ bool remove(const char name[], Type);
+
+ SkMetaData(const SkMetaData&) = delete;
+ SkMetaData& operator=(const SkMetaData&) = delete;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/SkShaper.h b/src/third_party/skia/tools/SkShaper.h
deleted file mode 100644
index bc78be7..0000000
--- a/src/third_party/skia/tools/SkShaper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkShaper_DEFINED
-#define SkShaper_DEFINED
-
-#include <memory>
-
-#include "SkPoint.h"
-#include "SkTypeface.h"
-
-class SkPaint;
-class SkTextBlobBuilder;
-
-/**
- Shapes text using HarfBuzz and places the shaped text into a
- TextBlob.
-
- If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs.
- */
-class SkShaper {
-public:
- SkShaper(sk_sp<SkTypeface> face);
- ~SkShaper();
-
- bool good() const;
- SkScalar shape(SkTextBlobBuilder* dest,
- const SkPaint& srcPaint,
- const char* utf8text,
- size_t textBytes,
- SkPoint point) const;
-
-private:
- SkShaper(const SkShaper&) = delete;
- SkShaper& operator=(const SkShaper&) = delete;
-
- struct Impl;
- std::unique_ptr<Impl> fImpl;
-};
-
-#endif // SkShaper_DEFINED
diff --git a/src/third_party/skia/tools/SkShaper_harfbuzz.cpp b/src/third_party/skia/tools/SkShaper_harfbuzz.cpp
deleted file mode 100644
index 9c7d69e..0000000
--- a/src/third_party/skia/tools/SkShaper_harfbuzz.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <hb-ot.h>
-
-#include "SkShaper.h"
-#include "SkStream.h"
-#include "SkTextBlob.h"
-#include "SkTypeface.h"
-
-static const int FONT_SIZE_SCALE = 512;
-
-namespace {
-struct HBFBlobDel {
- void operator()(hb_blob_t* b) { hb_blob_destroy(b); }
-};
-
-std::unique_ptr<hb_blob_t, HBFBlobDel> stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
- size_t size = asset->getLength();
- std::unique_ptr<hb_blob_t, HBFBlobDel> blob;
- if (const void* base = asset->getMemoryBase()) {
- blob.reset(hb_blob_create((char*)base, SkToUInt(size),
- HB_MEMORY_MODE_READONLY, asset.release(),
- [](void* p) { delete (SkStreamAsset*)p; }));
- } else {
- // SkDebugf("Extra SkStreamAsset copy\n");
- void* ptr = size ? sk_malloc_throw(size) : nullptr;
- asset->read(ptr, size);
- blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
- HB_MEMORY_MODE_READONLY, ptr, sk_free));
- }
- SkASSERT(blob);
- hb_blob_make_immutable(blob.get());
- return blob;
-}
-} // namespace
-
-struct SkShaper::Impl {
- struct HBFontDel {
- void operator()(hb_font_t* f) { hb_font_destroy(f); }
- };
- std::unique_ptr<hb_font_t, HBFontDel> fHarfBuzzFont;
- struct HBBufDel {
- void operator()(hb_buffer_t* b) { hb_buffer_destroy(b); }
- };
- std::unique_ptr<hb_buffer_t, HBBufDel> fBuffer;
- sk_sp<SkTypeface> fTypeface;
-};
-
-SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
- fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
- int index;
- std::unique_ptr<hb_blob_t, HBFBlobDel> blob(
- stream_to_blob(std::unique_ptr<SkStreamAsset>(
- fImpl->fTypeface->openStream(&index))));
- struct HBFaceDel {
- void operator()(hb_face_t* f) { hb_face_destroy(f); }
- };
- std::unique_ptr<hb_face_t, HBFaceDel> face(
- hb_face_create(blob.get(), (unsigned)index));
- SkASSERT(face);
- if (!face) {
- return;
- }
- hb_face_set_index(face.get(), (unsigned)index);
- hb_face_set_upem(face.get(), fImpl->fTypeface->getUnitsPerEm());
-
- fImpl->fHarfBuzzFont.reset(hb_font_create(face.get()));
- SkASSERT(fImpl->fHarfBuzzFont);
- hb_font_set_scale(fImpl->fHarfBuzzFont.get(), FONT_SIZE_SCALE, FONT_SIZE_SCALE);
- hb_ot_font_set_funcs(fImpl->fHarfBuzzFont.get());
-
- fImpl->fBuffer.reset(hb_buffer_create());
-}
-
-SkShaper::~SkShaper() {}
-
-bool SkShaper::good() const { return fImpl->fHarfBuzzFont != nullptr; }
-
-SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
- const SkPaint& srcPaint,
- const char* utf8text,
- size_t textBytes,
- SkPoint point) const {
- SkPaint paint(srcPaint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint.setTypeface(fImpl->fTypeface);
-
- SkASSERT(builder);
- hb_buffer_t* buffer = fImpl->fBuffer.get();
- hb_buffer_add_utf8(buffer, utf8text, -1, 0, -1);
- hb_buffer_guess_segment_properties(buffer);
- hb_shape(fImpl->fHarfBuzzFont.get(), buffer, nullptr, 0);
- unsigned len = hb_buffer_get_length(buffer);
- if (len == 0) {
- hb_buffer_clear_contents(buffer);
- return 0;
- }
-
- hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, NULL);
- hb_glyph_position_t* pos =
- hb_buffer_get_glyph_positions(buffer, NULL);
- auto runBuffer = builder->allocRunTextPos(
- paint, SkToInt(len), SkToInt(textBytes), SkString());
- memcpy(runBuffer.utf8text, utf8text, textBytes);
-
- double x = point.x();
- double y = point.y();
-
- double textSizeY = paint.getTextSize() / (double)FONT_SIZE_SCALE;
- double textSizeX = textSizeY * paint.getTextScaleX();
-
- for (unsigned i = 0; i < len; i++) {
- runBuffer.glyphs[i] = info[i].codepoint;
- runBuffer.clusters[i] = info[i].cluster;
- reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
- SkPoint::Make(SkDoubleToScalar(x + pos[i].x_offset * textSizeX),
- SkDoubleToScalar(y - pos[i].y_offset * textSizeY));
- x += pos[i].x_advance * textSizeX;
- y += pos[i].y_advance * textSizeY;
- }
-
- hb_buffer_clear_contents(buffer);
- return (SkScalar)x;
-}
diff --git a/src/third_party/skia/tools/SkShaper_primitive.cpp b/src/third_party/skia/tools/SkShaper_primitive.cpp
deleted file mode 100644
index b165285..0000000
--- a/src/third_party/skia/tools/SkShaper_primitive.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkShaper.h"
-#include "SkStream.h"
-#include "SkTextBlob.h"
-#include "SkTypeface.h"
-
-struct SkShaper::Impl {
- sk_sp<SkTypeface> fTypeface;
-};
-
-SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
- fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
-}
-
-SkShaper::~SkShaper() {}
-
-bool SkShaper::good() const { return true; }
-
-// This example only uses public API, so we don't use SkUTF8_NextUnichar.
-unsigned utf8_lead_byte_to_count(const char* ptr) {
- uint8_t c = *(const uint8_t*)ptr;
- SkASSERT(c <= 0xF7);
- SkASSERT((c & 0xC0) != 0x80);
- return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
-}
-
-SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
- const SkPaint& srcPaint,
- const char* utf8text,
- size_t textBytes,
- SkPoint point) const {
- SkPaint paint(srcPaint);
- paint.setTypeface(fImpl->fTypeface);
- paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
- int glyphCount = paint.countText(utf8text, textBytes);
- if (glyphCount <= 0) {
- return 0;
- }
- SkRect bounds;
- (void)paint.measureText(utf8text, textBytes, &bounds);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- const SkTextBlobBuilder::RunBuffer& runBuffer =
- builder->allocRunTextPosH(paint, glyphCount, point.y(), textBytes, SkString(), &bounds);
- memcpy(runBuffer.utf8text, utf8text, textBytes);
- const char* txtPtr = utf8text;
- for (int i = 0; i < glyphCount; ++i) {
- // Each charater maps to exactly one glyph via SkGlyphCache::unicharToGlyph().
- runBuffer.clusters[i] = SkToU32(txtPtr - utf8text);
- txtPtr += utf8_lead_byte_to_count(txtPtr);
- SkASSERT(txtPtr <= utf8text + textBytes);
- }
- paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
- (void)paint.textToGlyphs(utf8text, textBytes, runBuffer.glyphs);
- (void)paint.getTextWidths(utf8text, textBytes, runBuffer.pos);
- SkScalar x = point.x();
- for (int i = 0; i < glyphCount; ++i) {
- SkScalar w = runBuffer.pos[i];
- runBuffer.pos[i] = x;
- x += w;
- }
- return (SkScalar)x;
-}
diff --git a/src/third_party/skia/tools/SkSharingProc.cpp b/src/third_party/skia/tools/SkSharingProc.cpp
new file mode 100644
index 0000000..803f766
--- /dev/null
+++ b/src/third_party/skia/tools/SkSharingProc.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/SkSharingProc.h"
+
+#include "include/core/SkData.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkSerialProcs.h"
+
+sk_sp<SkData> SkSharingSerialContext::serializeImage(SkImage* img, void* ctx) {
+ SkSharingSerialContext* context = reinterpret_cast<SkSharingSerialContext*>(ctx);
+ uint32_t id = img->uniqueID(); // get this process's id for the image. these are not hashes.
+ // find out if we have already serialized this, and if so, what its in-file id is.
+ auto iter = context->fImageMap.find(id);
+ if (iter == context->fImageMap.end()) {
+ // When not present, add its id to the map and return its usual serialized form.
+ context->fImageMap[id] = context->fImageMap.size();
+ return img->encodeToData();
+ }
+ uint32_t fid = context->fImageMap[id];
+ // if present, return only the in-file id we registered the first time we serialized it.
+ return SkData::MakeWithCopy(&fid, sizeof(fid));
+}
+
+sk_sp<SkImage> SkSharingDeserialContext::deserializeImage(
+ const void* data, size_t length, void* ctx) {
+ SkSharingDeserialContext* context = reinterpret_cast<SkSharingDeserialContext*>(ctx);
+ uint32_t fid;
+ // If the data is an image fid, look up an already deserialized image from our map
+ if (length == sizeof(fid)) {
+ memcpy(&fid, data, sizeof(fid));
+ if (fid >= context->fImages.size()) {
+ SkDebugf("We do not have the data for image %d.\n", fid);
+ return nullptr;
+ }
+ return context->fImages[fid];
+ }
+ // Otherwise, the data is an image, deserialise it, store it in our map at its fid.
+ // TODO(nifong): make DeserialProcs accept sk_sp<SkData> so we don't have to copy this.
+ sk_sp<SkData> dataView = SkData::MakeWithCopy(data, length);
+ const sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(dataView));
+ context->fImages.push_back(image);
+ return image;
+}
diff --git a/src/third_party/skia/tools/SkSharingProc.h b/src/third_party/skia/tools/SkSharingProc.h
new file mode 100644
index 0000000..12a7b80
--- /dev/null
+++ b/src/third_party/skia/tools/SkSharingProc.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSharingProc_DEFINED
+#define SkSharingProc_DEFINED
+
+#include <unordered_map>
+#include <vector>
+
+#include "include/core/SkData.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkSerialProcs.h"
+
+struct SkSharingSerialContext {
+ // A map from the ids from SkImage::uniqueID() to ids used within the file
+ std::unordered_map<uint32_t, uint32_t> fImageMap;
+
+ // A serial proc that shares images between subpictures
+ // To use this, create an instance of SkSerialProcs and populate it this way.
+ // The client must retain ownership of the context.
+ // auto ctx = std::make_unique<SkSharingSerialContext>()
+ // SkSerialProcs procs;
+ // procs.fImageProc = SkSharingSerialContext::serializeImage;
+ // procs.fImageCtx = ctx.get();
+ static sk_sp<SkData> serializeImage(SkImage* img, void* ctx);
+};
+
+struct SkSharingDeserialContext {
+ // a list of unique images in the order they were encountered in the file
+ // Subsequent occurrences of an image refer to it by it's index in this list.
+ std::vector<sk_sp<SkImage>> fImages;
+
+ // A deserial proc that can interpret id's in place of images as references to previous images.
+ // Can also deserialize a SKP where all images are inlined (it's backwards compatible)
+ static sk_sp<SkImage> deserializeImage(const void* data, size_t length, void* ctx);
+};
+
+#endif
diff --git a/src/third_party/skia/tools/SkVMBuilders.cpp b/src/third_party/skia/tools/SkVMBuilders.cpp
new file mode 100644
index 0000000..1902b0e
--- /dev/null
+++ b/src/third_party/skia/tools/SkVMBuilders.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/SkVMBuilders.h"
+
+// Some parts of this builder code are written less fluently than possible,
+// to avoid any ambiguity of function argument evaluation order. This lets
+// our golden tests work portably. In general there's no reason to fear
+// nesting calls to Builder routines.
+
+SrcoverBuilder_F32::SrcoverBuilder_F32(Fmt srcFmt, Fmt dstFmt) {
+ auto byte_to_f32 = [&](skvm::I32 byte) {
+ skvm::F32 _1_255 = splat(1/255.0f);
+ return mul(_1_255, to_f32(byte));
+ };
+
+ auto load = [&](Fmt fmt, skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) {
+ skvm::Arg ptr;
+ switch (fmt) {
+ case Fmt::A8: {
+ ptr = varying<uint8_t>();
+ *r = *g = *b = splat(0.0f);
+ *a = byte_to_f32(load8(ptr));
+ } break;
+
+ case Fmt::G8: {
+ ptr = varying<uint8_t>();
+ *r = *g = *b = byte_to_f32(load8(ptr));
+ *a = splat(1.0f);
+ } break;
+
+ case Fmt::RGBA_8888: {
+ ptr = varying<int>();
+ skvm::I32 rgba = load32(ptr);
+ *r = byte_to_f32(extract(rgba, 0, splat(0xff)));
+ *g = byte_to_f32(extract(rgba, 8, splat(0xff)));
+ *b = byte_to_f32(extract(rgba, 16, splat(0xff)));
+ *a = byte_to_f32(extract(rgba, 24, splat(0xff)));
+ } break;
+ }
+ return ptr;
+ };
+
+ skvm::F32 r,g,b,a;
+ (void)load(srcFmt, &r,&g,&b,&a);
+
+ skvm::F32 dr,dg,db,da;
+ skvm::Arg dst = load(dstFmt, &dr,&dg,&db,&da);
+
+ skvm::F32 invA = sub(splat(1.0f), a);
+ r = mad(dr, invA, r);
+ g = mad(dg, invA, g);
+ b = mad(db, invA, b);
+ a = mad(da, invA, a);
+
+ auto f32_to_byte = [&](skvm::F32 f32) {
+ skvm::F32 _255 = splat(255.0f),
+ _0_5 = splat(0.5f);
+ return to_i32(mad(f32, _255, _0_5));
+ };
+ switch (dstFmt) {
+ case Fmt::A8: {
+ store8(dst, f32_to_byte(a));
+ } break;
+
+ case Fmt::G8: {
+ skvm::F32 _2126 = splat(0.2126f),
+ _7152 = splat(0.7152f),
+ _0722 = splat(0.0722f);
+ store8(dst, f32_to_byte(mad(r, _2126,
+ mad(g, _7152,
+ mul(b, _0722)))));
+ } break;
+
+ case Fmt::RGBA_8888: {
+ skvm::I32 R = f32_to_byte(r),
+ G = f32_to_byte(g),
+ B = f32_to_byte(b),
+ A = f32_to_byte(a);
+
+ R = pack(R, G, 8);
+ B = pack(B, A, 8);
+ R = pack(R, B, 16);
+
+ store32(dst, R);
+ } break;
+ }
+}
+
+SrcoverBuilder_I32_Naive::SrcoverBuilder_I32_Naive() {
+ skvm::Arg src = varying<int>(),
+ dst = varying<int>();
+
+ auto load = [&](skvm::Arg ptr,
+ skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) {
+ skvm::I32 rgba = load32(ptr);
+ *r = extract(rgba, 0, splat(0xff));
+ *g = extract(rgba, 8, splat(0xff));
+ *b = extract(rgba, 16, splat(0xff));
+ *a = extract(rgba, 24, splat(0xff));
+ };
+
+ skvm::I32 r,g,b,a;
+ load(src, &r,&g,&b,&a);
+
+ skvm::I32 dr,dg,db,da;
+ load(dst, &dr,&dg,&db,&da);
+
+ // (xy + x)/256 is a good approximation of (xy + 127)/255
+ //
+ // == (d*(255-a) + d)/256
+ // == (d*(255-a+1) )/256
+ // == (d*(256-a ) )/256
+
+ skvm::I32 invA = sub(splat(256), a);
+ r = add(r, shr(mul(dr, invA), 8));
+ g = add(g, shr(mul(dg, invA), 8));
+ b = add(b, shr(mul(db, invA), 8));
+ a = add(a, shr(mul(da, invA), 8));
+
+ r = pack(r, g, 8);
+ b = pack(b, a, 8);
+ r = pack(r, b, 16);
+ store32(dst, r);
+}
+
+SrcoverBuilder_I32::SrcoverBuilder_I32() {
+ skvm::Arg src = varying<int>(),
+ dst = varying<int>();
+
+ auto load = [&](skvm::Arg ptr,
+ skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) {
+ skvm::I32 rgba = load32(ptr);
+ *r = bit_and(rgba, splat(0xff));
+ *g = bytes (rgba, 0x0002);
+ *b = bytes (rgba, 0x0003);
+ *a = shr (rgba, 24);
+ };
+
+ skvm::I32 r,g,b,a;
+ load(src, &r,&g,&b,&a);
+
+ skvm::I32 dr,dg,db,da;
+ load(dst, &dr,&dg,&db,&da);
+
+ // (xy + x)/256 is a good approximation of (xy + 127)/255
+ //
+ // == (d*(255-a) + d)/256
+ // == (d*(255-a+1) )/256
+ // == (d*(256-a ) )/256
+
+ // We're doing 8x8 bit multiplies in 32-bit lanes.
+ // Since the inputs and results both fit in 16 bits,
+ // we can use mul_16x2, which tends to be faster than mul.
+ //
+ // (The top 2 zero bytes of the inputs will also multiply
+ // with each other to produce zero... perfect.)
+
+ skvm::I32 invA = sub(splat(256), a);
+ r = add(r, shr(mul_16x2(dr, invA), 8));
+ g = add(g, shr(mul_16x2(dg, invA), 8));
+ b = add(b, shr(mul_16x2(db, invA), 8));
+ a = add(a, shr(mul_16x2(da, invA), 8));
+
+ r = pack(r, g, 8);
+ b = pack(b, a, 8);
+ r = pack(r, b, 16);
+ store32(dst, r);
+}
+
+SrcoverBuilder_I32_SWAR::SrcoverBuilder_I32_SWAR() {
+ skvm::Arg src = varying<int>(),
+ dst = varying<int>();
+
+ // The s += d*invA adds won't overflow,
+ // so we don't have to unpack s beyond grabbing the alpha channel.
+ skvm::I32 s = load32(src),
+ ax2 = bytes(s, 0x0404); // rgba -> a0a0
+
+ // We'll use the same approximation math as above, this time making sure to
+ // use both i16 multiplies to our benefit, one for r/g, the other for b/a.
+ skvm::I32 invAx2 = sub_16x2(splat(0x01000100), ax2);
+
+ skvm::I32 d = load32(dst),
+ rb = bit_and (d, splat(0x00ff00ff)),
+ ga = shr_16x2(d, 8);
+
+ rb = shr_16x2(mul_16x2(rb, invAx2), 8); // Put the high 8 bits back in the low lane.
+ ga = mul_16x2(ga, invAx2); // Keep the high 8 bits up high...
+ ga = bit_clear(ga, splat(0x00ff00ff)); // ...and mask off the low bits.
+
+ store32(dst, add(s, bit_or(rb, ga)));
+}
diff --git a/src/third_party/skia/tools/SkVMBuilders.h b/src/third_party/skia/tools/SkVMBuilders.h
new file mode 100644
index 0000000..261c423
--- /dev/null
+++ b/src/third_party/skia/tools/SkVMBuilders.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkVMBuilders_DEFINED
+#define SkVMBuilders_DEFINED
+
+#include "src/core/SkVM.h"
+
+// SkVM builders used by both SkVMBench.cpp and SkVMTest.cpp.
+
+struct SrcoverBuilder_F32 : public skvm::Builder {
+ enum class Fmt { A8, G8, RGBA_8888 };
+ SrcoverBuilder_F32(Fmt srcFmt = Fmt::RGBA_8888,
+ Fmt dstFmt = Fmt::RGBA_8888);
+};
+
+struct SrcoverBuilder_I32_Naive : public skvm::Builder {
+ SrcoverBuilder_I32_Naive(); // 8888 over 8888
+};
+
+struct SrcoverBuilder_I32 : public skvm::Builder {
+ SrcoverBuilder_I32(); // 8888 over 8888
+};
+
+struct SrcoverBuilder_I32_SWAR : public skvm::Builder {
+ SrcoverBuilder_I32_SWAR(); // 8888 over 8888
+};
+
+#endif//SkVMBuilders_DEFINED
diff --git a/src/third_party/skia/tools/Stats.h b/src/third_party/skia/tools/Stats.h
index 557a2a5..526198e 100644
--- a/src/third_party/skia/tools/Stats.h
+++ b/src/third_party/skia/tools/Stats.h
@@ -8,8 +8,9 @@
#ifndef Stats_DEFINED
#define Stats_DEFINED
-#include "SkString.h"
-#include "SkTSort.h"
+#include "include/core/SkString.h"
+#include "include/private/SkFloatingPoint.h"
+#include "src/core/SkTSort.h"
#ifdef SK_BUILD_FOR_WIN
static const char* kBars[] = { ".", "o", "O" };
@@ -18,7 +19,7 @@
#endif
struct Stats {
- Stats(const SkTArray<double>& samples) {
+ Stats(const SkTArray<double>& samples, bool want_plot) {
int n = samples.count();
if (!n) {
min = max = mean = var = median = 0;
@@ -42,7 +43,7 @@
for (int i = 0 ; i < n; i++) {
err += (samples[i] - mean) * (samples[i] - mean);
}
- var = err / (n-1);
+ var = sk_ieee_double_divide(err, n-1);
SkAutoTMalloc<double> sorted(n);
memcpy(sorted.get(), samples.begin(), n * sizeof(double));
@@ -50,7 +51,7 @@
median = sorted[n/2];
// Normalize samples to [min, max] in as many quanta as we have distinct bars to print.
- for (int i = 0; i < n; i++) {
+ for (int i = 0; want_plot && i < n; i++) {
if (min == max) {
// All samples are the same value. Don't divide by zero.
plot.append(kBars[0]);
diff --git a/src/third_party/skia/tools/ThermalManager.cpp b/src/third_party/skia/tools/ThermalManager.cpp
deleted file mode 100644
index e0c7c44..0000000
--- a/src/third_party/skia/tools/ThermalManager.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "ThermalManager.h"
-
-#include "SkOSFile.h"
-
-#include <stdio.h>
-
-#ifndef SK_BUILD_FOR_WIN32
- #include <unistd.h>
-#endif
-
-#ifdef THERMAL_MANAGER_SUPPORTED
-
-/*
- * ThermalManager is completely dependent on sysfs to monitor thermal temperatures. In sysfs
- * thermal management is controlled by a number of thermal zones. They are laid out as follows:
- * /sys/class/thermal/thermal_zoneN where N is the number of the thermal zone starting at 0.
- *
- * Inside each thermal_zone folder is a file called 'temp,' which has the current temperature
- * reading from the sensor in that zone, as well as 0 or more files called 'trip_point_N_temp.'
- *
- * When the reading in temp is greater than one of the numbers in the trip_point files, then the
- * kernel will take some kind of action. This is all documented online.
- *
- * In any case, the goal of this class is to sleep right before a trip point is about to be
- * triggered, thus naturally cooling the system and preventing thermal throttling.
- */
-
-ThermalManager::ThermalManager(int32_t threshold, uint32_t sleepIntervalMs, uint32_t timeoutMs)
- : fSleepIntervalMs(sleepIntervalMs)
- , fTimeoutMs(timeoutMs) {
- static const char* kThermalZonePath = "/sys/class/thermal/";
- SkOSFile::Iter it(kThermalZonePath);
- SkString path;
- while (it.next(&path, true)) {
- if (!path.contains("thermal_zone")) {
- continue;
- }
-
- SkString fullPath(kThermalZonePath);
- fullPath.append(path);
- SkOSFile::Iter thermalZoneIt(fullPath.c_str());
-
- SkString filename;
- while (thermalZoneIt.next(&filename)) {
- if (!(filename.contains("trip_point") && filename.contains("temp"))) {
- continue;
- }
-
- fTripPoints.push_back(TripPoint(fullPath, filename, threshold));
- }
- }
-}
-
-bool ThermalManager::coolOffIfNecessary() {
- uint32_t i = 0, totalTimeSleptMs = 0;
- while (i < (uint32_t)fTripPoints.count() && totalTimeSleptMs < fTimeoutMs) {
- if (fTripPoints[i].willTrip()) {
- sleep(fSleepIntervalMs);
- totalTimeSleptMs += fSleepIntervalMs;
- } else {
- i++;
- }
- }
-
- return totalTimeSleptMs < fTimeoutMs;
-}
-
-int32_t ThermalManager::OpenFileAndReadInt32(const char* path) {
- FILE* tempFile = fopen(path, "r");
- SkASSERT(tempFile);
- int32_t value;
- int ret = fscanf(tempFile, "%d", &value);
- if (!ret) {
- SkDebugf("Could not read temperature\n");
- SkASSERT(false);
- }
-
- fclose(tempFile);
- return value;
-}
-
-ThermalManager::TripPoint::TripPoint(SkString thermalZoneRoot, SkString pointName,
- int32_t threshold)
- : fThermalZoneRoot(thermalZoneRoot)
- , fPointName(pointName) {
- SkString fullPath(thermalZoneRoot);
- fullPath.appendf("/%s", pointName.c_str());
- fPoint = OpenFileAndReadInt32(fullPath.c_str());
- fBase = GetTemp(fThermalZoneRoot);
- fThreshold = threshold;
- fDisabled = fBase + fThreshold >= fPoint; // We disable any trip point which start off
- // triggered
-}
-
-bool ThermalManager::TripPoint::willTrip() {
- int32_t currentTemp = GetTemp(fThermalZoneRoot);
- bool wouldTrip = !fDisabled && currentTemp + fThreshold >= fPoint;
-
- if (wouldTrip) {
- SkDebugf("%s/%s would trip {%d,%d,%d,%d}\n", fThermalZoneRoot.c_str(),
- fPointName.c_str(), fBase, currentTemp, fPoint, fThreshold);
- }
- return wouldTrip;
-}
-
-#endif
diff --git a/src/third_party/skia/tools/ThermalManager.h b/src/third_party/skia/tools/ThermalManager.h
deleted file mode 100644
index 747cf52..0000000
--- a/src/third_party/skia/tools/ThermalManager.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef ThermalManager_DEFINED
-#define ThermalManager_DEFINED
-
-#include "../private/SkTArray.h"
-#include "SkString.h"
-
-#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
-# define THERMAL_MANAGER_SUPPORTED
-#endif
-
-#ifdef THERMAL_MANAGER_SUPPORTED
-
-/*
- * This simple class monitors the thermal part of sysfs to ensure we don't trigger thermal events
- */
-
-class ThermalManager {
-public:
- ThermalManager(int32_t threshold, uint32_t sleepIntervalMs, uint32_t timeoutMs);
-
- bool coolOffIfNecessary();
-
-private:
- static int32_t OpenFileAndReadInt32(const char* path);
-
- // current temperature can be read from /thermalZonePath/temp
- static int32_t GetTemp(SkString thermalZonePath) {
- SkString temperatureFilePath(thermalZonePath);
- temperatureFilePath.appendf("/temp");
- return OpenFileAndReadInt32(temperatureFilePath.c_str());
- }
-
- struct TripPoint {
- TripPoint(SkString thermalZoneRoot, SkString pointName, int32_t threshold);
-
- bool willTrip();
-
- SkString fThermalZoneRoot;
- SkString fPointName;
- int32_t fBase;
- int32_t fPoint;
- int32_t fThreshold;
-
- // Certain trip points seem to start tripped. For example, I have seen trip points of 0 or
- // negative numbers.
- bool fDisabled;
- };
-
- SkTArray<TripPoint> fTripPoints;
- uint32_t fSleepIntervalMs;
- uint32_t fTimeoutMs;
-};
-#endif
-#endif
diff --git a/src/third_party/skia/tools/ToolUtils.cpp b/src/third_party/skia/tools/ToolUtils.cpp
new file mode 100644
index 0000000..99e25ee
--- /dev/null
+++ b/src/third_party/skia/tools/ToolUtils.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColorPriv.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPixelRef.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkPoint3.h"
+#include "include/core/SkRRect.h"
+#include "include/core/SkShader.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTextBlob.h"
+#include "include/ports/SkTypeface_win.h"
+#include "include/private/SkColorData.h"
+#include "include/private/SkFloatingPoint.h"
+#include "src/core/SkFontMgrPriv.h"
+#include "src/core/SkFontPriv.h"
+#include "tools/ToolUtils.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/fonts/TestFontMgr.h"
+
+#include <cmath>
+#include <cstring>
+#include <memory>
+
+namespace ToolUtils {
+
+const char* alphatype_name(SkAlphaType at) {
+ switch (at) {
+ case kUnknown_SkAlphaType: return "Unknown";
+ case kOpaque_SkAlphaType: return "Opaque";
+ case kPremul_SkAlphaType: return "Premul";
+ case kUnpremul_SkAlphaType: return "Unpremul";
+ }
+ SkASSERT(false);
+ return "unexpected alphatype";
+}
+
+const char* colortype_name(SkColorType ct) {
+ switch (ct) {
+ case kUnknown_SkColorType: return "Unknown";
+ case kAlpha_8_SkColorType: return "Alpha_8";
+ case kA16_unorm_SkColorType: return "Alpha_16";
+ case kA16_float_SkColorType: return "A16_float";
+ case kRGB_565_SkColorType: return "RGB_565";
+ case kARGB_4444_SkColorType: return "ARGB_4444";
+ case kRGBA_8888_SkColorType: return "RGBA_8888";
+ case kRGB_888x_SkColorType: return "RGB_888x";
+ case kBGRA_8888_SkColorType: return "BGRA_8888";
+ case kRGBA_1010102_SkColorType: return "RGBA_1010102";
+ case kRGB_101010x_SkColorType: return "RGB_101010x";
+ case kGray_8_SkColorType: return "Gray_8";
+ case kRGBA_F16Norm_SkColorType: return "RGBA_F16Norm";
+ case kRGBA_F16_SkColorType: return "RGBA_F16";
+ case kRGBA_F32_SkColorType: return "RGBA_F32";
+ case kR8G8_unorm_SkColorType: return "R8G8_unorm";
+ case kR16G16_unorm_SkColorType: return "R16G16_unorm";
+ case kR16G16_float_SkColorType: return "R16G16_float";
+ case kR16G16B16A16_unorm_SkColorType: return "R16G16B16A16_unorm";
+ }
+ SkASSERT(false);
+ return "unexpected colortype";
+}
+
+const char* colortype_depth(SkColorType ct) {
+ switch (ct) {
+ case kUnknown_SkColorType: return "Unknown";
+ case kAlpha_8_SkColorType: return "A8";
+ case kA16_unorm_SkColorType: return "A16";
+ case kA16_float_SkColorType: return "AF16";
+ case kRGB_565_SkColorType: return "565";
+ case kARGB_4444_SkColorType: return "4444";
+ case kRGBA_8888_SkColorType: return "8888";
+ case kRGB_888x_SkColorType: return "888";
+ case kBGRA_8888_SkColorType: return "8888";
+ case kRGBA_1010102_SkColorType: return "1010102";
+ case kRGB_101010x_SkColorType: return "101010";
+ case kGray_8_SkColorType: return "G8";
+ case kRGBA_F16Norm_SkColorType: return "F16Norm"; // TODO: "F16"?
+ case kRGBA_F16_SkColorType: return "F16";
+ case kRGBA_F32_SkColorType: return "F32";
+ case kR8G8_unorm_SkColorType: return "88";
+ case kR16G16_unorm_SkColorType: return "1616";
+ case kR16G16_float_SkColorType: return "F16F16";
+ case kR16G16B16A16_unorm_SkColorType: return "16161616";
+ }
+ SkASSERT(false);
+ return "unexpected colortype";
+}
+
+const char* tilemode_name(SkTileMode mode) {
+ switch (mode) {
+ case SkTileMode::kClamp: return "clamp";
+ case SkTileMode::kRepeat: return "repeat";
+ case SkTileMode::kMirror: return "mirror";
+ case SkTileMode::kDecal: return "decal";
+ }
+ SkASSERT(false);
+ return "unexpected tilemode";
+}
+
+SkColor color_to_565(SkColor color) {
+ // Not a good idea to use this function for greyscale colors...
+ // it will add an obvious purple or green tint.
+ SkASSERT(SkColorGetR(color) != SkColorGetG(color) || SkColorGetR(color) != SkColorGetB(color) ||
+ SkColorGetG(color) != SkColorGetB(color));
+
+ SkPMColor pmColor = SkPreMultiplyColor(color);
+ U16CPU color16 = SkPixel32ToPixel16(pmColor);
+ return SkPixel16ToColor(color16);
+}
+
+sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
+ SkBitmap bm;
+ bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
+ bm.eraseColor(c1);
+ bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
+ bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
+ return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
+}
+
+SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize) {
+ SkBitmap bitmap;
+ bitmap.allocPixels(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
+ SkCanvas canvas(bitmap);
+
+ ToolUtils::draw_checkerboard(&canvas, c1, c2, checkSize);
+ return bitmap;
+}
+
+void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
+ SkPaint paint;
+ paint.setShader(create_checkerboard_shader(c1, c2, size));
+ paint.setBlendMode(SkBlendMode::kSrc);
+ canvas->drawPaint(paint);
+}
+
+SkBitmap
+create_string_bitmap(int w, int h, SkColor c, int x, int y, int textSize, const char* str) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(w, h);
+ SkCanvas canvas(bitmap);
+
+ SkPaint paint;
+ paint.setColor(c);
+
+ SkFont font(ToolUtils::create_portable_typeface(), textSize);
+
+ canvas.clear(0x00000000);
+ canvas.drawSimpleText(str,
+ strlen(str),
+ SkTextEncoding::kUTF8,
+ SkIntToScalar(x),
+ SkIntToScalar(y),
+ font,
+ paint);
+
+ // Tag data as sRGB (without doing any color space conversion). Color-space aware configs
+ // will process this correctly but legacy configs will render as if this returned N32.
+ SkBitmap result;
+ result.setInfo(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
+ result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
+ return result;
+}
+
+void add_to_text_blob_w_len(SkTextBlobBuilder* builder,
+ const char* text,
+ size_t len,
+ SkTextEncoding encoding,
+ const SkFont& font,
+ SkScalar x,
+ SkScalar y) {
+ int count = font.countText(text, len, encoding);
+ auto run = builder->allocRun(font, count, x, y);
+ font.textToGlyphs(text, len, encoding, run.glyphs, count);
+}
+
+void add_to_text_blob(SkTextBlobBuilder* builder,
+ const char* text,
+ const SkFont& font,
+ SkScalar x,
+ SkScalar y) {
+ add_to_text_blob_w_len(builder, text, strlen(text), SkTextEncoding::kUTF8, font, x, y);
+}
+
+void get_text_path(const SkFont& font,
+ const void* text,
+ size_t length,
+ SkTextEncoding encoding,
+ SkPath* dst,
+ const SkPoint pos[]) {
+ SkAutoToGlyphs atg(font, text, length, encoding);
+ const int count = atg.count();
+ SkAutoTArray<SkPoint> computedPos;
+ if (pos == nullptr) {
+ computedPos.reset(count);
+ font.getPos(atg.glyphs(), count, &computedPos[0]);
+ pos = computedPos.get();
+ }
+
+ struct Rec {
+ SkPath* fDst;
+ const SkPoint* fPos;
+ } rec = {dst, pos};
+ font.getPaths(atg.glyphs(),
+ atg.count(),
+ [](const SkPath* src, const SkMatrix& mx, void* ctx) {
+ Rec* rec = (Rec*)ctx;
+ if (src) {
+ SkMatrix tmp(mx);
+ tmp.postTranslate(rec->fPos->fX, rec->fPos->fY);
+ rec->fDst->addPath(*src, tmp);
+ }
+ rec->fPos += 1;
+ },
+ &rec);
+}
+
+SkPath make_star(const SkRect& bounds, int numPts, int step) {
+ SkASSERT(numPts != step);
+ SkPath path;
+ path.setFillType(SkPath::kEvenOdd_FillType);
+ path.moveTo(0, -1);
+ for (int i = 1; i < numPts; ++i) {
+ int idx = i * step % numPts;
+ SkScalar theta = idx * 2 * SK_ScalarPI / numPts + SK_ScalarPI / 2;
+ SkScalar x = SkScalarCos(theta);
+ SkScalar y = -SkScalarSin(theta);
+ path.lineTo(x, y);
+ }
+ path.transform(SkMatrix::MakeRectToRect(path.getBounds(), bounds, SkMatrix::kFill_ScaleToFit));
+ return path;
+}
+
+static inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) {
+ SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f));
+ unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255);
+ unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255);
+ unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255);
+ *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
+}
+
+void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) {
+ const SkPoint center =
+ SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
+ const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f);
+
+ SkVector3 norm;
+
+ for (int y = dst.fTop; y < dst.fBottom; ++y) {
+ for (int x = dst.fLeft; x < dst.fRight; ++x) {
+ norm.fX = (x + 0.5f - center.fX) / halfSize.fX;
+ norm.fY = (y + 0.5f - center.fY) / halfSize.fY;
+
+ SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY;
+ if (tmp >= 1.0f) {
+ norm.set(0.0f, 0.0f, 1.0f);
+ } else {
+ norm.fZ = sqrtf(1.0f - tmp);
+ }
+
+ norm_to_rgb(bm, x, y, norm);
+ }
+ }
+}
+
+void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) {
+ const SkPoint center =
+ SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
+
+ SkIRect inner = dst;
+ inner.inset(dst.width() / 4, dst.height() / 4);
+
+ SkPoint3 norm;
+ const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
+ const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
+ const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
+ const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
+
+ for (int y = dst.fTop; y < dst.fBottom; ++y) {
+ for (int x = dst.fLeft; x < dst.fRight; ++x) {
+ if (inner.contains(x, y)) {
+ norm.set(0.0f, 0.0f, 1.0f);
+ } else {
+ SkScalar locX = x + 0.5f - center.fX;
+ SkScalar locY = y + 0.5f - center.fY;
+
+ if (locX >= 0.0f) {
+ if (locY > 0.0f) {
+ norm = locX >= locY ? right : down; // LR corner
+ } else {
+ norm = locX > -locY ? right : up; // UR corner
+ }
+ } else {
+ if (locY > 0.0f) {
+ norm = -locX > locY ? left : down; // LL corner
+ } else {
+ norm = locX > locY ? up : left; // UL corner
+ }
+ }
+ }
+
+ norm_to_rgb(bm, x, y, norm);
+ }
+ }
+}
+
+void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
+ const SkPoint center =
+ SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
+
+ static const SkScalar k1OverRoot3 = 0.5773502692f;
+
+ SkPoint3 norm;
+ const SkPoint3 leftUp = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3);
+ const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3);
+ const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
+
+ for (int y = dst.fTop; y < dst.fBottom; ++y) {
+ for (int x = dst.fLeft; x < dst.fRight; ++x) {
+ SkScalar locX = x + 0.5f - center.fX;
+ SkScalar locY = y + 0.5f - center.fY;
+
+ if (locX >= 0.0f) {
+ if (locY > 0.0f) {
+ norm = locX >= locY ? rightUp : down; // LR corner
+ } else {
+ norm = rightUp;
+ }
+ } else {
+ if (locY > 0.0f) {
+ norm = -locX > locY ? leftUp : down; // LL corner
+ } else {
+ norm = leftUp;
+ }
+ }
+
+ norm_to_rgb(bm, x, y, norm);
+ }
+ }
+}
+
+#if !defined(__clang__) && defined(_MSC_VER)
+// MSVC takes ~2 minutes to compile this function with optimization.
+// We don't really care to wait that long for this function.
+#pragma optimize("", off)
+#endif
+void make_big_path(SkPath& path) {
+#include "BigPathBench.inc" // IWYU pragma: keep
+}
+
+bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
+ SkPixmap srcPM;
+ if (!src.peekPixels(&srcPM)) {
+ return false;
+ }
+
+ SkBitmap tmpDst;
+ SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
+ if (!tmpDst.setInfo(dstInfo)) {
+ return false;
+ }
+
+ if (!tmpDst.tryAllocPixels()) {
+ return false;
+ }
+
+ SkPixmap dstPM;
+ if (!tmpDst.peekPixels(&dstPM)) {
+ return false;
+ }
+
+ if (!srcPM.readPixels(dstPM)) {
+ return false;
+ }
+
+ dst->swap(tmpDst);
+ return true;
+}
+
+void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
+ SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
+ kRGBA_8888_SkColorType == src.colorType());
+
+ SkImageInfo grayInfo = src.info().makeColorType(kGray_8_SkColorType);
+ dst->allocPixels(grayInfo);
+ uint8_t* dst8 = (uint8_t*)dst->getPixels();
+ const uint32_t* src32 = (const uint32_t*)src.getPixels();
+
+ const int w = src.width();
+ const int h = src.height();
+ const bool isBGRA = (kBGRA_8888_SkColorType == src.colorType());
+ for (int y = 0; y < h; ++y) {
+ if (isBGRA) {
+ // BGRA
+ for (int x = 0; x < w; ++x) {
+ uint32_t s = src32[x];
+ dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
+ }
+ } else {
+ // RGBA
+ for (int x = 0; x < w; ++x) {
+ uint32_t s = src32[x];
+ dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
+ }
+ }
+ src32 = (const uint32_t*)((const char*)src32 + src.rowBytes());
+ dst8 += dst->rowBytes();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+bool equal_pixels(const SkPixmap& a, const SkPixmap& b) {
+ if (a.width() != b.width() || a.height() != b.height() || a.colorType() != b.colorType()) {
+ return false;
+ }
+
+ for (int y = 0; y < a.height(); ++y) {
+ const char* aptr = (const char*)a.addr(0, y);
+ const char* bptr = (const char*)b.addr(0, y);
+ if (memcmp(aptr, bptr, a.width() * a.info().bytesPerPixel())) {
+ return false;
+ }
+ aptr += a.rowBytes();
+ bptr += b.rowBytes();
+ }
+ return true;
+}
+
+bool equal_pixels(const SkBitmap& bm0, const SkBitmap& bm1) {
+ SkPixmap pm0, pm1;
+ return bm0.peekPixels(&pm0) && bm1.peekPixels(&pm1) && equal_pixels(pm0, pm1);
+}
+
+bool equal_pixels(const SkImage* a, const SkImage* b) {
+ // ensure that peekPixels will succeed
+ auto imga = a->makeRasterImage();
+ auto imgb = b->makeRasterImage();
+
+ SkPixmap pm0, pm1;
+ return imga->peekPixels(&pm0) && imgb->peekPixels(&pm1) && equal_pixels(pm0, pm1);
+}
+
+sk_sp<SkSurface> makeSurface(SkCanvas* canvas,
+ const SkImageInfo& info,
+ const SkSurfaceProps* props) {
+ auto surf = canvas->makeSurface(info, props);
+ if (!surf) {
+ surf = SkSurface::MakeRaster(info, props);
+ }
+ return surf;
+}
+
+static DEFINE_bool(nativeFonts, true,
+ "If true, use native font manager and rendering. "
+ "If false, fonts will draw as portably as possible.");
+#if defined(SK_BUILD_FOR_WIN)
+ static DEFINE_bool(gdi, false,
+ "Use GDI instead of DirectWrite for font rendering.");
+#endif
+
+void SetDefaultFontMgr() {
+ if (!FLAGS_nativeFonts) {
+ gSkFontMgr_DefaultFactory = &ToolUtils::MakePortableFontMgr;
+ }
+#if defined(SK_BUILD_FOR_WIN)
+ if (FLAGS_gdi) {
+ gSkFontMgr_DefaultFactory = &SkFontMgr_New_GDI;
+ }
+#endif
+}
+
+} // namespace ToolUtils
diff --git a/src/third_party/skia/tools/ToolUtils.h b/src/third_party/skia/tools/ToolUtils.h
new file mode 100644
index 0000000..5c3edfb
--- /dev/null
+++ b/src/third_party/skia/tools/ToolUtils.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef ToolUtils_DEFINED
+#define ToolUtils_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkData.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkFont.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkImageEncoder.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTypeface.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTArray.h"
+#include "include/private/SkTDArray.h"
+#include "include/utils/SkRandom.h"
+
+class SkBitmap;
+class SkCanvas;
+class SkFontStyle;
+class SkImage;
+class SkPath;
+class SkPixmap;
+class SkRRect;
+class SkShader;
+class SkSurface;
+class SkSurfaceProps;
+class SkTextBlobBuilder;
+class SkTypeface;
+
+namespace ToolUtils {
+
+const char* alphatype_name (SkAlphaType);
+const char* colortype_name (SkColorType);
+const char* colortype_depth(SkColorType); // like colortype_name, but channel order agnostic
+const char* tilemode_name(SkTileMode);
+
+/**
+ * Map opaque colors from 8888 to 565.
+ */
+SkColor color_to_565(SkColor color);
+
+/* Return a color emoji typeface with planets to scale if available. */
+sk_sp<SkTypeface> planet_typeface();
+
+/** Return a color emoji typeface if available. */
+sk_sp<SkTypeface> emoji_typeface();
+
+/** Sample text for the emoji_typeface font. */
+const char* emoji_sample_text();
+
+/**
+ * Returns a platform-independent text renderer.
+ */
+sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style);
+
+static inline sk_sp<SkTypeface> create_portable_typeface() {
+ return create_portable_typeface(nullptr, SkFontStyle());
+}
+
+/**
+ * Turn on portable (--nonativeFonts) or GDI font rendering (--gdi).
+ */
+void SetDefaultFontMgr();
+
+
+void get_text_path(const SkFont&,
+ const void* text,
+ size_t length,
+ SkTextEncoding,
+ SkPath*,
+ const SkPoint* positions = nullptr);
+
+/**
+ * Returns true iff all of the pixels between the two images are identical.
+ *
+ * If the configs differ, return false.
+ */
+bool equal_pixels(const SkPixmap&, const SkPixmap&);
+bool equal_pixels(const SkBitmap&, const SkBitmap&);
+bool equal_pixels(const SkImage* a, const SkImage* b);
+
+/** Returns a newly created CheckerboardShader. */
+sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size);
+
+/** Draw a checkerboard pattern in the current canvas, restricted to
+ the current clip, using SkXfermode::kSrc_Mode. */
+void draw_checkerboard(SkCanvas* canvas, SkColor color1, SkColor color2, int checkSize);
+
+/** Make it easier to create a bitmap-based checkerboard */
+SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize);
+
+/** A default checkerboard. */
+inline void draw_checkerboard(SkCanvas* canvas) {
+ ToolUtils::draw_checkerboard(canvas, 0xFF999999, 0xFF666666, 8);
+}
+
+SkBitmap create_string_bitmap(int w, int h, SkColor c, int x, int y, int textSize, const char* str);
+
+// If the canvas does't make a surface (e.g. recording), make a raster surface
+sk_sp<SkSurface> makeSurface(SkCanvas*, const SkImageInfo&, const SkSurfaceProps* = nullptr);
+
+// A helper for inserting a drawtext call into a SkTextBlobBuilder
+void add_to_text_blob_w_len(SkTextBlobBuilder*,
+ const char* text,
+ size_t len,
+ SkTextEncoding,
+ const SkFont&,
+ SkScalar x,
+ SkScalar y);
+
+void add_to_text_blob(SkTextBlobBuilder*, const char* text, const SkFont&, SkScalar x, SkScalar y);
+
+// Constructs a star by walking a 'numPts'-sided regular polygon with even/odd fill:
+//
+// moveTo(pts[0]);
+// lineTo(pts[step % numPts]);
+// ...
+// lineTo(pts[(step * (N - 1)) % numPts]);
+//
+// numPts=5, step=2 will produce a classic five-point star.
+//
+// numPts and step must be co-prime.
+SkPath make_star(const SkRect& bounds, int numPts = 5, int step = 2);
+
+void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst);
+
+void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst);
+
+void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);
+
+void make_big_path(SkPath& path);
+
+// A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
+class TopoTestNode : public SkRefCnt {
+public:
+ TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) {}
+
+ void dependsOn(TopoTestNode* src) { *fDependencies.append() = src; }
+
+ int id() const { return fID; }
+ void reset() { fOutputPos = -1; }
+
+ int outputPos() const { return fOutputPos; }
+
+ // check that the topological sort is valid for this node
+ bool check() {
+ if (-1 == fOutputPos) {
+ return false;
+ }
+
+ for (int i = 0; i < fDependencies.count(); ++i) {
+ if (-1 == fDependencies[i]->outputPos()) {
+ return false;
+ }
+ // This node should've been output after all the nodes on which it depends
+ if (fOutputPos < fDependencies[i]->outputPos()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // The following 7 methods are needed by the topological sort
+ static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; }
+ static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; }
+ static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; }
+ static void Output(TopoTestNode* node, int outputPos) {
+ SkASSERT(-1 != outputPos);
+ node->fOutputPos = outputPos;
+ }
+ static bool WasOutput(TopoTestNode* node) { return (-1 != node->fOutputPos); }
+ static int NumDependencies(TopoTestNode* node) { return node->fDependencies.count(); }
+ static TopoTestNode* Dependency(TopoTestNode* node, int index) {
+ return node->fDependencies[index];
+ }
+
+ // Helper functions for TopoSortBench & TopoSortTest
+ static void AllocNodes(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph, int num) {
+ graph->reserve(num);
+
+ for (int i = 0; i < num; ++i) {
+ graph->push_back(sk_sp<TopoTestNode>(new TopoTestNode(i)));
+ }
+ }
+
+#ifdef SK_DEBUG
+ static void Print(const SkTArray<TopoTestNode*>& graph) {
+ for (int i = 0; i < graph.count(); ++i) {
+ SkDebugf("%d, ", graph[i]->id());
+ }
+ SkDebugf("\n");
+ }
+#endif
+
+ // randomize the array
+ static void Shuffle(SkTArray<sk_sp<TopoTestNode>>* graph, SkRandom* rand) {
+ for (int i = graph->count() - 1; i > 0; --i) {
+ int swap = rand->nextU() % (i + 1);
+
+ (*graph)[i].swap((*graph)[swap]);
+ }
+ }
+
+private:
+ int fID;
+ int fOutputPos;
+ bool fTempMark;
+
+ SkTDArray<TopoTestNode*> fDependencies;
+};
+
+template <typename T>
+inline bool EncodeImageToFile(const char* path, const T& src, SkEncodedImageFormat f, int q) {
+ SkFILEWStream file(path);
+ return file.isValid() && SkEncodeImage(&file, src, f, q);
+}
+
+bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
+void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
+
+class PixelIter {
+public:
+ PixelIter();
+ PixelIter(SkSurface* surf) {
+ SkPixmap pm;
+ if (!surf->peekPixels(&pm)) {
+ pm.reset();
+ }
+ this->reset(pm);
+ }
+
+ void reset(const SkPixmap& pm) {
+ fPM = pm;
+ fLoc = {-1, 0};
+ }
+
+ void* next(SkIPoint* loc = nullptr) {
+ if (!fPM.addr()) {
+ return nullptr;
+ }
+ fLoc.fX += 1;
+ if (fLoc.fX >= fPM.width()) {
+ fLoc.fX = 0;
+ if (++fLoc.fY >= fPM.height()) {
+ this->setDone();
+ return nullptr;
+ }
+ }
+ if (loc) {
+ *loc = fLoc;
+ }
+ return fPM.writable_addr(fLoc.fX, fLoc.fY);
+ }
+
+ void setDone() { fPM.reset(); }
+
+private:
+ SkPixmap fPM;
+ SkIPoint fLoc;
+};
+
+} // namespace ToolUtils
+
+#endif // ToolUtils_DEFINED
diff --git a/src/third_party/skia/tools/UrlDataManager.cpp b/src/third_party/skia/tools/UrlDataManager.cpp
index a30d8ba..40d909f 100644
--- a/src/third_party/skia/tools/UrlDataManager.cpp
+++ b/src/third_party/skia/tools/UrlDataManager.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "UrlDataManager.h"
+#include "tools/UrlDataManager.h"
bool operator==(const SkData& a, const SkData& b) {
return a.equals(&b);
diff --git a/src/third_party/skia/tools/UrlDataManager.h b/src/third_party/skia/tools/UrlDataManager.h
index bae1dc7..d68b119 100644
--- a/src/third_party/skia/tools/UrlDataManager.h
+++ b/src/third_party/skia/tools/UrlDataManager.h
@@ -8,10 +8,10 @@
#ifndef SkUrlDataManager_DEFINED
#define SkUrlDataManager_DEFINED
-#include "SkData.h"
-#include "SkOpts.h"
-#include "SkString.h"
-#include "SkTDynamicHash.h"
+#include "include/core/SkData.h"
+#include "include/core/SkString.h"
+#include "src/core/SkOpts.h"
+#include "src/core/SkTDynamicHash.h"
/*
* A simple class which allows clients to add opaque data types, and returns a url where this data
diff --git a/src/third_party/skia/tools/add_codereview_message.py b/src/third_party/skia/tools/add_codereview_message.py
index 296a894..ea4afd8 100755
--- a/src/third_party/skia/tools/add_codereview_message.py
+++ b/src/third_party/skia/tools/add_codereview_message.py
@@ -39,10 +39,10 @@
this url, or this could simply be the issue number.
message: (string) message to add.
"""
- # Passing None for the email and password will result in a prompt or
+ # Passing None for the email and auth_config will result in a prompt or
# reuse of existing cached credentials.
- my_rietveld = rietveld.Rietveld(RIETVELD_URL, email=None, password=None)
-
+ my_rietveld = rietveld.Rietveld(RIETVELD_URL, email=None, auth_config=None)
+
my_rietveld.add_comment(issue, message)
diff --git a/src/third_party/skia/tools/android/measure_fps.py b/src/third_party/skia/tools/android/measure_fps.py
new file mode 100644
index 0000000..7ec80dc
--- /dev/null
+++ b/src/third_party/skia/tools/android/measure_fps.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import optparse
+import re
+import subprocess
+import time
+
+
+def query_surfaceflinger_frame_count():
+ parcel = subprocess.Popen("adb shell service call SurfaceFlinger 1013",
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ shell=True).communicate()[0]
+ if not parcel:
+ raise Exception("FAILED: adb shell service call SurfaceFlinger 1013")
+
+ framecount = re.search("Result: Parcel\(([a-f0-9]+) ", parcel)
+ if not framecount:
+ raise Exception("Unexpected result from SurfaceFlinger: " + parcel)
+
+ return int(framecount.group(1), 16)
+
+
+def main(interval):
+ startframe = query_surfaceflinger_frame_count()
+ starttime = time.time()
+
+ while True:
+ time.sleep(interval)
+
+ endframe = query_surfaceflinger_frame_count()
+ endtime = time.time()
+ fps = (endframe - startframe) / (endtime - starttime)
+ print "%.2f" % fps
+
+ startframe = endframe
+ starttime = endtime
+
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser()
+ parser.add_option("-i", "--interval", type="int", default="2",
+ help="Number of seconds to count frames.")
+ options, args = parser.parse_args()
+ main(options.interval)
+
diff --git a/src/third_party/skia/tools/android/upload_to_android.py b/src/third_party/skia/tools/android/upload_to_android.py
new file mode 100644
index 0000000..dba0c16
--- /dev/null
+++ b/src/third_party/skia/tools/android/upload_to_android.py
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Script that uploads the specified Skia Gerrit change to Android.
+
+This script does the following:
+* Downloads the repo tool.
+* Inits and checks out the bare-minimum required Android checkout.
+* Sets the required git config options in external/skia.
+* Cherry-picks the specified Skia patch.
+* Modifies the change subject to append a "Test:" line required for presubmits.
+* Uploads the Skia change to Android's Gerrit instance.
+
+After the change is uploaded to Android, developers can trigger TH and download
+binaries (if required) after runs complete.
+
+The script re-uses the workdir when it is run again. To start from a clean slate
+delete the workdir.
+
+Timings:
+* ~1m15s when using an empty/non-existent workdir for the first time.
+* ~15s when using a workdir previously populated by the script.
+
+Example usage:
+ $ python upload_to_android.py -w /repos/testing -c 44200
+"""
+
+import argparse
+import getpass
+import json
+import os
+import subprocess
+import stat
+import urllib2
+
+
+REPO_TOOL_URL = 'https://storage.googleapis.com/git-repo-downloads/repo'
+SKIA_PATH_IN_ANDROID = os.path.join('external', 'skia')
+ANDROID_REPO_URL = 'https://googleplex-android.googlesource.com'
+REPO_BRANCH_NAME = 'experiment'
+SKIA_GERRIT_INSTANCE = 'https://skia-review.googlesource.com'
+SK_USER_CONFIG_PATH = os.path.join('include', 'config', 'SkUserConfig.h')
+
+
+def get_change_details(change_num):
+ response = urllib2.urlopen('%s/changes/%s/detail?o=ALL_REVISIONS' % (
+ SKIA_GERRIT_INSTANCE, change_num), timeout=5)
+ content = response.read()
+ # Remove the first line which contains ")]}'\n".
+ return json.loads(content[5:])
+
+
+def init_work_dir(work_dir):
+ if not os.path.isdir(work_dir):
+ print 'Creating %s' % work_dir
+ os.makedirs(work_dir)
+
+ # Ensure the repo tool exists in the work_dir.
+ repo_dir = os.path.join(work_dir, 'bin')
+ repo_binary = os.path.join(repo_dir, 'repo')
+ if not os.path.isdir(repo_dir):
+ print 'Creating %s' % repo_dir
+ os.makedirs(repo_dir)
+ if not os.path.exists(repo_binary):
+ print 'Downloading %s from %s' % (repo_binary, REPO_TOOL_URL)
+ response = urllib2.urlopen(REPO_TOOL_URL, timeout=5)
+ content = response.read()
+ with open(repo_binary, 'w') as f:
+ f.write(content)
+ # Set executable bit.
+ st = os.stat(repo_binary)
+ os.chmod(repo_binary, st.st_mode | stat.S_IEXEC)
+
+ # Create android-repo directory in the work_dir.
+ android_dir = os.path.join(work_dir, 'android-repo')
+ if not os.path.isdir(android_dir):
+ print 'Creating %s' % android_dir
+ os.makedirs(android_dir)
+
+ print """
+
+About to run repo init. If it hangs asking you to run glogin then please:
+* Exit the script (ctrl-c).
+* Run 'glogin'.
+* Re-run the script.
+
+"""
+ os.chdir(android_dir)
+ subprocess.check_call(
+ '%s init -u %s/a/platform/manifest -g "all,-notdefault,-darwin" '
+ '-b master --depth=1'
+ % (repo_binary, ANDROID_REPO_URL), shell=True)
+
+ print 'Syncing the Android checkout at %s' % android_dir
+ subprocess.check_call('%s sync %s tools/repohooks -j 32 -c' % (
+ repo_binary, SKIA_PATH_IN_ANDROID), shell=True)
+
+ # Set the necessary git config options.
+ os.chdir(SKIA_PATH_IN_ANDROID)
+ subprocess.check_call(
+ 'git config remote.goog.review %s/' % ANDROID_REPO_URL, shell=True)
+ subprocess.check_call(
+ 'git config review.%s/.autoupload true' % ANDROID_REPO_URL, shell=True)
+ subprocess.check_call(
+ 'git config user.email %s@google.com' % getpass.getuser(), shell=True)
+
+ return repo_binary
+
+
+class Modifier:
+ def modify(self):
+ raise NotImplementedError
+ def get_user_msg(self):
+ raise NotImplementedError
+
+
+class FetchModifier(Modifier):
+ def __init__(self, change_num, debug):
+ self.change_num = change_num
+ self.debug = debug
+
+ def modify(self):
+ # Download and cherry-pick the patch.
+ change_details = get_change_details(self.change_num)
+ latest_patchset = len(change_details['revisions'])
+ mod = int(self.change_num) % 100
+ download_ref = 'refs/changes/%s/%s/%s' % (
+ str(mod).zfill(2), self.change_num, latest_patchset)
+ subprocess.check_call(
+ 'git fetch https://skia.googlesource.com/skia %s' % download_ref,
+ shell=True)
+ subprocess.check_call('git cherry-pick FETCH_HEAD', shell=True)
+
+ if self.debug:
+ # Add SK_DEBUG to SkUserConfig.h.
+ with open(SK_USER_CONFIG_PATH, 'a') as f:
+ f.write('#ifndef SK_DEBUG\n')
+ f.write('#define SK_DEBUG\n')
+ f.write('#endif//SK_DEBUG\n')
+ subprocess.check_call('git add %s' % SK_USER_CONFIG_PATH, shell=True)
+
+ # Amend the commit message to add a prefix that makes it clear that the
+ # change should not be submitted and a "Test:" line which is required by
+ # Android presubmit checks.
+ original_commit_message = change_details['subject']
+ new_commit_message = (
+ # Intentionally breaking up the below string because some presubmits
+ # complain about it.
+ '[DO ' + 'NOT ' + 'SUBMIT] %s\n\n'
+ 'Test: Presubmit checks will test this change.' % (
+ original_commit_message))
+
+ subprocess.check_call('git commit --amend -m "%s"' % new_commit_message,
+ shell=True)
+
+ def get_user_msg(self):
+ return """
+
+Open the above URL and trigger TH by checking 'Presubmit-Ready'.
+You can download binaries (if required) from the TH link after it completes.
+"""
+
+
+# Add a legacy flag if it doesn't exist, or remove it if it exists.
+class AndroidLegacyFlagModifier(Modifier):
+ def __init__(self, flag):
+ self.flag = flag
+ self.verb = "Unknown"
+
+ def modify(self):
+ flag_line = " #define %s\n" % self.flag
+
+ config_file = os.path.join('include', 'config', 'SkUserConfigManual.h')
+
+ with open(config_file) as f:
+ lines = f.readlines()
+
+ if flag_line not in lines:
+ lines.insert(
+ lines.index("#endif // SkUserConfigManual_DEFINED\n"), flag_line)
+ verb = "Add"
+ else:
+ lines.remove(flag_line)
+ verb = "Remove"
+
+ with open(config_file, 'w') as f:
+ for line in lines:
+ f.write(line)
+
+ subprocess.check_call('git add %s' % config_file, shell=True)
+ message = '%s %s\n\nTest: Presubmit checks will test this change.' % (
+ verb, self.flag)
+
+ subprocess.check_call('git commit -m "%s"' % message, shell=True)
+
+ def get_user_msg(self):
+ return """
+
+ Please open the above URL to review and land the change.
+"""
+
+
+def upload_to_android(work_dir, modifier):
+ repo_binary = init_work_dir(work_dir)
+
+ # Create repo branch.
+ subprocess.check_call('%s start %s .' % (repo_binary, REPO_BRANCH_NAME),
+ shell=True)
+ try:
+ modifier.modify()
+
+ # Upload to Android Gerrit.
+ subprocess.check_call('%s upload --verify' % repo_binary, shell=True)
+
+ print modifier.get_user_msg()
+ finally:
+ # Abandon repo branch.
+ subprocess.call('%s abandon %s' % (repo_binary, REPO_BRANCH_NAME),
+ shell=True)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--work-dir', '-w', required=True,
+ help='Directory where an Android checkout will be created (if it does '
+ 'not already exist). Note: ~1GB space will be used.')
+ parser.add_argument(
+ '--change-num', '-c', required=True,
+ help='The skia-rev Gerrit change number that should be patched into '
+ 'Android.')
+ parser.add_argument(
+ '--debug', '-d', action='store_true', default=False,
+ help='Adds SK_DEBUG to SkUserConfig.h.')
+ args = parser.parse_args()
+ upload_to_android(args.work_dir, FetchModifier(args.change_num, args.debug))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/build_workaround_header.py b/src/third_party/skia/tools/build_workaround_header.py
new file mode 100755
index 0000000..f1d45de
--- /dev/null
+++ b/src/third_party/skia/tools/build_workaround_header.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# Copyright (c) 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""code generator for gpu workaround definitions"""
+
+import os
+import os.path
+import sys
+from optparse import OptionParser
+
+_LICENSE = """// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"""
+
+_DO_NOT_EDIT_WARNING = ("// This file is auto-generated from " +
+ os.path.basename(__file__) + "\n" +
+ "// DO NOT EDIT!\n\n")
+
+def merge_files_into_workarounds(files):
+ workarounds = set()
+ for filename in files:
+ with open(filename, 'r') as f:
+ workarounds.update([workaround.strip() for workaround in f])
+ return sorted(list(workarounds))
+
+
+def write_header(filename, workarounds):
+ max_workaround_len = len(max(workarounds, key=len))
+
+ with open(filename, 'w') as f:
+ f.write(_LICENSE)
+ f.write(_DO_NOT_EDIT_WARNING)
+
+ indent = ' '
+ macro = 'GPU_OP'
+
+ # length of max string passed to write + 1
+ max_len = len(indent) + len(macro) + 1 + max_workaround_len + 1 + 1
+ write = lambda line: f.write(line + ' ' * (max_len - len(line)) + '\\\n')
+
+ write('#define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)')
+ for w in workarounds:
+ write(indent + macro + '(' + w.upper() + ',')
+ write(indent + ' ' * (len(macro) + 1) + w + ')')
+
+ # one extra line to consume the the last \
+ f.write('// The End\n')
+
+
+def main(argv):
+ usage = "usage: %prog [options] file1 file2 file3 etc"
+ parser = OptionParser(usage=usage)
+ parser.add_option(
+ "--output-file",
+ dest="output_file",
+ default="gpu_driver_bug_workaround_autogen.h",
+ help="the name of the header file to write")
+
+ (options, _) = parser.parse_args(args=argv)
+
+ workarounds = merge_files_into_workarounds(parser.largs)
+ write_header(options.output_file, workarounds)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/src/third_party/skia/tools/calmbench/ab.py b/src/third_party/skia/tools/calmbench/ab.py
new file mode 100644
index 0000000..6a45fe4
--- /dev/null
+++ b/src/third_party/skia/tools/calmbench/ab.py
@@ -0,0 +1,407 @@
+#!/usr/bin/python
+# encoding: utf-8
+
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be found
+# in the LICENSE file.
+#
+# This is an A/B test utility script used by calmbench.py
+#
+# For each bench, we get a distribution of min_ms measurements from nanobench.
+# From that, we try to recover the 1/3 and 2/3 quantiles of the distribution.
+# If range (1/3 quantile, 2/3 quantile) is completely disjoint between A and B,
+# we report that as a regression.
+#
+# The more measurements we have for a bench, the more accurate our quantiles
+# are. However, taking more measurements is time consuming. Hence we'll prune
+# out benches and only take more measurements for benches whose current quantile
+# ranges are disjoint.
+#
+# P.S. The current script is brute forcely translated from a ruby script. So it
+# may be ugly...
+
+import re
+import os
+import sys
+import time
+import json
+import subprocess
+import shlex
+import multiprocessing
+import traceback
+from argparse import ArgumentParser
+from multiprocessing import Process
+from threading import Thread
+from threading import Lock
+from pdb import set_trace
+
+
+HELP = """
+\033[31mPlease call calmbench.py to drive this script if you're not doing so.
+This script is not supposed to be used by itself. (At least, it's not easy to
+use by itself. The calmbench bots may use this script directly.)
+\033[0m
+"""
+
+FACTOR = 3 # lower/upper quantile factor
+DIFF_T = 0.99 # different enough threshold
+TERM = 10 # terminate after this no. of iterations without suspect changes
+MAXTRY = 30 # max number of nanobench tries to narrow down suspects
+
+UNITS = "ns µs ms s".split()
+
+
+timesLock = Lock()
+timesA = {}
+timesB = {}
+
+
+def parse_args():
+ parser = ArgumentParser(description=HELP)
+
+ parser.add_argument('outdir', type=str, help="output directory")
+ parser.add_argument('a', type=str, help="name of A")
+ parser.add_argument('b', type=str, help="name of B")
+ parser.add_argument('nano_a', type=str, help="path to A's nanobench binary")
+ parser.add_argument('nano_b', type=str, help="path to B's nanobench binary")
+ parser.add_argument('arg_a', type=str, help="args for A's nanobench run")
+ parser.add_argument('arg_b', type=str, help="args for B's nanobench run")
+ parser.add_argument('repeat', type=int, help="number of initial runs")
+ parser.add_argument('skip_b', type=str, help=("whether to skip running B"
+ " ('true' or 'false')"))
+ parser.add_argument('config', type=str, help="nanobenh config")
+ parser.add_argument('threads', type=int, help="number of threads to run")
+ parser.add_argument('noinit', type=str, help=("whether to skip running B"
+ " ('true' or 'false')"))
+
+ parser.add_argument('--concise', dest='concise', action="store_true",
+ help="If set, no verbose thread info will be printed.")
+ parser.set_defaults(concise=False)
+
+ # Additional args for bots
+ BHELP = "bot specific options"
+ parser.add_argument('--githash', type=str, default="", help=BHELP)
+ parser.add_argument('--keys', type=str, default=[], nargs='+', help=BHELP)
+
+ args = parser.parse_args()
+ args.skip_b = args.skip_b == "true"
+ args.noinit = args.noinit == "true"
+
+ if args.threads == -1:
+ args.threads = 1
+ if args.config in ["8888", "565"]: # multi-thread for CPU only
+ args.threads = max(1, multiprocessing.cpu_count() / 2)
+
+ return args
+
+def append_dict_sorted_array(dict_array, key, value):
+ if key not in dict_array:
+ dict_array[key] = []
+ dict_array[key].append(value)
+ dict_array[key].sort()
+
+
+def add_time(args, name, bench, t, unit):
+ normalized_t = t * 1000 ** UNITS.index(unit);
+ if name.startswith(args.a):
+ append_dict_sorted_array(timesA, bench, normalized_t)
+ else:
+ append_dict_sorted_array(timesB, bench, normalized_t)
+
+
+def append_times_from_file(args, name, filename):
+ with open(filename) as f:
+ lines = f.readlines()
+ for line in lines:
+ items = line.split()
+ if len(items) > 10:
+ bench = items[10]
+ matches = re.search("([+-]?\d*.?\d+)(s|ms|µs|ns)", items[3])
+ if (not matches or items[9] != args.config):
+ continue
+ time_num = matches.group(1)
+ time_unit = matches.group(2)
+ add_time(args, name, bench, float(time_num), time_unit)
+
+
+class ThreadWithException(Thread):
+ def __init__(self, target):
+ super(ThreadWithException, self).__init__(target = target)
+ self.exception = None
+
+ def run(self):
+ try:
+ self._Thread__target(*self._Thread__args, **self._Thread__kwargs)
+ except BaseException as e:
+ self.exception = e
+
+ def join(self, timeout=None):
+ super(ThreadWithException, self).join(timeout)
+
+
+class ThreadRunner:
+ """Simplest and stupidiest threaded executer."""
+ def __init__(self, args):
+ self.concise = args.concise
+ self.threads = []
+
+ def add(self, args, fn):
+ if len(self.threads) >= args.threads:
+ self.wait()
+ t = ThreadWithException(target = fn)
+ t.daemon = True
+ self.threads.append(t)
+ t.start()
+
+ def wait(self):
+ def spin():
+ i = 0
+ spinners = [". ", ".. ", "..."]
+ while len(self.threads) > 0:
+ timesLock.acquire()
+ sys.stderr.write(
+ "\r" + spinners[i % len(spinners)] +
+ " (%d threads running)" % len(self.threads) +
+ " \r" # spaces for erasing characters
+ )
+ timesLock.release()
+ time.sleep(0.5)
+ i += 1
+
+ if not self.concise:
+ ts = Thread(target = spin);
+ ts.start()
+
+ for t in self.threads:
+ t.join()
+
+ exceptions = []
+ for t in self.threads:
+ if t.exception:
+ exceptions.append(t.exception)
+
+ self.threads = []
+
+ if not self.concise:
+ ts.join()
+
+ if len(exceptions):
+ for exc in exceptions:
+ print exc
+ raise exceptions[0]
+
+
+def split_arg(arg):
+ raw = shlex.split(arg)
+ result = []
+ for r in raw:
+ if '~' in r:
+ result.append(os.path.expanduser(r))
+ else:
+ result.append(r)
+ return result
+
+
+def run(args, threadRunner, name, nano, arg, i):
+ def task():
+ file_i = "%s/%s.out%d" % (args.outdir, name, i)
+
+ should_run = not args.noinit and not (name == args.b and args.skip_b)
+ if i <= 0:
+ should_run = True # always run for suspects
+
+ if should_run:
+ if i > 0:
+ timesLock.acquire()
+ print "Init run %d for %s..." % (i, name)
+ timesLock.release()
+ subprocess.check_call(["touch", file_i])
+ with open(file_i, 'w') as f:
+ subprocess.check_call([nano] + split_arg(arg) +
+ ["--config", args.config], stderr=f, stdout=f)
+
+ timesLock.acquire()
+ append_times_from_file(args, name, file_i)
+ timesLock.release()
+
+ threadRunner.add(args, task)
+
+
+def init_run(args):
+ threadRunner = ThreadRunner(args)
+ for i in range(1, max(args.repeat, args.threads / 2) + 1):
+ run(args, threadRunner, args.a, args.nano_a, args.arg_a, i)
+ run(args, threadRunner, args.b, args.nano_b, args.arg_b, i)
+ threadRunner.wait()
+
+
+def get_lower_upper(values):
+ i = max(0, (len(values) - 1) / FACTOR)
+ return values[i], values[-i - 1]
+
+
+def different_enough(lower1, upper2):
+ return upper2 < DIFF_T * lower1
+
+
+# TODO(liyuqian): we used this hacky criteria mainly because that I didn't have
+# time to study more rigorous statistical tests. We should adopt a more rigorous
+# test in the future.
+def get_suspects():
+ suspects = []
+ for bench in timesA.keys():
+ if bench not in timesB:
+ continue
+ lowerA, upperA = get_lower_upper(timesA[bench])
+ lowerB, upperB = get_lower_upper(timesB[bench])
+ if different_enough(lowerA, upperB) or different_enough(lowerB, upperA):
+ suspects.append(bench)
+ return suspects
+
+
+def process_bench_pattern(s):
+ if ".skp" in s: # skp bench won't match their exact names...
+ return "^\"" + s[0:(s.index(".skp") + 3)] + "\""
+ else:
+ return "^\"" + s + "\"$"
+
+
+def suspects_arg(suspects):
+ patterns = map(process_bench_pattern, suspects)
+ return " --match " + (" ".join(patterns))
+
+
+def median(array):
+ return array[len(array) / 2]
+
+
+def regression(bench):
+ a = median(timesA[bench])
+ b = median(timesB[bench])
+ if (a == 0): # bad bench, just return no regression
+ return 1
+ return b / a
+
+
+def percentage(x):
+ return (x - 1) * 100
+
+
+def format_r(r):
+ return ('%6.2f' % percentage(r)) + "%"
+
+
+def normalize_r(r):
+ if r > 1.0:
+ return r - 1.0
+ else:
+ return 1.0 - 1/r
+
+
+def test():
+ args = parse_args()
+
+ init_run(args)
+ last_unchanged_iter = 0
+ last_suspect_number = -1
+ tryCnt = 0
+ it = 0
+ while tryCnt < MAXTRY:
+ it += 1
+ suspects = get_suspects()
+ if len(suspects) != last_suspect_number:
+ last_suspect_number = len(suspects)
+ last_unchanged_iter = it
+ if (len(suspects) == 0 or it - last_unchanged_iter >= TERM):
+ break
+
+ print "Number of suspects at iteration %d: %d" % (it, len(suspects))
+ threadRunner = ThreadRunner(args)
+ for j in range(1, max(1, args.threads / 2) + 1):
+ run(args, threadRunner, args.a, args.nano_a,
+ args.arg_a + suspects_arg(suspects), -j)
+ run(args, threadRunner, args.b, args.nano_b,
+ args.arg_b + suspects_arg(suspects), -j)
+ tryCnt += 1
+ threadRunner.wait()
+
+ suspects = get_suspects()
+ if len(suspects) == 0:
+ print ("%s and %s does not seem to have significant " + \
+ "performance differences.") % (args.a, args.b)
+ else:
+ suspects.sort(key = regression)
+ print "%s (compared to %s) is likely" % (args.a, args.b)
+ for suspect in suspects:
+ r = regression(suspect)
+ if r < 1:
+ print "\033[31m %s slower in %s\033[0m" % \
+ (format_r(1/r), suspect)
+ else:
+ print "\033[32m %s faster in %s\033[0m" % \
+ (format_r(r), suspect)
+
+ with open("%s/bench_%s_%s.json" % (args.outdir, args.a, args.b), 'w') as f:
+ results = {}
+ for bench in timesA:
+ r = regression(bench) if bench in suspects else 1.0
+ results[bench] = {
+ args.config: {
+ "signed_regression": normalize_r(r),
+ "lower_quantile_ms": get_lower_upper(timesA[bench])[0] * 1e-6,
+ "upper_quantile_ms": get_lower_upper(timesA[bench])[1] * 1e-6,
+ "options": {
+ # TODO(liyuqian): let ab.py call nanobench with --outResultsFile so
+ # nanobench could generate the json for us that's exactly the same
+ # as that being used by perf bots. Currently, we cannot guarantee
+ # that bench is the name (e.g., bench may have additional resolution
+ # information appended after name).
+ "name": bench
+ }
+ }
+ }
+
+ output = {"results": results}
+ if args.githash:
+ output["gitHash"] = args.githash
+ if args.keys:
+ keys = {}
+ for i in range(len(args.keys) / 2):
+ keys[args.keys[i * 2]] = args.keys[i * 2 + 1]
+ output["key"] = keys
+ f.write(json.dumps(output, indent=4))
+ print ("\033[36mJSON results available in %s\033[0m" % f.name)
+
+ with open("%s/bench_%s_%s.csv" % (args.outdir, args.a, args.b), 'w') as out:
+ out.write(("bench, significant?, raw regresion, " +
+ "%(A)s quantile (ns), %(B)s quantile (ns), " +
+ "%(A)s (ns), %(B)s (ns)\n") % {'A': args.a, 'B': args.b})
+ for bench in suspects + timesA.keys():
+ if (bench not in timesA or bench not in timesB):
+ continue
+ ta = timesA[bench]
+ tb = timesB[bench]
+ out.write(
+ "%s, %s, %f, " % (bench, bench in suspects, regression(bench)) +
+ ' '.join(map(str, get_lower_upper(ta))) + ", " +
+ ' '.join(map(str, get_lower_upper(tb))) + ", " +
+ ("%s, %s\n" % (' '.join(map(str, ta)), ' '.join(map(str, tb))))
+ )
+ print (("\033[36m" +
+ "Compared %d benches. " +
+ "%d of them seem to be significantly differrent." +
+ "\033[0m") %
+ (len([x for x in timesA if x in timesB]), len(suspects)))
+ print ("\033[36mPlease see detailed bench results in %s\033[0m" %
+ out.name)
+
+
+if __name__ == "__main__":
+ try:
+ test()
+ except Exception as e:
+ print e
+ print HELP
+ traceback.print_exc()
+ raise e
diff --git a/src/third_party/skia/tools/calmbench/calmbench.py b/src/third_party/skia/tools/calmbench/calmbench.py
new file mode 100644
index 0000000..4bef485
--- /dev/null
+++ b/src/third_party/skia/tools/calmbench/calmbench.py
@@ -0,0 +1,216 @@
+#!/usr/bin/pyton
+
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import subprocess
+import multiprocessing
+
+from argparse import ArgumentParser
+
+
+README = """
+Simply run
+\033[36m
+ python {0} TEST_GIT_BRANCH
+\033[0m
+to see if TEST_GIT_BRANCH has performance regressions against master in 8888.
+
+To compare a specific config with svg and skp resources included, add --config
+and --extraarg option. For exampe,
+\033[36m
+ python {0} TEST_GIT_BRANCH --config gl \\
+ --extraarg "--svgs ~/Desktop/bots/svgs --skps ~/Desktop/bots/skps"
+\033[0m
+For more options, please see
+
+ python {0} --help
+""".format(__file__)
+
+
+CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
+AB_SCRIPT = "ab.py"
+
+
+def parse_args():
+ if len(sys.argv) <= 1 or sys.argv[1] == '-h' or sys.argv[1] == '--help':
+ print README
+
+ parser = ArgumentParser(
+ description='Noiselessly (hence calm) becnhmark a git branch against ' +
+ 'another baseline branch (e.g., master) using multiple ' +
+ ' nanobench runs.'
+ )
+
+ default_threads = max(1, multiprocessing.cpu_count() / 2);
+ default_skiadir = os.path.normpath(CURRENT_DIR + "/../../")
+
+ config_help = (
+ 'nanobench config; we currently support only one config '
+ 'at a time (default: %(default)s)')
+ reps_help = (
+ 'initial repititions of the nanobench run; this may be '
+ 'overridden when we have many threads (default: %(default)s)')
+ extraarg_help = (
+ 'nanobench args (example: --svgs ~/Desktop/bots/svgs --skps '
+ '~/Desktop/bots/skps)')
+ baseline_help = (
+ 'baseline branch to compare against (default: %(default)s)')
+ basearg_help = (
+ 'nanobench arg for the baseline branch; if not given, we use '
+ ' the same arg for both the test branch and the baseline branch')
+ threads_help = (
+ 'number of threads to be used (default: %(default)s); '
+ 'for GPU config, this will always be 1')
+ no_compile_help = (
+ 'whether NOT to compile nanobench and copy it to WRITEDIR '
+ '(i.e., reuse previous nanobench compiled)')
+ skip_base_help = (
+ 'whether NOT to run nanobench on baseline branch '
+ '(i.e., reuse previous baseline measurements)')
+ noinit_help = (
+ 'whether to skip initial nanobench runs (default: %(default)s)')
+ branch_help = (
+ "the test branch to benchmark; if it's 'modified', we'll benchmark the "
+ "current modified code against 'git stash'.")
+
+ definitions = [
+ # argname, type, default value, help
+ ['--config', str, '8888', config_help],
+ ['--skiadir', str, default_skiadir, 'default: %(default)s'],
+ ['--ninjadir', str, 'out/Release', 'default: %(default)s'],
+ ['--writedir', str, '/var/tmp', 'default: %(default)s'],
+ ['--extraarg', str, '', extraarg_help],
+ ['--baseline', str, 'master', baseline_help],
+ ['--basearg', str, '', basearg_help],
+ ['--reps', int, 2, reps_help],
+ ['--threads', int, default_threads, threads_help],
+ ]
+
+ for d in definitions:
+ parser.add_argument(d[0], type=d[1], default=d[2], help=d[3])
+
+ parser.add_argument('branch', type=str, help=branch_help)
+ parser.add_argument('--no-compile', dest='no_compile', action="store_true",
+ help=no_compile_help)
+ parser.add_argument('--skip-base', dest='skipbase', action="store_true",
+ help=skip_base_help)
+ parser.add_argument('--noinit', dest='noinit', action="store_true",
+ help=noinit_help)
+ parser.add_argument('--concise', dest='concise', action="store_true",
+ help="If set, no verbose thread info will be printed.")
+ parser.set_defaults(no_compile=False);
+ parser.set_defaults(skipbase=False);
+ parser.set_defaults(noinit=False);
+ parser.set_defaults(concise=False);
+
+ # Additional args for bots
+ BHELP = "bot specific options"
+ parser.add_argument('--githash', type=str, help=BHELP)
+ parser.add_argument('--keys', type=str, default=[], nargs='+', help=BHELP)
+
+ args = parser.parse_args()
+ if not args.basearg:
+ args.basearg = args.extraarg
+
+ return args
+
+
+def nano_path(args, branch):
+ return args.writedir + '/nanobench_' + branch
+
+
+def compile_branch(args, branch):
+ print "Compiling branch %s" % args.branch
+
+ commands = [
+ ['git', 'checkout', branch],
+ ['ninja', '-C', args.ninjadir, 'nanobench'],
+ ['cp', args.ninjadir + '/nanobench', nano_path(args, branch)]
+ ]
+ for command in commands:
+ subprocess.check_call(command, cwd=args.skiadir)
+
+
+def compile_modified(args):
+ print "Compiling modified code"
+ subprocess.check_call(
+ ['ninja', '-C', args.ninjadir, 'nanobench'], cwd=args.skiadir)
+ subprocess.check_call(
+ ['cp', args.ninjadir + '/nanobench', nano_path(args, args.branch)],
+ cwd=args.skiadir)
+
+ print "Compiling stashed code"
+ stash_output = subprocess.check_output(['git', 'stash'], cwd=args.skiadir)
+ if 'No local changes to save' in stash_output:
+ subprocess.check_call(['git', 'reset', 'HEAD^', '--soft'])
+ subprocess.check_call(['git', 'stash'])
+
+ subprocess.check_call(['gclient', 'sync'], cwd=args.skiadir)
+ subprocess.check_call(
+ ['ninja', '-C', args.ninjadir, 'nanobench'], cwd=args.skiadir)
+ subprocess.check_call(
+ ['cp', args.ninjadir + '/nanobench', nano_path(args, args.baseline)],
+ cwd=args.skiadir)
+ subprocess.check_call(['git', 'stash', 'pop'], cwd=args.skiadir)
+
+def compile_nanobench(args):
+ if args.branch == 'modified':
+ compile_modified(args)
+ else:
+ compile_branch(args, args.branch)
+ compile_branch(args, args.baseline)
+
+
+def main():
+ args = parse_args()
+
+ # copy in case that it will be gone after git branch switching
+ orig_ab_name = CURRENT_DIR + "/" + AB_SCRIPT
+ temp_ab_name = args.writedir + "/" + AB_SCRIPT
+ subprocess.check_call(['cp', orig_ab_name, temp_ab_name])
+
+ if not args.no_compile:
+ compile_nanobench(args)
+
+ command = [
+ 'python',
+ temp_ab_name,
+ args.writedir,
+ args.branch + ("_A" if args.branch == args.baseline else ""),
+ args.baseline + ("_B" if args.branch == args.baseline else ""),
+ nano_path(args, args.branch),
+ nano_path(args, args.baseline),
+ args.extraarg,
+ args.basearg,
+ str(args.reps),
+ "true" if args.skipbase else "false",
+ args.config,
+ str(args.threads if args.config in ["8888", "565"] else 1),
+ "true" if args.noinit else "false"
+ ]
+
+ if args.githash:
+ command += ['--githash', args.githash]
+ if args.keys:
+ command += (['--keys'] + args.keys)
+
+ if args.concise:
+ command.append("--concise")
+
+ p = subprocess.Popen(command, cwd=args.skiadir)
+ try:
+ p.wait()
+ except KeyboardInterrupt:
+ try:
+ p.terminate()
+ except OSError as e:
+ print e
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/third_party/skia/tools/check-headers-self-sufficient b/src/third_party/skia/tools/check-headers-self-sufficient
index 9b676c1..8ecb76b 100755
--- a/src/third_party/skia/tools/check-headers-self-sufficient
+++ b/src/third_party/skia/tools/check-headers-self-sufficient
@@ -5,9 +5,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import fnmatch
import multiprocessing
import os
+import re
import subprocess
import sys
@@ -18,118 +18,55 @@
Otherwise, test all checked-in headers except for those in the ignore list.
'''
-public_header_args = [
- '-Iinclude/core',
- '-Iinclude/config',
- '-Iinclude/android',
- '-Iinclude/codec',
- '-Iinclude/effects',
- '-Iinclude/gpu',
- '-Iinclude/gpu/gl',
- '-Iinclude/pathops',
- '-Iinclude/ports',
- '-Iinclude/private',
- '-Iinclude/svg',
- '-Iinclude/utils',
- '-Iinclude/utils/mac',
- '-Iinclude/views',
- '-Ithird_party/vulkan',
-]
+ignore = re.compile('|'.join([
+ r'debugger/QT/.*',
+ r'example/.*',
+ r'experimental/.*',
+ r'include/config/.*',
+ r'include/core/SkPostConfig\.h',
+ r'include/gpu/mtl/.*',
+ r'include/gpu/vk/.*',
+ r'include/ports/SkFontMgr_android\.h',
+ r'include/ports/SkFontMgr_fontconfig\.h',
+ r'include/ports/SkFontMgr_fuchsia\.h',
+ r'include/ports/SkTypeface_win\.h',
+ r'include/private/.*_impl\.h',
+ r'include/private/.*_neon\.h',
+ r'include/private/.*_sse\.h',
+ r'include/third_party/vulkan/.*',
+ r'include/utils/mac/SkCGUtils\.h',
+ r'include/views/SkOSWindow_.*\.h',
+ r'modules/.*',
+ r'platform_tools/.*',
+ r'src/c/sk_c_from_to\.h',
+ r'src/core/.*Template\.h',
+ r'src/core/SkBitmapProcState_.*\.h',
+ r'src/core/SkLinearBitmapPipeline\.h',
+ r'src/core/SkLinearBitmapPipeline_.*\.h',
+ r'src/gpu/mtl/.*',
+ r'src/gpu/vk/.*',
+ r'src/opts/.*_SSE2\.h',
+ r'src/opts/.*_SSSE3\.h',
+ r'src/opts/.*_neon\.h',
+ r'src/opts/.*_sse\.h',
+ r'src/opts/Sk4px_.*\.h',
+ r'src/ports/.*',
+ r'src/utils/.*_win\.h',
+ r'src/utils/win/.*',
+ r'src/views/.*',
+ r'third_party/.*',
+ r'tools/fiddle/.*',
+ r'tools/gpu/vk/.*',
+ r'tools/mdbviz/.*',
+ r'tools/sk_app/.*',
+ r'tools/viewer/.*',
+ ]))
-all_header_args = [
- '-Iinclude/core',
- '-Iinclude/config',
- '-Iinclude/android',
- '-Iinclude/c',
- '-Iinclude/codec',
- '-Iinclude/effects',
- '-Iinclude/gpu',
- '-Iinclude/gpu/gl',
- '-Iinclude/pathops',
- '-Iinclude/ports',
- '-Iinclude/private',
- '-Iinclude/svg',
- '-Iinclude/utils',
- '-Iinclude/utils/mac',
- '-Iinclude/views',
- '-Isrc/codec',
- '-Isrc/core',
- '-Isrc/effects',
- '-Isrc/effects/gradients',
- '-Isrc/fonts',
- '-Isrc/gpu',
- '-Isrc/image',
- '-Isrc/images',
- '-Isrc/lazy',
- '-Isrc/opts',
- '-Isrc/pathops',
- '-Isrc/ports',
- '-Isrc/sfnt',
- '-Isrc/shaders',
- '-Isrc/sksl',
- '-Isrc/utils',
- '-Isrc/utils/win',
- '-Isrc/xml',
- '-Igm',
- '-Itests',
- '-Itools',
- '-Itools/debugger',
- '-Itools/flags',
- '-Itools/gpu',
- '-Itools/timer',
- '-Ithird_party/etc1',
- '-Ithird_party/externals/jsoncpp/include',
- '-Ithird_party/externals/libjpeg-turbo',
- '-Ithird_party/externals/sfntly/cpp/src',
- '-Ithird_party/externals/zlib',
- '-Ithird_party/gif',
- '-Ithird_party/vulkan',
-]
-
-ignore = [
- '*/lex.*.h',
- '*/osmesa_wrapper.h',
- 'debugger/QT/*',
- 'example/*',
- 'experimental/*',
- 'include/config/*',
- 'include/core/SkPostConfig.h',
- 'include/gpu/vk/*',
- 'include/ports/SkFontMgr_android.h',
- 'include/ports/SkFontMgr_fontconfig.h',
- 'include/ports/SkTypeface_win.h',
- 'include/private/*_impl.h',
- 'include/utils/mac/SkCGUtils.h',
- 'include/views/SkOSWindow_*.h',
- 'src/c/sk_c_from_to.h',
- 'src/core/*Template.h',
- 'src/core/SkBitmapProcState_*.h',
- 'src/core/SkFDot6Constants.h',
- 'src/core/SkLinearBitmapPipeline.h',
- 'src/core/SkLinearBitmapPipeline_*.h',
- 'src/core/SkUnPreMultiplyPriv.h',
- 'src/gpu/vk/*',
- 'src/opts/*_SSE2.h',
- 'src/opts/*_SSSE3.h',
- 'src/opts/*_neon.h',
- 'src/opts/*_sse.h',
- 'src/opts/Sk4px_*.h',
- 'src/ports/*',
- 'src/utils/*_win.h',
- 'src/utils/win/*',
- 'src/views/*',
- 'third_party/*',
- 'tools/fiddle/*',
- 'tools/viewer/*',
-]
# test header for self-sufficiency and idempotency.
# Returns a string containing errors, or None iff there are no errors.
def compile_header(header):
- args = ([] if fnmatch.fnmatch(header, 'include/c/*') else
- public_header_args if fnmatch.fnmatch(header, 'include/*') else
- all_header_args)
- cmd = ['c++', '--std=c++11'] + args + [ '-o', '/dev/null', '-c', '-x', 'c++', '-']
+ cmd = ['c++', '--std=c++14', '-I.', '-o', '/dev/null', '-c', '-x', 'c++', '-']
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
proc.stdin.write('#include "%s"\n#include "%s"\n' % (header, header))
@@ -139,6 +76,7 @@
return '\n\033[7m ERROR: %s \033[0m\n%s\n\n' % (header, errors)
return None
+
# for h in headers:
# compile_header(h)
# ...Except use a multiprocessing pool.
@@ -171,8 +109,7 @@
else:
os.chdir(skia_dir)
paths = [path for path in subprocess.check_output(['git', 'ls-files']).splitlines()
- if path.endswith('.h')
- and not any(fnmatch.fnmatch(path, pattern) for pattern in ignore)]
+ if path.endswith('.h') and not ignore.match(path)]
compile_headers(paths)
diff --git a/src/third_party/skia/tools/chrome_fuzz.cpp b/src/third_party/skia/tools/chrome_fuzz.cpp
index fcc0db2..3ae775e 100644
--- a/src/third_party/skia/tools/chrome_fuzz.cpp
+++ b/src/third_party/skia/tools/chrome_fuzz.cpp
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "SkCanvas.h"
+#include "include/core/SkCanvas.h"
#include "SkFlattenableSerialization.h"
-#include "SkImageFilter.h"
-#include "SkOSFile.h"
-#include "SkString.h"
+#include "include/core/SkImageFilter.h"
+#include "include/core/SkString.h"
+#include "src/core/SkOSFile.h"
#include <stdio.h>
diff --git a/src/third_party/skia/tools/chrome_release_branch b/src/third_party/skia/tools/chrome_release_branch
new file mode 100755
index 0000000..8a6cffc
--- /dev/null
+++ b/src/third_party/skia/tools/chrome_release_branch
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+base_dir=$(dirname "$0")
+
+PYTHONDONTWRITEBYTECODE=1 exec python -u "$base_dir/chrome_release_branch.py" "$@"
diff --git a/src/third_party/skia/tools/chrome_release_branch.bat b/src/third_party/skia/tools/chrome_release_branch.bat
new file mode 100644
index 0000000..1f61fe2
--- /dev/null
+++ b/src/third_party/skia/tools/chrome_release_branch.bat
@@ -0,0 +1,7 @@
+@echo off
+:: Copyright 2019 Google Inc.
+::
+:: Use of this source code is governed by a BSD-style license that can be
+:: found in the LICENSE file.
+setlocal
+python -u "%~dp0\chrome_release_branch.py" %*
diff --git a/src/third_party/skia/tools/chrome_release_branch.py b/src/third_party/skia/tools/chrome_release_branch.py
new file mode 100644
index 0000000..d9085aa
--- /dev/null
+++ b/src/third_party/skia/tools/chrome_release_branch.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import os
+import re
+import subprocess
+import sys
+
+from infra import git
+from infra import go
+
+_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
+_REPO_ROOT = os.path.realpath(os.path.join(_TOOLS_DIR, os.pardir))
+_INFRA_BOTS = os.path.join(_REPO_ROOT, 'infra', 'bots')
+sys.path.insert(0, _INFRA_BOTS)
+import git_utils
+
+
+REFS_HEADS_PREFIX = 'refs/heads/'
+CHROME_REF_PREFIX = REFS_HEADS_PREFIX + 'chrome/m'
+SK_MILESTONE_H = os.path.join('include', 'core', 'SkMilestone.h')
+SK_MILESTONE_TMPL = r'#define SK_MILESTONE %s'
+SK_MILESTONE_RE = SK_MILESTONE_TMPL % r'(\d+)'
+SKIA_REPO = 'https://skia.googlesource.com/skia.git'
+SUPPORTED_CHROME_BRANCHES = 2 # Per infra policy; see skbug.com/8940
+UPDATE_MILESTONE_COMMIT_MSG = '''Update Skia milestone to %d'''
+
+
+def get_current_milestone():
+ '''Read SkMilestone.h and parse out the current milestone.'''
+ sk_milestone = os.path.join(_REPO_ROOT, SK_MILESTONE_H)
+ with open(sk_milestone, 'r') as f:
+ contents = f.read()
+ for line in contents.splitlines():
+ m = re.match(SK_MILESTONE_RE, line)
+ if m:
+ return int(m.groups()[0])
+ print >> sys.stderr, (
+ 'Failed to parse %s; has the format changed?' % SK_MILESTONE_H)
+ sys.exit(1)
+
+
+def create_new_branch(new_branch, branch_at):
+ '''Create a temporary checkout of the repo, create the new branch and push.'''
+ b = new_branch[len(REFS_HEADS_PREFIX):]
+ with git_utils.NewGitCheckout(SKIA_REPO, local=_REPO_ROOT):
+ git.git('checkout', '-b', b)
+ git.git('reset', '--hard', branch_at)
+ git.git('push', '--set-upstream', 'origin', b)
+
+
+def update_milestone(m):
+ '''Update SkMilestone.h to match the given milestone number.'''
+ with git_utils.NewGitCheckout(SKIA_REPO, local=_REPO_ROOT):
+ with git_utils.GitBranch(
+ 'update_milestone', UPDATE_MILESTONE_COMMIT_MSG % m):
+ with open(SK_MILESTONE_H, 'r+') as f:
+ contents = re.sub(
+ SK_MILESTONE_RE, SK_MILESTONE_TMPL % str(m), f.read(), flags=re.M)
+ f.seek(0)
+ f.write(contents)
+ f.truncate()
+ git.git('diff')
+
+
+def update_infra_config(old_branch, new_branch):
+ '''Create a CL to add infra support for the new branch and remove the old.'''
+ owner = git.git('config', 'user.email').rstrip()
+ if not owner:
+ print >> sys.stderr, ('No configured git user; please run '
+ '"git config user.email <your email>".')
+ sys.exit(1)
+ go.get(go.INFRA_GO+'/go/supported_branches/cmd/new-branch')
+ subprocess.check_call(['new-branch',
+ '--branch', new_branch[len(REFS_HEADS_PREFIX):],
+ '--delete', old_branch[len(REFS_HEADS_PREFIX):],
+ '--owner', owner,
+ '--exclude-trybots=chromium.*',
+ '--exclude-trybots=.*Android_Framework.*'])
+
+
+def main():
+ if len(sys.argv) != 2 or '--help' in sys.argv or '-h' in sys.argv:
+ print >> sys.stderr, 'Usage: %s <commit hash for branch>' % sys.argv[0]
+ sys.exit(1)
+ go.check()
+ branch_at = sys.argv[1]
+ m = get_current_milestone()
+ new_branch = '%s%d' % (CHROME_REF_PREFIX, m)
+ old_branch = '%s%d' % (CHROME_REF_PREFIX, m-SUPPORTED_CHROME_BRANCHES)
+ print 'Creating branch %s and removing support (eg. CQ) for %s' % (
+ new_branch, old_branch)
+ create_new_branch(new_branch, branch_at)
+ update_milestone(m+1)
+ update_infra_config(old_branch, new_branch)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/clang-tidy.sh b/src/third_party/skia/tools/clang-tidy.sh
new file mode 100755
index 0000000..addbee3
--- /dev/null
+++ b/src/third_party/skia/tools/clang-tidy.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2018 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+set -e
+
+args=""
+src=""
+
+while [ "$1" ]; do
+ arg=$1
+
+ args="$args $1"
+ shift
+
+ if [ "$arg" == "-c" ]; then
+ src=$1
+
+ args="$args $1"
+ shift
+ fi
+done
+
+if [ "$src" ]; then
+ clang-tidy -quiet -header-filter='.*' -warnings-as-errors='*' $src -- $args
+fi
+exec clang++ $args
+
diff --git a/src/third_party/skia/tools/colorspaceinfo.cpp b/src/third_party/skia/tools/colorspaceinfo.cpp
deleted file mode 100644
index 0542d88..0000000
--- a/src/third_party/skia/tools/colorspaceinfo.cpp
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Resources.h"
-
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkCodec.h"
-#include "SkColorSpace_A2B.h"
-#include "SkColorSpace_XYZ.h"
-#include "SkColorSpacePriv.h"
-#include "SkCommandLineFlags.h"
-#include "SkICCPriv.h"
-#include "SkImageEncoder.h"
-#include "SkMatrix44.h"
-#include "SkOSFile.h"
-
-#include "sk_tool_utils.h"
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-DEFINE_string(input, "input.png", "A path to the input image (or icc profile with --icc).");
-DEFINE_string(output, ".", "A path to the output image directory.");
-DEFINE_bool(icc, false, "Indicates that the input is an icc profile.");
-DEFINE_bool(sRGB_gamut, false, "Draws the sRGB gamut on the gamut visualization.");
-DEFINE_bool(adobeRGB, false, "Draws the Adobe RGB gamut on the gamut visualization.");
-DEFINE_bool(sRGB_gamma, false, "Draws the sRGB gamma on all gamma output images.");
-DEFINE_string(uncorrected, "", "A path to reencode the uncorrected input image.");
-
-
-//-------------------------------------------------------------------------------------------------
-//------------------------------------ Gamma visualizations ---------------------------------------
-
-static const char* kRGBChannelNames[3] = {
- "Red ",
- "Green",
- "Blue "
-};
-static const SkColor kRGBChannelColors[3] = {
- SkColorSetARGB(128, 255, 0, 0),
- SkColorSetARGB(128, 0, 255, 0),
- SkColorSetARGB(128, 0, 0, 255)
-};
-
-static const char* kGrayChannelNames[1] = { "Gray"};
-static const SkColor kGrayChannelColors[1] = { SkColorSetRGB(128, 128, 128) };
-
-static const char* kCMYKChannelNames[4] = {
- "Cyan ",
- "Magenta",
- "Yellow ",
- "Black "
-};
-static const SkColor kCMYKChannelColors[4] = {
- SkColorSetARGB(128, 0, 255, 255),
- SkColorSetARGB(128, 255, 0, 255),
- SkColorSetARGB(128, 255, 255, 0),
- SkColorSetARGB(128, 16, 16, 16)
-};
-
-static const char*const*const kChannelNames[4] = {
- kGrayChannelNames,
- kRGBChannelNames,
- kRGBChannelNames,
- kCMYKChannelNames
-};
-static const SkColor*const kChannelColors[4] = {
- kGrayChannelColors,
- kRGBChannelColors,
- kRGBChannelColors,
- kCMYKChannelColors
-};
-
-static void dump_transfer_fn(SkGammaNamed gammaNamed) {
- switch (gammaNamed) {
- case kSRGB_SkGammaNamed:
- SkDebugf("Transfer Function: sRGB\n");
- return;
- case k2Dot2Curve_SkGammaNamed:
- SkDebugf("Exponential Transfer Function: Exponent 2.2\n");
- return;
- case kLinear_SkGammaNamed:
- SkDebugf("Transfer Function: Linear\n");
- return;
- default:
- break;
- }
-
-}
-
-static constexpr int kGammaImageWidth = 500;
-static constexpr int kGammaImageHeight = 500;
-
-static void dump_transfer_fn(const SkGammas& gammas) {
- SkASSERT(gammas.channels() <= 4);
- const char*const*const channels = kChannelNames[gammas.channels() - 1];
- for (int i = 0; i < gammas.channels(); i++) {
- if (gammas.isNamed(i)) {
- switch (gammas.data(i).fNamed) {
- case kSRGB_SkGammaNamed:
- SkDebugf("%s Transfer Function: sRGB\n", channels[i]);
- return;
- case k2Dot2Curve_SkGammaNamed:
- SkDebugf("%s Transfer Function: Exponent 2.2\n", channels[i]);
- return;
- case kLinear_SkGammaNamed:
- SkDebugf("%s Transfer Function: Linear\n", channels[i]);
- return;
- default:
- SkASSERT(false);
- continue;
- }
- } else if (gammas.isValue(i)) {
- SkDebugf("%s Transfer Function: Exponent %.3f\n", channels[i], gammas.data(i).fValue);
- } else if (gammas.isParametric(i)) {
- const SkColorSpaceTransferFn& fn = gammas.data(i).params(&gammas);
- SkDebugf("%s Transfer Function: Parametric A = %.3f, B = %.3f, C = %.3f, D = %.3f, "
- "E = %.3f, F = %.3f, G = %.3f\n", channels[i], fn.fA, fn.fB, fn.fC, fn.fD,
- fn.fE, fn.fF, fn.fG);
- } else {
- SkASSERT(gammas.isTable(i));
- SkDebugf("%s Transfer Function: Table (%d entries)\n", channels[i],
- gammas.data(i).fTable.fSize);
- }
- }
-}
-
-static inline float parametric(const SkColorSpaceTransferFn& fn, float x) {
- return x >= fn.fD ? powf(fn.fA*x + fn.fB, fn.fG) + fn.fE
- : fn.fC*x + fn.fF;
-}
-
-static void draw_transfer_fn(SkCanvas* canvas, SkGammaNamed gammaNamed, const SkGammas* gammas,
- SkColor color) {
- SkColorSpaceTransferFn fn[4];
- struct TableInfo {
- const float* fTable;
- int fSize;
- };
- TableInfo table[4];
- bool isTable[4] = {false, false, false, false};
- const int channels = gammas ? gammas->channels() : 1;
- SkASSERT(channels <= 4);
- if (kNonStandard_SkGammaNamed != gammaNamed) {
- dump_transfer_fn(gammaNamed);
- for (int i = 0; i < channels; ++i) {
- named_to_parametric(&fn[i], gammaNamed);
- }
- } else {
- SkASSERT(gammas);
- dump_transfer_fn(*gammas);
- for (int i = 0; i < channels; ++i) {
- if (gammas->isTable(i)) {
- table[i].fTable = gammas->table(i);
- table[i].fSize = gammas->data(i).fTable.fSize;
- isTable[i] = true;
- } else {
- switch (gammas->type(i)) {
- case SkGammas::Type::kNamed_Type:
- named_to_parametric(&fn[i], gammas->data(i).fNamed);
- break;
- case SkGammas::Type::kValue_Type:
- value_to_parametric(&fn[i], gammas->data(i).fValue);
- break;
- case SkGammas::Type::kParam_Type:
- fn[i] = gammas->params(i);
- break;
- default:
- SkASSERT(false);
- }
- }
- }
- }
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(color);
- paint.setStrokeWidth(2.0f);
- // note: gamma has positive values going up in this image so this origin is
- // the bottom left and we must subtract y instead of adding.
- const float gap = 16.0f;
- const float gammaWidth = kGammaImageWidth - 2 * gap;
- const float gammaHeight = kGammaImageHeight - 2 * gap;
- // gamma origin point
- const float ox = gap;
- const float oy = gap + gammaHeight;
- for (int i = 0; i < channels; ++i) {
- if (kNonStandard_SkGammaNamed == gammaNamed) {
- paint.setColor(kChannelColors[channels - 1][i]);
- } else {
- paint.setColor(color);
- }
- if (isTable[i]) {
- auto tx = [&table,i](int index) {
- return index / (table[i].fSize - 1.0f);
- };
- for (int ti = 1; ti < table[i].fSize; ++ti) {
- canvas->drawLine(ox + gammaWidth * tx(ti - 1),
- oy - gammaHeight * table[i].fTable[ti - 1],
- ox + gammaWidth * tx(ti),
- oy - gammaHeight * table[i].fTable[ti],
- paint);
- }
- } else {
- const float step = 0.01f;
- float yPrev = parametric(fn[i], 0.0f);
- for (float x = step; x <= 1.0f; x += step) {
- const float y = parametric(fn[i], x);
- canvas->drawLine(ox + gammaWidth * (x - step), oy - gammaHeight * yPrev,
- ox + gammaWidth * x, oy - gammaHeight * y,
- paint);
- yPrev = y;
- }
- }
- }
- paint.setColor(0xFF000000);
- paint.setStrokeWidth(3.0f);
- canvas->drawRect({ ox, oy - gammaHeight, ox + gammaWidth, oy }, paint);
-}
-
-//-------------------------------------------------------------------------------------------------
-//------------------------------------ CLUT visualizations ----------------------------------------
-static void dump_clut(const SkColorLookUpTable& clut) {
- SkDebugf("CLUT: ");
- for (int i = 0; i < clut.inputChannels(); ++i) {
- SkDebugf("[%d]", clut.gridPoints(i));
- }
- SkDebugf(" -> [%d]\n", clut.outputChannels());
-}
-
-constexpr int kClutGap = 8;
-constexpr float kClutCanvasSize = 2000;
-
-static inline int usedGridPoints(const SkColorLookUpTable& clut, int dimension) {
- const int gp = clut.gridPoints(dimension);
- return gp <= 16 ? gp : 16;
-}
-
-// how many rows of cross-section cuts to display
-static inline int cut_rows(const SkColorLookUpTable& clut, int dimOrder[4]) {
- // and vertical ones for the 4th dimension (if applicable)
- return clut.inputChannels() >= 4 ? usedGridPoints(clut, dimOrder[3]) : 1;
-}
-
-// how many columns of cross-section cuts to display
-static inline int cut_cols(const SkColorLookUpTable& clut, int dimOrder[4]) {
- // do horizontal cuts for the 3rd dimension (if applicable)
- return clut.inputChannels() >= 3 ? usedGridPoints(clut, dimOrder[2]) : 1;
-}
-
-// gets the width/height to use for cross-sections of a CLUT
-static int cut_size(const SkColorLookUpTable& clut, int dimOrder[4]) {
- const int rows = cut_rows(clut, dimOrder);
- const int cols = cut_cols(clut, dimOrder);
- // make sure the cross-section CLUT cuts are square still by using the
- // smallest of the width/height, then adjust the gaps between accordingly
- const int cutWidth = (kClutCanvasSize - kClutGap * (1 + cols)) / cols;
- const int cutHeight = (kClutCanvasSize - kClutGap * (1 + rows)) / rows;
- return cutWidth < cutHeight ? cutWidth : cutHeight;
-}
-
-static void draw_clut(SkCanvas* canvas, const SkColorLookUpTable& clut, int dimOrder[4]) {
- dump_clut(clut);
-
- const int cutSize = cut_size(clut, dimOrder);
- const int rows = cut_rows(clut, dimOrder);
- const int cols = cut_cols(clut, dimOrder);
- const int cutHorizGap = (kClutCanvasSize - cutSize * cols) / (1 + cols);
- const int cutVertGap = (kClutCanvasSize - cutSize * rows) / (1 + rows);
-
- SkPaint paint;
- for (int row = 0; row < rows; ++row) {
- for (int col = 0; col < cols; ++col) {
- // make sure to move at least one pixel, but otherwise move per-gridpoint
- const float xStep = 1.0f / (SkTMin(cutSize, clut.gridPoints(dimOrder[0])) - 1);
- const float yStep = 1.0f / (SkTMin(cutSize, clut.gridPoints(dimOrder[1])) - 1);
- const float ox = clut.inputChannels() >= 3 ? (1 + col) * cutHorizGap + col * cutSize
- : kClutGap;
- const float oy = clut.inputChannels() >= 4 ? (1 + row) * cutVertGap + row * cutSize
- : kClutGap;
- // for each cross-section cut, draw a bunch of squares whose colour is the top-left's
- // colour in the CLUT (usually this will just draw the gridpoints)
- for (float x = 0.0f; x < 1.0f; x += xStep) {
- for (float y = 0.0f; y < 1.0f; y += yStep) {
- const float z = col / (cols - 1.0f);
- const float w = row / (rows - 1.0f);
- const float input[4] = {x, y, z, w};
- float output[3];
- clut.interp(output, input);
- paint.setColor(SkColorSetRGB(255*output[0], 255*output[1], 255*output[2]));
- canvas->drawRect(SkRect::MakeLTRB(ox + cutSize * x, oy + cutSize * y,
- ox + cutSize * (x + xStep),
- oy + cutSize * (y + yStep)), paint);
- }
- }
- }
- }
-}
-
-
-//-------------------------------------------------------------------------------------------------
-//------------------------------------ Gamut visualizations ---------------------------------------
-static void dump_matrix(const SkMatrix44& m) {
- for (int r = 0; r < 4; ++r) {
- SkDebugf("|");
- for (int c = 0; c < 4; ++c) {
- SkDebugf(" %f ", m.get(r, c));
- }
- SkDebugf("|\n");
- }
-}
-
-/**
- * Loads the triangular gamut as a set of three points.
- */
-static void load_gamut(SkPoint rgb[], const SkMatrix44& xyz) {
- // rx = rX / (rX + rY + rZ)
- // ry = rX / (rX + rY + rZ)
- // gx, gy, bx, and gy are calulcated similarly.
- float rSum = xyz.get(0, 0) + xyz.get(1, 0) + xyz.get(2, 0);
- float gSum = xyz.get(0, 1) + xyz.get(1, 1) + xyz.get(2, 1);
- float bSum = xyz.get(0, 2) + xyz.get(1, 2) + xyz.get(2, 2);
- rgb[0].fX = xyz.get(0, 0) / rSum;
- rgb[0].fY = xyz.get(1, 0) / rSum;
- rgb[1].fX = xyz.get(0, 1) / gSum;
- rgb[1].fY = xyz.get(1, 1) / gSum;
- rgb[2].fX = xyz.get(0, 2) / bSum;
- rgb[2].fY = xyz.get(1, 2) / bSum;
-}
-
-/**
- * Calculates the area of the triangular gamut.
- */
-static float calculate_area(SkPoint abc[]) {
- SkPoint a = abc[0];
- SkPoint b = abc[1];
- SkPoint c = abc[2];
- return 0.5f * SkTAbs(a.fX*b.fY + b.fX*c.fY - a.fX*c.fY - c.fX*b.fY - b.fX*a.fY);
-}
-
-static void draw_gamut(SkCanvas* canvas, const SkMatrix44& xyz, const char* name, SkColor color,
- bool label) {
- // Report the XYZ values.
- SkDebugf("%s\n", name);
- SkDebugf(" R G B\n");
- SkDebugf("X %.3f %.3f %.3f\n", xyz.get(0, 0), xyz.get(0, 1), xyz.get(0, 2));
- SkDebugf("Y %.3f %.3f %.3f\n", xyz.get(1, 0), xyz.get(1, 1), xyz.get(1, 2));
- SkDebugf("Z %.3f %.3f %.3f\n", xyz.get(2, 0), xyz.get(2, 1), xyz.get(2, 2));
-
- // Calculate the points in the gamut from the XYZ values.
- SkPoint rgb[4];
- load_gamut(rgb, xyz);
-
- // Report the area of the gamut.
- SkDebugf("Area of Gamut: %.3f\n\n", calculate_area(rgb));
-
- // Magic constants that help us place the gamut triangles in the appropriate position
- // on the canvas.
- const float xScale = 2071.25f; // Num pixels from 0 to 1 in x
- const float xOffset = 241.0f; // Num pixels until start of x-axis
- const float yScale = 2067.78f; // Num pixels from 0 to 1 in y
- const float yOffset = -144.78f; // Num pixels until start of y-axis
- // (negative because y extends beyond image bounds)
-
- // Now transform the points so they can be drawn on our canvas.
- // Note that y increases as we move down the canvas.
- rgb[0].fX = xOffset + xScale * rgb[0].fX;
- rgb[0].fY = yOffset + yScale * (1.0f - rgb[0].fY);
- rgb[1].fX = xOffset + xScale * rgb[1].fX;
- rgb[1].fY = yOffset + yScale * (1.0f - rgb[1].fY);
- rgb[2].fX = xOffset + xScale * rgb[2].fX;
- rgb[2].fY = yOffset + yScale * (1.0f - rgb[2].fY);
-
- // Repeat the first point to connect the polygon.
- rgb[3] = rgb[0];
- SkPaint paint;
- paint.setColor(color);
- paint.setStrokeWidth(6.0f);
- paint.setTextSize(75.0f);
- canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, rgb, paint);
- if (label) {
- canvas->drawString("R", rgb[0].fX + 5.0f, rgb[0].fY + 75.0f, paint);
- canvas->drawString("G", rgb[1].fX + 5.0f, rgb[1].fY - 5.0f, paint);
- canvas->drawString("B", rgb[2].fX - 75.0f, rgb[2].fY - 5.0f, paint);
- }
-}
-
-
-//-------------------------------------------------------------------------------------------------
-//----------------------------------------- Main code ---------------------------------------------
-static SkBitmap transparentBitmap(int width, int height) {
- SkBitmap bitmap;
- bitmap.allocN32Pixels(width, height);
- bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
- return bitmap;
-}
-
-class OutputCanvas {
-public:
- OutputCanvas(SkBitmap&& bitmap)
- :fBitmap(bitmap)
- ,fCanvas(fBitmap)
- {}
-
- bool save(std::vector<std::string>* output, const std::string& filename) {
- // Finally, encode the result to the output file.
- sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(fBitmap, SkEncodedImageFormat::kPNG,
- 100);
- if (!out) {
- SkDebugf("Failed to encode %s output.\n", filename.c_str());
- return false;
- }
- SkFILEWStream stream(filename.c_str());
- if (!stream.write(out->data(), out->size())) {
- SkDebugf("Failed to write %s output.\n", filename.c_str());
- return false;
- }
- // record name of canvas
- output->push_back(filename);
- return true;
- }
-
- SkCanvas* canvas() { return &fCanvas; }
-
-private:
- SkBitmap fBitmap;
- SkCanvas fCanvas;
-};
-
-int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage(
- "Usage: colorspaceinfo --input <path to input image (or icc profile with --icc)> "
- "--output <directory to output images> "
- "--icc <indicates that the input is an icc profile>"
- "--sRGB_gamut <draw canonical sRGB gamut> "
- "--adobeRGB <draw canonical Adobe RGB gamut> "
- "--sRGB_gamma <draw sRGB gamma> "
- "--uncorrected <path to reencoded, uncorrected input image>\n"
- "Description: Writes visualizations of the color space to the output image(s) ."
- "Also, if a path is provided, writes uncorrected bytes to an unmarked "
- "png, for comparison with the input image.\n");
- SkCommandLineFlags::Parse(argc, argv);
- const char* input = FLAGS_input[0];
- const char* output = FLAGS_output[0];
- if (!input || !output) {
- SkCommandLineFlags::PrintUsage();
- return -1;
- }
-
- sk_sp<SkData> data(SkData::MakeFromFileName(input));
- if (!data) {
- SkDebugf("Cannot find input image.\n");
- return -1;
- }
-
- std::unique_ptr<SkCodec> codec = nullptr;
- sk_sp<SkColorSpace> colorSpace = nullptr;
- if (FLAGS_icc) {
- colorSpace = SkColorSpace::MakeICC(data->bytes(), data->size());
- } else {
- codec.reset(SkCodec::NewFromData(data));
- colorSpace = sk_ref_sp(codec->getInfo().colorSpace());
- }
-
- if (!colorSpace) {
- SkDebugf("Cannot create codec or icc profile from input file.\n");
- return -1;
- }
-
- {
- SkColorSpaceTransferFn colorSpaceTransferFn;
- SkMatrix44 toXYZD50;
- if (colorSpace->isNumericalTransferFn(&colorSpaceTransferFn) &&
- colorSpace->toXYZD50(&toXYZD50)) {
- SkString description = SkICCGetColorProfileTag(colorSpaceTransferFn, toXYZD50);
- SkDebugf("Color Profile Description: \"%s\"\n", description.c_str());
- }
- }
-
- // TODO: command line tweaking of this order
- int dimOrder[4] = {0, 1, 2, 3};
-
- std::vector<std::string> outputFilenames;
-
- auto createOutputFilename = [output](const char* category, int index) -> std::string {
- std::stringstream ss;
- ss << output << '/' << category << '_' << index << ".png";
- return ss.str();
- };
-
- if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type()) {
- SkDebugf("XYZ/TRC color space\n");
-
- // Load a graph of the CIE XYZ color gamut.
- SkBitmap gamutCanvasBitmap;
- if (!GetResourceAsBitmap("gamut.png", &gamutCanvasBitmap)) {
- SkDebugf("Program failure (could not load gamut.png).\n");
- return -1;
- }
- OutputCanvas gamutCanvas(std::move(gamutCanvasBitmap));
- // Draw the sRGB gamut if requested.
- if (FLAGS_sRGB_gamut) {
- sk_sp<SkColorSpace> sRGBSpace = SkColorSpace::MakeSRGB();
- const SkMatrix44* mat = as_CSB(sRGBSpace)->toXYZD50();
- SkASSERT(mat);
- draw_gamut(gamutCanvas.canvas(), *mat, "sRGB", 0xFFFF9394, false);
- }
-
- // Draw the Adobe RGB gamut if requested.
- if (FLAGS_adobeRGB) {
- sk_sp<SkColorSpace> adobeRGBSpace = SkColorSpace::MakeRGB(
- SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kAdobeRGB_Gamut);
- const SkMatrix44* mat = as_CSB(adobeRGBSpace)->toXYZD50();
- SkASSERT(mat);
- draw_gamut(gamutCanvas.canvas(), *mat, "Adobe RGB", 0xFF31a9e1, false);
- }
- const SkMatrix44* mat = as_CSB(colorSpace)->toXYZD50();
- SkASSERT(mat);
- auto xyz = static_cast<SkColorSpace_XYZ*>(colorSpace.get());
- draw_gamut(gamutCanvas.canvas(), *mat, input, 0xFF000000, true);
- if (!gamutCanvas.save(&outputFilenames, createOutputFilename("gamut", 0))) {
- return -1;
- }
-
- OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth, kGammaImageHeight));
- if (FLAGS_sRGB_gamma) {
- draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr, 0xFFFF9394);
- }
- draw_transfer_fn(gammaCanvas.canvas(), xyz->gammaNamed(), xyz->gammas(), 0xFF000000);
- if (!gammaCanvas.save(&outputFilenames, createOutputFilename("gamma", 0))) {
- return -1;
- }
- } else {
- SkDebugf("A2B color space");
- SkColorSpace_A2B* a2b = static_cast<SkColorSpace_A2B*>(colorSpace.get());
- SkDebugf("Conversion type: ");
- switch (a2b->iccType()) {
- case SkColorSpace_Base::kRGB_ICCTypeFlag:
- SkDebugf("RGB");
- break;
- case SkColorSpace_Base::kCMYK_ICCTypeFlag:
- SkDebugf("CMYK");
- break;
- case SkColorSpace_Base::kGray_ICCTypeFlag:
- SkDebugf("Gray");
- break;
- default:
- SkASSERT(false);
- break;
-
- }
- SkDebugf(" -> ");
- switch (a2b->pcs()) {
- case SkColorSpace_A2B::PCS::kXYZ:
- SkDebugf("XYZ\n");
- break;
- case SkColorSpace_A2B::PCS::kLAB:
- SkDebugf("LAB\n");
- break;
- }
- int clutCount = 0;
- int gammaCount = 0;
- for (int i = 0; i < a2b->count(); ++i) {
- const SkColorSpace_A2B::Element& e = a2b->element(i);
- switch (e.type()) {
- case SkColorSpace_A2B::Element::Type::kGammaNamed: {
- OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth,
- kGammaImageHeight));
- if (FLAGS_sRGB_gamma) {
- draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr,
- 0xFFFF9394);
- }
- draw_transfer_fn(gammaCanvas.canvas(), e.gammaNamed(), nullptr,
- 0xFF000000);
- if (!gammaCanvas.save(&outputFilenames,
- createOutputFilename("gamma", gammaCount++))) {
- return -1;
- }
- }
- break;
- case SkColorSpace_A2B::Element::Type::kGammas: {
- OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth,
- kGammaImageHeight));
- if (FLAGS_sRGB_gamma) {
- draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr,
- 0xFFFF9394);
- }
- draw_transfer_fn(gammaCanvas.canvas(), kNonStandard_SkGammaNamed,
- &e.gammas(), 0xFF000000);
- if (!gammaCanvas.save(&outputFilenames,
- createOutputFilename("gamma", gammaCount++))) {
- return -1;
- }
- }
- break;
- case SkColorSpace_A2B::Element::Type::kCLUT: {
- const SkColorLookUpTable& clut = e.colorLUT();
- const int cutSize = cut_size(clut, dimOrder);
- const int clutWidth = clut.inputChannels() >= 3 ? kClutCanvasSize
- : 2 * kClutGap + cutSize;
- const int clutHeight = clut.inputChannels() >= 4 ? kClutCanvasSize
- : 2 * kClutGap + cutSize;
- OutputCanvas clutCanvas(transparentBitmap(clutWidth, clutHeight));
- draw_clut(clutCanvas.canvas(), e.colorLUT(), dimOrder);
- if (!clutCanvas.save(&outputFilenames,
- createOutputFilename("clut", clutCount++))) {
- return -1;
- }
- }
- break;
- case SkColorSpace_A2B::Element::Type::kMatrix:
- dump_matrix(e.matrix());
- break;
- }
- }
- }
-
- // marker to tell the web-tool the names of all images output
- SkDebugf("=========\n");
- for (const std::string& filename : outputFilenames) {
- SkDebugf("%s\n", filename.c_str());
- }
- if (!FLAGS_icc) {
- SkDebugf("%s\n", input);
- }
- // Also, if requested, decode and reencode the uncorrected input image.
- if (!FLAGS_uncorrected.isEmpty() && !FLAGS_icc) {
- SkBitmap bitmap;
- int width = codec->getInfo().width();
- int height = codec->getInfo().height();
- bitmap.allocN32Pixels(width, height, kOpaque_SkAlphaType == codec->getInfo().alphaType());
- SkImageInfo decodeInfo = SkImageInfo::MakeN32(width, height, kUnpremul_SkAlphaType);
- if (SkCodec::kSuccess != codec->getPixels(decodeInfo, bitmap.getPixels(),
- bitmap.rowBytes())) {
- SkDebugf("Could not decode input image.\n");
- return -1;
- }
- sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG,
- 100);
- if (!out) {
- SkDebugf("Failed to encode uncorrected image.\n");
- return -1;
- }
- SkFILEWStream bitmapStream(FLAGS_uncorrected[0]);
- if (!bitmapStream.write(out->data(), out->size())) {
- SkDebugf("Failed to write uncorrected image output.\n");
- return -1;
- }
- SkDebugf("%s\n", FLAGS_uncorrected[0]);
- }
-
- return 0;
-}
diff --git a/src/third_party/skia/tools/copyright/main.py b/src/third_party/skia/tools/copyright/main.py
index 24969a7..e428448 100644
--- a/src/third_party/skia/tools/copyright/main.py
+++ b/src/third_party/skia/tools/copyright/main.py
@@ -67,7 +67,7 @@
@param root_directory root directory within which to find all files
"""
path_list = []
- for dirpath, dirnames, filenames in os.walk(root_directory):
+ for dirpath, _, filenames in os.walk(root_directory):
for filename in filenames:
path_list.append(os.path.abspath(os.path.join(dirpath, filename)))
return path_list
diff --git a/src/third_party/skia/tools/cpu_modules.cpp b/src/third_party/skia/tools/cpu_modules.cpp
new file mode 100644
index 0000000..a749ebf
--- /dev/null
+++ b/src/third_party/skia/tools/cpu_modules.cpp
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "modules/particles/include/SkParticleEffect.h"
+
+// Doesn't do anything important; just exists to show we can use modules/particles without the GPU
+// backend being available.
+int main(int argc, char** argv) {
+ // Register types for serialization
+ SkParticleEffect::RegisterParticleTypes();
+ return 0;
+}
diff --git a/src/third_party/skia/tools/create_flutter_test_images.cpp b/src/third_party/skia/tools/create_flutter_test_images.cpp
deleted file mode 100644
index 69a0d11..0000000
--- a/src/third_party/skia/tools/create_flutter_test_images.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkColorSpacePriv.h"
-#include "SkImage.h"
-#include "SkPngEncoder.h"
-
-#include "Resources.h"
-
-/**
- * Create a color space that swaps the red, green, and blue channels.
- */
-static sk_sp<SkColorSpace> gbr_color_space() {
- float gbr[9];
- gbr[0] = gSRGB_toXYZD50[1];
- gbr[1] = gSRGB_toXYZD50[2];
- gbr[2] = gSRGB_toXYZD50[0];
- gbr[3] = gSRGB_toXYZD50[4];
- gbr[4] = gSRGB_toXYZD50[5];
- gbr[5] = gSRGB_toXYZD50[3];
- gbr[6] = gSRGB_toXYZD50[7];
- gbr[7] = gSRGB_toXYZD50[8];
- gbr[8] = gSRGB_toXYZD50[6];
- SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
- toXYZD50.set3x3RowMajorf(gbr);
- return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, toXYZD50);
-}
-
-/**
- * Create a color space with a steep transfer function.
- */
-static sk_sp<SkColorSpace> tf_color_space() {
- SkColorSpaceTransferFn fn;
- fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 50.f;
- return SkColorSpace::MakeRGB(fn, SkColorSpace::kSRGB_Gamut);
-}
-
-/**
- * Create a wide gamut color space.
- */
-static sk_sp<SkColorSpace> wide_gamut_color_space() {
- return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
- SkColorSpace::kRec2020_Gamut);
-}
-
-int main(int argc, char** argv) {
- sk_sp<SkImage> image = GetResourceAsImage("flutter_logo.jpg");
- if (!image) {
- SkDebugf("Cannot find flutter_logo.jpg in resources.\n");
- return 1;
- }
-
- // Encode an image with a gbr color space.
- SkImageInfo info = SkImageInfo::MakeN32(image->width(), image->height(), kOpaque_SkAlphaType,
- gbr_color_space());
- size_t rowBytes = info.minRowBytes();
- SkAutoTMalloc<uint8_t> storage(rowBytes * image->height());
- SkPixmap src(info, storage.get(), rowBytes);
- image->readPixels(src, 0, 0, SkImage::kDisallow_CachingHint);
- SkFILEWStream dst0("gbr.png");
- SkPngEncoder::Options opts;
- opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore; // Does not matter for opaque src
- SkAssertResult(SkPngEncoder::Encode(&dst0, src, opts));
-
- // Encode an image with steep transfer function.
- src.setColorSpace(tf_color_space());
- image->readPixels(src, 0, 0, SkImage::kDisallow_CachingHint);
- SkFILEWStream dst1("tf.png");
- SkAssertResult(SkPngEncoder::Encode(&dst1, src, opts));
-
- // Encode a wide gamut image.
- src.setColorSpace(wide_gamut_color_space());
- image->readPixels(src, 0, 0, SkImage::kDisallow_CachingHint);
- SkFILEWStream dst2("wide-gamut.png");
- SkAssertResult(SkPngEncoder::Encode(&dst2, src, opts));
-
- return 0;
-}
diff --git a/src/third_party/skia/tools/create_test_font.cpp b/src/third_party/skia/tools/create_test_font.cpp
deleted file mode 100644
index 5183981..0000000
--- a/src/third_party/skia/tools/create_test_font.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// running create_test_font generates ./tools/test_font_data.cpp
-// which is read by ./tools/sk_tool_utils_font.cpp
-
-#include "Resources.h"
-#include "SkOSFile.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-#include "SkStream.h"
-#include "SkTArray.h"
-#include "SkTSort.h"
-#include "SkTypeface.h"
-#include "SkUtils.h"
-#include <stdio.h>
-
-#define DEFAULT_FONT_NAME "sans-serif"
-
-static struct FontDesc {
- const char* fName;
- SkTypeface::Style fStyle;
- const char* fFont;
- const char* fFile;
- int fFontIndex;
-} gFonts[] = {
- {"monospace", SkTypeface::kNormal, "Liberation Mono", "LiberationMono-Regular.ttf", -1},
- {"monospace", SkTypeface::kBold, "Liberation Mono", "LiberationMono-Bold.ttf", -1},
- {"monospace", SkTypeface::kItalic, "Liberation Mono", "LiberationMono-Italic.ttf", -1},
- {"monospace", SkTypeface::kBoldItalic, "Liberation Mono", "LiberationMono-BoldItalic.ttf", -1},
- {"sans-serif", SkTypeface::kNormal, "Liberation Sans", "LiberationSans-Regular.ttf", -1},
- {"sans-serif", SkTypeface::kBold, "Liberation Sans", "LiberationSans-Bold.ttf", -1},
- {"sans-serif", SkTypeface::kItalic, "Liberation Sans", "LiberationSans-Italic.ttf", -1},
- {"sans-serif", SkTypeface::kBoldItalic, "Liberation Sans", "LiberationSans-BoldItalic.ttf", -1},
- {"serif", SkTypeface::kNormal, "Liberation Serif", "LiberationSerif-Regular.ttf", -1},
- {"serif", SkTypeface::kBold, "Liberation Serif", "LiberationSerif-Bold.ttf", -1},
- {"serif", SkTypeface::kItalic, "Liberation Serif", "LiberationSerif-Italic.ttf", -1},
- {"serif", SkTypeface::kBoldItalic, "Liberation Serif", "LiberationSerif-BoldItalic.ttf", -1},
-};
-
-const int gFontsCount = (int) SK_ARRAY_COUNT(gFonts);
-
-const char* gStyleName[] = {
- "Normal",
- "Bold",
- "Italic",
- "BoldItalic",
-};
-
-const char gHeader[] =
-"/*\n"
-" * Copyright 2015 Google Inc.\n"
-" *\n"
-" * Use of this source code is governed by a BSD-style license that can be\n"
-" * found in the LICENSE file.\n"
-" */\n"
-"\n"
-"// Auto-generated by ";
-
-static FILE* font_header(const char* family) {
- SkString outPath(SkOSPath::Join(".", "tools"));
- outPath = SkOSPath::Join(outPath.c_str(), "test_font_");
- SkString fam(family);
- do {
- int dashIndex = fam.find("-");
- if (dashIndex < 0) {
- break;
- }
- fam.writable_str()[dashIndex] = '_';
- } while (true);
- outPath.append(fam);
- outPath.append(".cpp");
- FILE* out = fopen(outPath.c_str(), "w");
- fprintf(out, "%s%s\n\n", gHeader, SkOSPath::Basename(__FILE__).c_str());
- return out;
-}
-
-enum {
- kMaxLineLength = 80,
-};
-
-static ptrdiff_t last_line_length(const SkString& str) {
- const char* first = str.c_str();
- const char* last = first + str.size();
- const char* ptr = last;
- while (ptr > first && *--ptr != '\n')
- ;
- return last - ptr - 1;
-}
-
-static void output_fixed(SkScalar num, int emSize, SkString* out) {
- int hex = (int) (num * 65536 / emSize);
- out->appendf("0x%08x,", hex);
- *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
-}
-
-static void output_scalar(SkScalar num, int emSize, SkString* out) {
- num /= emSize;
- if (num == (int) num) {
- out->appendS32((int) num);
- } else {
- SkString str;
- str.printf("%1.6g", num);
- int width = (int) str.size();
- const char* cStr = str.c_str();
- while (cStr[width - 1] == '0') {
- --width;
- }
- str.remove(width, str.size() - width);
- out->appendf("%sf", str.c_str());
- }
- *out += ',';
- *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
-}
-
-static int output_points(const SkPoint* pts, int emSize, int count, SkString* ptsOut) {
- for (int index = 0; index < count; ++index) {
-// SkASSERT(floor(pts[index].fX) == pts[index].fX);
- output_scalar(pts[index].fX, emSize, ptsOut);
-// SkASSERT(floor(pts[index].fY) == pts[index].fY);
- output_scalar(pts[index].fY, emSize, ptsOut);
- }
- return count;
-}
-
-static void output_path_data(const SkPaint& paint,
- int emSize, SkString* ptsOut, SkTDArray<SkPath::Verb>* verbs,
- SkTDArray<unsigned>* charCodes, SkTDArray<SkScalar>* widths) {
- for (int ch = 0x00; ch < 0x7f; ++ch) {
- char str[1];
- str[0] = ch;
- const char* used = str;
- SkUnichar index = SkUTF8_NextUnichar(&used);
- SkPath path;
- paint.getTextPath((const void*) &index, 2, 0, 0, &path);
- SkPath::RawIter iter(path);
- SkPath::Verb verb;
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- *verbs->append() = verb;
- switch (verb) {
- case SkPath::kMove_Verb:
- output_points(&pts[0], emSize, 1, ptsOut);
- break;
- case SkPath::kLine_Verb:
- output_points(&pts[1], emSize, 1, ptsOut);
- break;
- case SkPath::kQuad_Verb:
- output_points(&pts[1], emSize, 2, ptsOut);
- break;
- case SkPath::kCubic_Verb:
- output_points(&pts[1], emSize, 3, ptsOut);
- break;
- case SkPath::kClose_Verb:
- break;
- default:
- SkDEBUGFAIL("bad verb");
- SkASSERT(0);
- }
- }
- *verbs->append() = SkPath::kDone_Verb;
- *charCodes->append() = index;
- SkScalar width;
- SkDEBUGCODE(int charCount =) paint.getTextWidths((const void*) &index, 2, &width);
- SkASSERT(charCount == 1);
- // SkASSERT(floor(width) == width); // not true for Hiragino Maru Gothic Pro
- *widths->append() = width;
- if (!ch) {
- ch = 0x1f; // skip the rest of the control codes
- }
- }
-}
-
-static int offset_str_len(unsigned num) {
- if (num == (unsigned) -1) {
- return 10;
- }
- unsigned result = 1;
- unsigned ref = 10;
- while (ref <= num) {
- ++result;
- ref *= 10;
- }
- return result;
-}
-
-static SkString strip_spaces(const SkString& str) {
- SkString result;
- int count = (int) str.size();
- for (int index = 0; index < count; ++index) {
- char c = str[index];
- if (c != ' ' && c != '-') {
- result += c;
- }
- }
- return result;
-}
-
-static SkString strip_final(const SkString& str) {
- SkString result(str);
- if (result.endsWith("\n")) {
- result.remove(result.size() - 1, 1);
- }
- if (result.endsWith(" ")) {
- result.remove(result.size() - 1, 1);
- }
- if (result.endsWith(",")) {
- result.remove(result.size() - 1, 1);
- }
- return result;
-}
-
-static void output_font(SkTypeface* face, const char* name, SkTypeface::Style style, FILE* out) {
- int emSize = face->getUnitsPerEm() * 2;
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setTextAlign(SkPaint::kLeft_Align);
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- paint.setTextSize(emSize);
- SkSafeUnref(paint.setTypeface(face));
- SkTDArray<SkPath::Verb> verbs;
- SkTDArray<unsigned> charCodes;
- SkTDArray<SkScalar> widths;
- SkString ptsOut;
- output_path_data(paint, emSize, &ptsOut, &verbs, &charCodes, &widths);
- SkString fontnameStr(name);
- SkString strippedStr = strip_spaces(fontnameStr);
- strippedStr.appendf("%s", gStyleName[style]);
- const char* fontname = strippedStr.c_str();
- fprintf(out, "const SkScalar %sPoints[] = {\n", fontname);
- ptsOut = strip_final(ptsOut);
- fprintf(out, "%s", ptsOut.c_str());
- fprintf(out, "\n};\n\n");
- fprintf(out, "const unsigned char %sVerbs[] = {\n", fontname);
- int verbCount = verbs.count();
- int outChCount = 0;
- for (int index = 0; index < verbCount;) {
- SkPath::Verb verb = verbs[index];
- SkASSERT(verb >= SkPath::kMove_Verb && verb <= SkPath::kDone_Verb);
- SkASSERT((unsigned) verb == (unsigned char) verb);
- fprintf(out, "%u", verb);
- if (++index < verbCount) {
- outChCount += 3;
- fprintf(out, "%c", ',');
- if (outChCount >= kMaxLineLength) {
- outChCount = 0;
- fprintf(out, "%c", '\n');
- } else {
- fprintf(out, "%c", ' ');
- }
- }
- }
- fprintf(out, "\n};\n\n");
-
- // all fonts are now 0x00, 0x20 - 0xFE
- // don't need to generate or output character codes?
- fprintf(out, "const unsigned %sCharCodes[] = {\n", fontname);
- int offsetCount = charCodes.count();
- for (int index = 0; index < offsetCount;) {
- unsigned offset = charCodes[index];
- fprintf(out, "%u", offset);
- if (++index < offsetCount) {
- outChCount += offset_str_len(offset) + 2;
- fprintf(out, "%c", ',');
- if (outChCount >= kMaxLineLength) {
- outChCount = 0;
- fprintf(out, "%c", '\n');
- } else {
- fprintf(out, "%c", ' ');
- }
- }
- }
- fprintf(out, "\n};\n\n");
-
- SkString widthsStr;
- fprintf(out, "const SkFixed %sWidths[] = {\n", fontname);
- for (int index = 0; index < offsetCount; ++index) {
- output_fixed(widths[index], emSize, &widthsStr);
- }
- widthsStr = strip_final(widthsStr);
- fprintf(out, "%s\n};\n\n", widthsStr.c_str());
-
- fprintf(out, "const int %sCharCodesCount = (int) SK_ARRAY_COUNT(%sCharCodes);\n\n",
- fontname, fontname);
-
- SkPaint::FontMetrics metrics;
- paint.getFontMetrics(&metrics);
- fprintf(out, "const SkPaint::FontMetrics %sMetrics = {\n", fontname);
- SkString metricsStr;
- metricsStr.printf("0x%08x, ", metrics.fFlags);
- output_scalar(metrics.fTop, emSize, &metricsStr);
- output_scalar(metrics.fAscent, emSize, &metricsStr);
- output_scalar(metrics.fDescent, emSize, &metricsStr);
- output_scalar(metrics.fBottom, emSize, &metricsStr);
- output_scalar(metrics.fLeading, emSize, &metricsStr);
- output_scalar(metrics.fAvgCharWidth, emSize, &metricsStr);
- output_scalar(metrics.fMaxCharWidth, emSize, &metricsStr);
- output_scalar(metrics.fXMin, emSize, &metricsStr);
- output_scalar(metrics.fXMax, emSize, &metricsStr);
- output_scalar(metrics.fXHeight, emSize, &metricsStr);
- output_scalar(metrics.fCapHeight, emSize, &metricsStr);
- output_scalar(metrics.fUnderlineThickness, emSize, &metricsStr);
- output_scalar(metrics.fUnderlinePosition, emSize, &metricsStr);
- metricsStr = strip_final(metricsStr);
- fprintf(out, "%s\n};\n\n", metricsStr.c_str());
-}
-
-struct FontWritten {
- const char* fName;
- SkTypeface::Style fStyle;
-};
-
-static SkTDArray<FontWritten> gWritten;
-
-static int written_index(const FontDesc& fontDesc) {
- for (int index = 0; index < gWritten.count(); ++index) {
- const FontWritten& writ = gWritten[index];
- if (!strcmp(fontDesc.fFont, writ.fName) && fontDesc.fStyle == writ.fStyle) {
- return index;
- }
- }
- return -1;
-}
-
-static void generate_fonts() {
- FILE* out = nullptr;
- for (int index = 0; index < gFontsCount; ++index) {
- FontDesc& fontDesc = gFonts[index];
- if ((index & 3) == 0) {
- out = font_header(fontDesc.fName);
- }
- int fontIndex = written_index(fontDesc);
- if (fontIndex >= 0) {
- fontDesc.fFontIndex = fontIndex;
- continue;
- }
- SkTypeface* systemTypeface = SkTypeface::CreateFromName(fontDesc.fFont, fontDesc.fStyle);
- SkASSERT(systemTypeface);
- SkString filepath("/Library/Fonts/");
- filepath.append(fontDesc.fFile);
- SkASSERT(sk_exists(filepath.c_str()));
- SkTypeface* resourceTypeface = SkTypeface::CreateFromFile(filepath.c_str());
- SkASSERT(resourceTypeface);
- output_font(resourceTypeface, fontDesc.fFont, fontDesc.fStyle, out);
- fontDesc.fFontIndex = gWritten.count();
- FontWritten* writ = gWritten.append();
- writ->fName = fontDesc.fFont;
- writ->fStyle = fontDesc.fStyle;
- if ((index & 3) == 3) {
- fclose(out);
- }
- }
-}
-
-static void generate_index(const char* defaultName) {
- int fontCount = gWritten.count();
- FILE* out = font_header("index");
- int fontIndex;
-#if 0
- // currently generated files are inlined one after the other.
- // if the inlining is undesirable, generate externs using the code below
- // (additional code required to add include files)
- for (fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
- const FontWritten& writ = gWritten[fontIndex];
- const char* name = writ.fName;
- SkString strippedStr = strip_spaces(SkString(name));
- strippedStr.appendf("%s", gStyleName[writ.fStyle]);
- const char* strip = strippedStr.c_str();
- fprintf(out,
- "extern const SkScalar %sPoints[];\n"
- "extern const unsigned char %sVerbs[];\n"
- "extern const unsigned %sCharCodes[];\n"
- "extern const int %sCharCodesCount;\n"
- "extern const SkFixed %sWidths[];\n"
- "extern const SkPaint::FontMetrics %sMetrics;\n",
- strip, strip, strip, strip, strip, strip);
- }
- fprintf(out, "\n");
-#endif
- fprintf(out, "static SkTestFontData gTestFonts[] = {\n");
- for (fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
- const FontWritten& writ = gWritten[fontIndex];
- const char* name = writ.fName;
- SkString strippedStr = strip_spaces(SkString(name));
- strippedStr.appendf("%s", gStyleName[writ.fStyle]);
- const char* strip = strippedStr.c_str();
- fprintf(out,
- " { %sPoints, %sVerbs, %sCharCodes,\n"
- " %sCharCodesCount, %sWidths,\n"
- " %sMetrics, \"Toy %s\", SkTypeface::k%s, nullptr\n"
- " },\n",
- strip, strip, strip, strip, strip, strip, name, gStyleName[writ.fStyle]);
- }
- fprintf(out, "};\n\n");
- fprintf(out, "const int gTestFontsCount = (int) SK_ARRAY_COUNT(gTestFonts);\n\n");
- fprintf(out,
- "struct SubFont {\n"
- " const char* fName;\n"
- " SkTypeface::Style fStyle;\n"
- " SkTestFontData& fFont;\n"
- " const char* fFile;\n"
- "};\n\n"
- "const SubFont gSubFonts[] = {\n");
- int defaultIndex = -1;
- for (int subIndex = 0; subIndex < gFontsCount; subIndex++) {
- const FontDesc& desc = gFonts[subIndex];
- if (defaultIndex < 0 && !strcmp(defaultName, desc.fName)) {
- defaultIndex = subIndex;
- }
- fprintf(out,
- " { \"%s\", SkTypeface::k%s, gTestFonts[%d], \"%s\" },\n", desc.fName,
- gStyleName[desc.fStyle], desc.fFontIndex, desc.fFile);
- }
- for (int subIndex = 0; subIndex < gFontsCount; subIndex++) {
- const FontDesc& desc = gFonts[subIndex];
- fprintf(out,
- " { \"Toy %s\", SkTypeface::k%s, gTestFonts[%d], \"%s\" },\n", desc.fFont,
- gStyleName[desc.fStyle], desc.fFontIndex, desc.fFile);
- }
- fprintf(out, "};\n\n");
- fprintf(out, "const int gSubFontsCount = (int) SK_ARRAY_COUNT(gSubFonts);\n\n");
- SkASSERT(defaultIndex >= 0);
- fprintf(out, "const int gDefaultFontIndex = %d;\n", defaultIndex);
- fclose(out);
-}
-
-int main(int , char * const []) {
-#ifndef SK_BUILD_FOR_MAC
- #error "use fonts installed on Mac"
-#endif
- generate_fonts();
- generate_index(DEFAULT_FONT_NAME);
- return 0;
-}
diff --git a/src/third_party/skia/tools/debugger/DebugCanvas.cpp b/src/third_party/skia/tools/debugger/DebugCanvas.cpp
new file mode 100644
index 0000000..9f6776a
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/DebugCanvas.cpp
@@ -0,0 +1,524 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkPicture.h"
+#include "include/core/SkTextBlob.h"
+#include "include/utils/SkPaintFilterCanvas.h"
+#include "src/core/SkCanvasPriv.h"
+#include "src/core/SkClipOpPriv.h"
+#include "src/core/SkRectPriv.h"
+#include "src/utils/SkJSONWriter.h"
+#include "tools/debugger/DebugCanvas.h"
+#include "tools/debugger/DrawCommand.h"
+
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrAuditTrail.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
+
+#define SKDEBUGCANVAS_VERSION 1
+#define SKDEBUGCANVAS_ATTRIBUTE_VERSION "version"
+#define SKDEBUGCANVAS_ATTRIBUTE_COMMANDS "commands"
+#define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL "auditTrail"
+
+class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
+public:
+ DebugPaintFilterCanvas(SkCanvas* canvas, bool overdrawViz)
+ : INHERITED(canvas), fOverdrawViz(overdrawViz) {}
+
+protected:
+ bool onFilter(SkPaint& paint) const override {
+ if (fOverdrawViz) {
+ paint.setColor(SK_ColorRED);
+ paint.setAlpha(0x08);
+ paint.setBlendMode(SkBlendMode::kSrcOver);
+ }
+ return true;
+ }
+
+ void onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) override {
+ // We need to replay the picture onto this canvas in order to filter its internal paints.
+ this->SkCanvas::onDrawPicture(picture, matrix, paint);
+ }
+
+private:
+ bool fOverdrawViz;
+
+ typedef SkPaintFilterCanvas INHERITED;
+};
+
+DebugCanvas::DebugCanvas(int width, int height)
+ : INHERITED(width, height)
+ , fOverdrawViz(false)
+ , fClipVizColor(SK_ColorTRANSPARENT)
+ , fDrawGpuOpBounds(false) {
+ // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
+ // operations. This can lead to problems in the debugger which expects all
+ // the operations in the captured skp to appear in the debug canvas. To
+ // circumvent this we create a wide open clip here (an empty clip rect
+ // is not sufficient).
+ // Internally, the SkRect passed to clipRect is converted to an SkIRect and
+ // rounded out. The following code creates a nearly maximal rect that will
+ // not get collapsed by the coming conversions (Due to precision loss the
+ // inset has to be surprisingly large).
+ SkIRect largeIRect = SkRectPriv::MakeILarge();
+ largeIRect.inset(1024, 1024);
+ SkRect large = SkRect::Make(largeIRect);
+#ifdef SK_DEBUG
+ SkASSERT(!large.roundOut().isEmpty());
+#endif
+ // call the base class' version to avoid adding a draw command
+ this->INHERITED::onClipRect(large, kReplace_SkClipOp, kHard_ClipEdgeStyle);
+}
+
+DebugCanvas::DebugCanvas(SkIRect bounds) { DebugCanvas(bounds.width(), bounds.height()); }
+
+DebugCanvas::~DebugCanvas() { fCommandVector.deleteAll(); }
+
+void DebugCanvas::addDrawCommand(DrawCommand* command) { fCommandVector.push_back(command); }
+
+void DebugCanvas::draw(SkCanvas* canvas) {
+ if (!fCommandVector.isEmpty()) {
+ this->drawTo(canvas, fCommandVector.count() - 1);
+ }
+}
+
+void DebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
+ SkASSERT(!fCommandVector.isEmpty());
+ SkASSERT(index < fCommandVector.count());
+
+ int saveCount = originalCanvas->save();
+
+ SkRect windowRect = SkRect::MakeWH(SkIntToScalar(originalCanvas->getBaseLayerSize().width()),
+ SkIntToScalar(originalCanvas->getBaseLayerSize().height()));
+
+ originalCanvas->clear(SK_ColorTRANSPARENT);
+ originalCanvas->resetMatrix();
+ if (!windowRect.isEmpty()) {
+ originalCanvas->clipRect(windowRect, kReplace_SkClipOp);
+ }
+
+ DebugPaintFilterCanvas filterCanvas(originalCanvas, fOverdrawViz);
+
+ // If we have a GPU backend we can also visualize the op information
+ GrAuditTrail* at = nullptr;
+ if (fDrawGpuOpBounds || m != -1) {
+ // The audit trail must be obtained from the original canvas.
+ at = this->getAuditTrail(originalCanvas);
+ }
+
+ for (int i = 0; i <= index; i++) {
+ // We need to flush any pending operations, or they might combine with commands below.
+ // Previous operations were not registered with the audit trail when they were
+ // created, so if we allow them to combine, the audit trail will fail to find them.
+ filterCanvas.flush();
+
+ GrAuditTrail::AutoCollectOps* acb = nullptr;
+ if (at) {
+ acb = new GrAuditTrail::AutoCollectOps(at, i);
+ }
+
+ if (fCommandVector[i]->isVisible()) {
+ fCommandVector[i]->execute(&filterCanvas);
+ }
+ if (at && acb) {
+ delete acb;
+ }
+ }
+
+ if (SkColorGetA(fClipVizColor) != 0) {
+ filterCanvas.save();
+#define LARGE_COORD 1000000000
+ filterCanvas.clipRect(
+ SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD),
+ kReverseDifference_SkClipOp);
+ SkPaint clipPaint;
+ clipPaint.setColor(fClipVizColor);
+ filterCanvas.drawPaint(clipPaint);
+ filterCanvas.restore();
+ }
+
+ fMatrix = filterCanvas.getTotalMatrix();
+ fClip = filterCanvas.getDeviceClipBounds();
+ filterCanvas.restoreToCount(saveCount);
+
+ // draw any ops if required and issue a full reset onto GrAuditTrail
+ if (at) {
+ // just in case there is global reordering, we flush the canvas before querying
+ // GrAuditTrail
+ GrAuditTrail::AutoEnable ae(at);
+ filterCanvas.flush();
+
+ // we pick three colorblind-safe colors, 75% alpha
+ static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
+ static const SkColor kCommandOpBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
+ static const SkColor kOtherOpBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
+
+ // get the render target of the top device (from the original canvas) so we can ignore ops
+ // drawn offscreen
+ GrRenderTargetContext* rtc =
+ originalCanvas->internal_private_accessTopLayerRenderTargetContext();
+ GrSurfaceProxy::UniqueID proxyID = rtc->asSurfaceProxy()->uniqueID();
+
+ // get the bounding boxes to draw
+ SkTArray<GrAuditTrail::OpInfo> childrenBounds;
+ if (m == -1) {
+ at->getBoundsByClientID(&childrenBounds, index);
+ } else {
+ // the client wants us to draw the mth op
+ at->getBoundsByOpsTaskID(&childrenBounds.push_back(), m);
+ }
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+ for (int i = 0; i < childrenBounds.count(); i++) {
+ if (childrenBounds[i].fProxyUniqueID != proxyID) {
+ // offscreen draw, ignore for now
+ continue;
+ }
+ paint.setColor(kTotalBounds);
+ filterCanvas.drawRect(childrenBounds[i].fBounds, paint);
+ for (int j = 0; j < childrenBounds[i].fOps.count(); j++) {
+ const GrAuditTrail::OpInfo::Op& op = childrenBounds[i].fOps[j];
+ if (op.fClientID != index) {
+ paint.setColor(kOtherOpBounds);
+ } else {
+ paint.setColor(kCommandOpBounds);
+ }
+ filterCanvas.drawRect(op.fBounds, paint);
+ }
+ }
+ }
+ this->cleanupAuditTrail(originalCanvas);
+}
+
+void DebugCanvas::deleteDrawCommandAt(int index) {
+ SkASSERT(index < fCommandVector.count());
+ delete fCommandVector[index];
+ fCommandVector.remove(index);
+}
+
+DrawCommand* DebugCanvas::getDrawCommandAt(int index) {
+ SkASSERT(index < fCommandVector.count());
+ return fCommandVector[index];
+}
+
+GrAuditTrail* DebugCanvas::getAuditTrail(SkCanvas* canvas) {
+ GrAuditTrail* at = nullptr;
+ GrContext* ctx = canvas->getGrContext();
+ if (ctx) {
+ at = ctx->priv().auditTrail();
+ }
+ return at;
+}
+
+void DebugCanvas::drawAndCollectOps(int n, SkCanvas* canvas) {
+ GrAuditTrail* at = this->getAuditTrail(canvas);
+ if (at) {
+ // loop over all of the commands and draw them, this is to collect reordering
+ // information
+ for (int i = 0; i < this->getSize() && i <= n; i++) {
+ GrAuditTrail::AutoCollectOps enable(at, i);
+ fCommandVector[i]->execute(canvas);
+ }
+
+ // in case there is some kind of global reordering
+ {
+ GrAuditTrail::AutoEnable ae(at);
+ canvas->flush();
+ }
+ }
+}
+
+void DebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
+ GrAuditTrail* at = this->getAuditTrail(canvas);
+ if (at) {
+ GrAuditTrail::AutoEnable ae(at);
+ at->fullReset();
+ }
+}
+
+void DebugCanvas::toJSON(SkJSONWriter& writer,
+ UrlDataManager& urlDataManager,
+ int n,
+ SkCanvas* canvas) {
+ this->drawAndCollectOps(n, canvas);
+
+ // now collect json
+ GrAuditTrail* at = this->getAuditTrail(canvas);
+ writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_VERSION, SKDEBUGCANVAS_VERSION);
+ writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COMMANDS);
+
+ for (int i = 0; i < this->getSize() && i <= n; i++) {
+ writer.beginObject(); // command
+ this->getDrawCommandAt(i)->toJSON(writer, urlDataManager);
+
+ if (at) {
+ writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL);
+ at->toJson(writer, i);
+ }
+ writer.endObject(); // command
+ }
+
+ writer.endArray(); // commands
+ this->cleanupAuditTrail(canvas);
+}
+
+void DebugCanvas::toJSONOpsTask(SkJSONWriter& writer, int n, SkCanvas* canvas) {
+ this->drawAndCollectOps(n, canvas);
+
+ GrAuditTrail* at = this->getAuditTrail(canvas);
+ if (at) {
+ GrAuditTrail::AutoManageOpsTask enable(at);
+ at->toJson(writer);
+ } else {
+ writer.beginObject();
+ writer.endObject();
+ }
+ this->cleanupAuditTrail(canvas);
+}
+
+void DebugCanvas::setOverdrawViz(bool overdrawViz) { fOverdrawViz = overdrawViz; }
+
+void DebugCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new ClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
+}
+
+void DebugCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new ClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
+}
+
+void DebugCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new ClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
+}
+
+void DebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
+ this->addDrawCommand(new ClipRegionCommand(region, op));
+}
+
+void DebugCanvas::didConcat(const SkMatrix& matrix) {
+ this->addDrawCommand(new ConcatCommand(matrix));
+ this->INHERITED::didConcat(matrix);
+}
+
+void DebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
+ this->addDrawCommand(new DrawAnnotationCommand(rect, key, sk_ref_sp(value)));
+}
+
+void DebugCanvas::onDrawBitmap(const SkBitmap& bitmap,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawBitmapCommand(bitmap, left, top, paint));
+}
+
+void DebugCanvas::onDrawBitmapLattice(const SkBitmap& bitmap,
+ const Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawBitmapLatticeCommand(bitmap, lattice, dst, paint));
+}
+
+void DebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SrcRectConstraint constraint) {
+ this->addDrawCommand(
+ new DrawBitmapRectCommand(bitmap, src, dst, paint, (SrcRectConstraint)constraint));
+}
+
+void DebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawBitmapNineCommand(bitmap, center, dst, paint));
+}
+
+void DebugCanvas::onDrawImage(const SkImage* image,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawImageCommand(image, left, top, paint));
+}
+
+void DebugCanvas::onDrawImageLattice(const SkImage* image,
+ const Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawImageLatticeCommand(image, lattice, dst, paint));
+}
+
+void DebugCanvas::onDrawImageRect(const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SrcRectConstraint constraint) {
+ this->addDrawCommand(new DrawImageRectCommand(image, src, dst, paint, constraint));
+}
+
+void DebugCanvas::onDrawImageNine(const SkImage* image,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ this->addDrawCommand(new DrawImageNineCommand(image, center, dst, paint));
+}
+
+void DebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
+ this->addDrawCommand(new DrawOvalCommand(oval, paint));
+}
+
+void DebugCanvas::onDrawArc(const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const SkPaint& paint) {
+ this->addDrawCommand(new DrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
+}
+
+void DebugCanvas::onDrawPaint(const SkPaint& paint) {
+ this->addDrawCommand(new DrawPaintCommand(paint));
+}
+
+void DebugCanvas::onDrawBehind(const SkPaint& paint) {
+ this->addDrawCommand(new DrawBehindCommand(paint));
+}
+
+void DebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
+ this->addDrawCommand(new DrawPathCommand(path, paint));
+}
+
+void DebugCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ this->addDrawCommand(new DrawRegionCommand(region, paint));
+}
+
+void DebugCanvas::onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ this->addDrawCommand(new BeginDrawPictureCommand(picture, matrix, paint));
+ SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
+ picture->playback(this);
+ this->addDrawCommand(new EndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
+}
+
+void DebugCanvas::onDrawPoints(PointMode mode,
+ size_t count,
+ const SkPoint pts[],
+ const SkPaint& paint) {
+ this->addDrawCommand(new DrawPointsCommand(mode, count, pts, paint));
+}
+
+void DebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
+ // NOTE(chudy): Messing up when renamed to DrawRect... Why?
+ addDrawCommand(new DrawRectCommand(rect, paint));
+}
+
+void DebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
+ this->addDrawCommand(new DrawRRectCommand(rrect, paint));
+}
+
+void DebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
+ this->addDrawCommand(new DrawDRRectCommand(outer, inner, paint));
+}
+
+void DebugCanvas::onDrawTextBlob(const SkTextBlob* blob,
+ SkScalar x,
+ SkScalar y,
+ const SkPaint& paint) {
+ this->addDrawCommand(
+ new DrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)), x, y, paint));
+}
+
+void DebugCanvas::onDrawPatch(const SkPoint cubics[12],
+ const SkColor colors[4],
+ const SkPoint texCoords[4],
+ SkBlendMode bmode,
+ const SkPaint& paint) {
+ this->addDrawCommand(new DrawPatchCommand(cubics, colors, texCoords, bmode, paint));
+}
+
+void DebugCanvas::onDrawVerticesObject(const SkVertices* vertices,
+ const SkVertices::Bone bones[],
+ int boneCount,
+ SkBlendMode bmode,
+ const SkPaint& paint) {
+ // TODO: ANIMATION NOT LOGGED
+ this->addDrawCommand(
+ new DrawVerticesCommand(sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode, paint));
+}
+
+void DebugCanvas::onDrawAtlas(const SkImage* image,
+ const SkRSXform xform[],
+ const SkRect tex[],
+ const SkColor colors[],
+ int count,
+ SkBlendMode bmode,
+ const SkRect* cull,
+ const SkPaint* paint) {
+ this->addDrawCommand(
+ new DrawAtlasCommand(image, xform, tex, colors, count, bmode, cull, paint));
+}
+
+void DebugCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ this->addDrawCommand(new DrawShadowCommand(path, rec));
+}
+
+void DebugCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
+ this->addDrawCommand(new DrawDrawableCommand(drawable, matrix));
+}
+
+void DebugCanvas::onDrawEdgeAAQuad(const SkRect& rect,
+ const SkPoint clip[4],
+ QuadAAFlags aa,
+ const SkColor4f& color,
+ SkBlendMode mode) {
+ this->addDrawCommand(new DrawEdgeAAQuadCommand(rect, clip, aa, color, mode));
+}
+
+void DebugCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[],
+ int count,
+ const SkPoint dstClips[],
+ const SkMatrix preViewMatrices[],
+ const SkPaint* paint,
+ SrcRectConstraint constraint) {
+ this->addDrawCommand(new DrawEdgeAAImageSetCommand(
+ set, count, dstClips, preViewMatrices, paint, constraint));
+}
+
+void DebugCanvas::willRestore() {
+ this->addDrawCommand(new RestoreCommand());
+ this->INHERITED::willRestore();
+}
+
+void DebugCanvas::willSave() {
+ this->addDrawCommand(new SaveCommand());
+ this->INHERITED::willSave();
+}
+
+SkCanvas::SaveLayerStrategy DebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
+ this->addDrawCommand(new SaveLayerCommand(rec));
+ (void)this->INHERITED::getSaveLayerStrategy(rec);
+ // No need for a full layer.
+ return kNoLayer_SaveLayerStrategy;
+}
+
+bool DebugCanvas::onDoSaveBehind(const SkRect* subset) {
+ // TODO
+ return false;
+}
+
+void DebugCanvas::didSetMatrix(const SkMatrix& matrix) {
+ this->addDrawCommand(new SetMatrixCommand(matrix));
+ this->INHERITED::didSetMatrix(matrix);
+}
+
+void DebugCanvas::toggleCommand(int index, bool toggle) {
+ SkASSERT(index < fCommandVector.count());
+ fCommandVector[index]->setVisible(toggle);
+}
diff --git a/src/third_party/skia/tools/debugger/DebugCanvas.h b/src/third_party/skia/tools/debugger/DebugCanvas.h
new file mode 100644
index 0000000..d7917ab
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/DebugCanvas.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKDEBUGCANVAS_H_
+#define SKDEBUGCANVAS_H_
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkCanvasVirtualEnforcer.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkString.h"
+#include "include/core/SkVertices.h"
+#include "include/pathops/SkPathOps.h"
+#include "include/private/SkTArray.h"
+#include "tools/UrlDataManager.h"
+#include "tools/debugger/DrawCommand.h"
+
+class GrAuditTrail;
+class SkNWayCanvas;
+class SkPicture;
+
+class DebugCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {
+public:
+ DebugCanvas(int width, int height);
+
+ DebugCanvas(SkIRect bounds);
+
+ ~DebugCanvas() override;
+
+ /**
+ * Enable or disable overdraw visualization
+ */
+ void setOverdrawViz(bool overdrawViz);
+
+ bool getOverdrawViz() const { return fOverdrawViz; }
+
+ /**
+ * Set the color of the clip visualization. An alpha of zero renders the clip invisible.
+ */
+ void setClipVizColor(SkColor clipVizColor) { this->fClipVizColor = clipVizColor; }
+
+ void setDrawGpuOpBounds(bool drawGpuOpBounds) { fDrawGpuOpBounds = drawGpuOpBounds; }
+
+ bool getDrawGpuOpBounds() const { return fDrawGpuOpBounds; }
+
+ /**
+ Executes all draw calls to the canvas.
+ @param canvas The canvas being drawn to
+ */
+ void draw(SkCanvas* canvas);
+
+ /**
+ Executes the draw calls up to the specified index.
+ @param canvas The canvas being drawn to
+ @param index The index of the final command being executed
+ @param m an optional Mth gpu op to highlight, or -1
+ */
+ void drawTo(SkCanvas* canvas, int index, int m = -1);
+
+ /**
+ Returns the most recently calculated transformation matrix
+ */
+ const SkMatrix& getCurrentMatrix() { return fMatrix; }
+
+ /**
+ Returns the most recently calculated clip
+ */
+ const SkIRect& getCurrentClip() { return fClip; }
+
+ /**
+ Removes the command at the specified index
+ @param index The index of the command to delete
+ */
+ void deleteDrawCommandAt(int index);
+
+ /**
+ Returns the draw command at the given index.
+ @param index The index of the command
+ */
+ DrawCommand* getDrawCommandAt(int index);
+
+ /**
+ Returns length of draw command vector.
+ */
+ int getSize() const { return fCommandVector.count(); }
+
+ /**
+ Toggles the visibility / execution of the draw command at index i with
+ the value of toggle.
+ */
+ void toggleCommand(int index, bool toggle);
+
+ /**
+ Returns a JSON object representing up to the Nth draw, where N is less than
+ DebugCanvas::getSize(). The encoder may use the UrlDataManager to store binary data such
+ as images, referring to them via URLs embedded in the JSON.
+ */
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager, int n, SkCanvas*);
+
+ void toJSONOpsTask(SkJSONWriter& writer, int n, SkCanvas*);
+
+ void detachCommands(SkTDArray<DrawCommand*>* dst) { fCommandVector.swap(*dst); }
+
+protected:
+ void willSave() override;
+ SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
+ bool onDoSaveBehind(const SkRect*) override;
+ void willRestore() override;
+
+ void didConcat(const SkMatrix&) override;
+
+ void didSetMatrix(const SkMatrix&) override;
+
+ void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
+ void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+ void onDrawTextBlob(const SkTextBlob* blob,
+ SkScalar x,
+ SkScalar y,
+ const SkPaint& paint) override;
+
+ void onDrawPatch(const SkPoint cubics[12],
+ const SkColor colors[4],
+ const SkPoint texCoords[4],
+ SkBlendMode,
+ const SkPaint& paint) override;
+ void onDrawPaint(const SkPaint&) override;
+ void onDrawBehind(const SkPaint&) override;
+
+ void onDrawRect(const SkRect&, const SkPaint&) override;
+ void onDrawOval(const SkRect&, const SkPaint&) override;
+ void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
+ void onDrawRRect(const SkRRect&, const SkPaint&) override;
+ void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
+ void onDrawVerticesObject(const SkVertices*,
+ const SkVertices::Bone bones[],
+ int boneCount,
+ SkBlendMode,
+ const SkPaint&) override;
+ void onDrawPath(const SkPath&, const SkPaint&) override;
+ void onDrawRegion(const SkRegion&, const SkPaint&) override;
+ void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
+ void onDrawBitmapLattice(const SkBitmap&,
+ const Lattice&,
+ const SkRect&,
+ const SkPaint*) override;
+ void onDrawBitmapRect(const SkBitmap&,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint*,
+ SrcRectConstraint) override;
+ void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
+ void onDrawImageLattice(const SkImage* image,
+ const Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint) override;
+ void onDrawImageRect(const SkImage*,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint*,
+ SrcRectConstraint) override;
+ void onDrawBitmapNine(const SkBitmap&,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint*) override;
+ void onDrawImageNine(const SkImage*,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint*) override;
+ void onDrawAtlas(const SkImage*,
+ const SkRSXform[],
+ const SkRect[],
+ const SkColor[],
+ int,
+ SkBlendMode,
+ const SkRect*,
+ const SkPaint*) override;
+ void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
+ void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
+ void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
+ void onClipRegion(const SkRegion& region, SkClipOp) override;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
+
+ void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
+ void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+ void onDrawEdgeAAQuad(const SkRect&,
+ const SkPoint[4],
+ QuadAAFlags,
+ const SkColor4f&,
+ SkBlendMode) override;
+ void onDrawEdgeAAImageSet(const ImageSetEntry[],
+ int count,
+ const SkPoint[],
+ const SkMatrix[],
+ const SkPaint*,
+ SrcRectConstraint) override;
+
+private:
+ SkTDArray<DrawCommand*> fCommandVector;
+ SkMatrix fMatrix;
+ SkIRect fClip;
+
+ bool fOverdrawViz;
+ SkColor fClipVizColor;
+ bool fDrawGpuOpBounds;
+
+ /**
+ Adds the command to the class' vector of commands.
+ @param command The draw command for execution
+ */
+ void addDrawCommand(DrawCommand* command);
+
+ GrAuditTrail* getAuditTrail(SkCanvas*);
+
+ void drawAndCollectOps(int n, SkCanvas*);
+ void cleanupAuditTrail(SkCanvas*);
+
+ typedef SkCanvasVirtualEnforcer<SkCanvas> INHERITED;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/debugger/DrawCommand.cpp b/src/third_party/skia/tools/debugger/DrawCommand.cpp
new file mode 100644
index 0000000..7571a48
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/DrawCommand.cpp
@@ -0,0 +1,2125 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/debugger/DrawCommand.h"
+
+#include <algorithm>
+#include "include/core/SkColorFilter.h"
+#include "include/core/SkDrawable.h"
+#include "include/core/SkImageFilter.h"
+#include "include/core/SkPathEffect.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkTypeface.h"
+#include "include/effects/SkDashPathEffect.h"
+#include "include/encode/SkPngEncoder.h"
+#include "include/private/SkShadowFlags.h"
+#include "include/private/SkTHash.h"
+#include "src/core/SkAutoMalloc.h"
+#include "src/core/SkCanvasPriv.h"
+#include "src/core/SkClipOpPriv.h"
+#include "src/core/SkLatticeIter.h"
+#include "src/core/SkMaskFilterBase.h"
+#include "src/core/SkPaintDefaults.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkRectPriv.h"
+#include "src/core/SkTextBlobPriv.h"
+#include "src/core/SkWriteBuffer.h"
+#include "tools/debugger/JsonWriteBuffer.h"
+
+#define DEBUGCANVAS_ATTRIBUTE_COMMAND "command"
+#define DEBUGCANVAS_ATTRIBUTE_VISIBLE "visible"
+#define DEBUGCANVAS_ATTRIBUTE_MATRIX "matrix"
+#define DEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation"
+#define DEBUGCANVAS_ATTRIBUTE_COORDS "coords"
+#define DEBUGCANVAS_ATTRIBUTE_EDGING "edging"
+#define DEBUGCANVAS_ATTRIBUTE_HINTING "hinting"
+#define DEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds"
+#define DEBUGCANVAS_ATTRIBUTE_PAINT "paint"
+#define DEBUGCANVAS_ATTRIBUTE_OUTER "outer"
+#define DEBUGCANVAS_ATTRIBUTE_INNER "inner"
+#define DEBUGCANVAS_ATTRIBUTE_MODE "mode"
+#define DEBUGCANVAS_ATTRIBUTE_POINTS "points"
+#define DEBUGCANVAS_ATTRIBUTE_PATH "path"
+#define DEBUGCANVAS_ATTRIBUTE_TEXT "text"
+#define DEBUGCANVAS_ATTRIBUTE_COLOR "color"
+#define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
+#define DEBUGCANVAS_ATTRIBUTE_BLENDMODE "blendMode"
+#define DEBUGCANVAS_ATTRIBUTE_STYLE "style"
+#define DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH "strokeWidth"
+#define DEBUGCANVAS_ATTRIBUTE_STROKEMITER "strokeMiter"
+#define DEBUGCANVAS_ATTRIBUTE_STROKEJOIN "strokeJoin"
+#define DEBUGCANVAS_ATTRIBUTE_CAP "cap"
+#define DEBUGCANVAS_ATTRIBUTE_ANTIALIAS "antiAlias"
+#define DEBUGCANVAS_ATTRIBUTE_DITHER "dither"
+#define DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT "fakeBoldText"
+#define DEBUGCANVAS_ATTRIBUTE_LINEARTEXT "linearText"
+#define DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT "subpixelText"
+#define DEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT "devKernText"
+#define DEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT "lcdRenderText"
+#define DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText"
+#define DEBUGCANVAS_ATTRIBUTE_AUTOHINTING "forceAutoHinting"
+#define DEBUGCANVAS_ATTRIBUTE_REGION "region"
+#define DEBUGCANVAS_ATTRIBUTE_REGIONOP "op"
+#define DEBUGCANVAS_ATTRIBUTE_EDGESTYLE "edgeStyle"
+#define DEBUGCANVAS_ATTRIBUTE_DEVICEREGION "deviceRegion"
+#define DEBUGCANVAS_ATTRIBUTE_BLUR "blur"
+#define DEBUGCANVAS_ATTRIBUTE_SIGMA "sigma"
+#define DEBUGCANVAS_ATTRIBUTE_QUALITY "quality"
+#define DEBUGCANVAS_ATTRIBUTE_TEXTSIZE "textSize"
+#define DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX "textScaleX"
+#define DEBUGCANVAS_ATTRIBUTE_TEXTSKEWX "textSkewX"
+#define DEBUGCANVAS_ATTRIBUTE_DASHING "dashing"
+#define DEBUGCANVAS_ATTRIBUTE_INTERVALS "intervals"
+#define DEBUGCANVAS_ATTRIBUTE_PHASE "phase"
+#define DEBUGCANVAS_ATTRIBUTE_FILLTYPE "fillType"
+#define DEBUGCANVAS_ATTRIBUTE_VERBS "verbs"
+#define DEBUGCANVAS_ATTRIBUTE_NAME "name"
+#define DEBUGCANVAS_ATTRIBUTE_DATA "data"
+#define DEBUGCANVAS_ATTRIBUTE_VALUES "values"
+#define DEBUGCANVAS_ATTRIBUTE_SHADER "shader"
+#define DEBUGCANVAS_ATTRIBUTE_PATHEFFECT "pathEffect"
+#define DEBUGCANVAS_ATTRIBUTE_MASKFILTER "maskFilter"
+#define DEBUGCANVAS_ATTRIBUTE_XFERMODE "xfermode"
+#define DEBUGCANVAS_ATTRIBUTE_BACKDROP "backdrop"
+#define DEBUGCANVAS_ATTRIBUTE_COLORFILTER "colorfilter"
+#define DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter"
+#define DEBUGCANVAS_ATTRIBUTE_IMAGE "image"
+#define DEBUGCANVAS_ATTRIBUTE_BITMAP "bitmap"
+#define DEBUGCANVAS_ATTRIBUTE_SRC "src"
+#define DEBUGCANVAS_ATTRIBUTE_DST "dst"
+#define DEBUGCANVAS_ATTRIBUTE_CENTER "center"
+#define DEBUGCANVAS_ATTRIBUTE_STRICT "strict"
+#define DEBUGCANVAS_ATTRIBUTE_DESCRIPTION "description"
+#define DEBUGCANVAS_ATTRIBUTE_X "x"
+#define DEBUGCANVAS_ATTRIBUTE_Y "y"
+#define DEBUGCANVAS_ATTRIBUTE_RUNS "runs"
+#define DEBUGCANVAS_ATTRIBUTE_POSITIONS "positions"
+#define DEBUGCANVAS_ATTRIBUTE_GLYPHS "glyphs"
+#define DEBUGCANVAS_ATTRIBUTE_FONT "font"
+#define DEBUGCANVAS_ATTRIBUTE_TYPEFACE "typeface"
+#define DEBUGCANVAS_ATTRIBUTE_CUBICS "cubics"
+#define DEBUGCANVAS_ATTRIBUTE_COLORS "colors"
+#define DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS "textureCoords"
+#define DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY "filterQuality"
+#define DEBUGCANVAS_ATTRIBUTE_STARTANGLE "startAngle"
+#define DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE "sweepAngle"
+#define DEBUGCANVAS_ATTRIBUTE_USECENTER "useCenter"
+#define DEBUGCANVAS_ATTRIBUTE_SHORTDESC "shortDesc"
+#define DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID "uniqueID"
+#define DEBUGCANVAS_ATTRIBUTE_WIDTH "width"
+#define DEBUGCANVAS_ATTRIBUTE_HEIGHT "height"
+#define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICE "lattice"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT "xCount"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT "yCount"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS "xDivs"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS "yDivs"
+#define DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS "flags"
+#define DEBUGCANVAS_ATTRIBUTE_ZPLANE "zPlane"
+#define DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION "lightPositions"
+#define DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR "ambientColor"
+#define DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR "spotColor"
+#define DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS "lightRadius"
+
+#define DEBUGCANVAS_VERB_MOVE "move"
+#define DEBUGCANVAS_VERB_LINE "line"
+#define DEBUGCANVAS_VERB_QUAD "quad"
+#define DEBUGCANVAS_VERB_CUBIC "cubic"
+#define DEBUGCANVAS_VERB_CONIC "conic"
+#define DEBUGCANVAS_VERB_CLOSE "close"
+
+#define DEBUGCANVAS_STYLE_FILL "fill"
+#define DEBUGCANVAS_STYLE_STROKE "stroke"
+#define DEBUGCANVAS_STYLE_STROKEANDFILL "strokeAndFill"
+
+#define DEBUGCANVAS_POINTMODE_POINTS "points"
+#define DEBUGCANVAS_POINTMODE_LINES "lines"
+#define DEBUGCANVAS_POINTMODE_POLYGON "polygon"
+
+#define DEBUGCANVAS_REGIONOP_DIFFERENCE "difference"
+#define DEBUGCANVAS_REGIONOP_INTERSECT "intersect"
+#define DEBUGCANVAS_REGIONOP_UNION "union"
+#define DEBUGCANVAS_REGIONOP_XOR "xor"
+#define DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
+#define DEBUGCANVAS_REGIONOP_REPLACE "replace"
+
+#define DEBUGCANVAS_BLURSTYLE_NORMAL "normal"
+#define DEBUGCANVAS_BLURSTYLE_SOLID "solid"
+#define DEBUGCANVAS_BLURSTYLE_OUTER "outer"
+#define DEBUGCANVAS_BLURSTYLE_INNER "inner"
+
+#define DEBUGCANVAS_BLURQUALITY_LOW "low"
+#define DEBUGCANVAS_BLURQUALITY_HIGH "high"
+
+#define DEBUGCANVAS_FILLTYPE_WINDING "winding"
+#define DEBUGCANVAS_FILLTYPE_EVENODD "evenOdd"
+#define DEBUGCANVAS_FILLTYPE_INVERSEWINDING "inverseWinding"
+#define DEBUGCANVAS_FILLTYPE_INVERSEEVENODD "inverseEvenOdd"
+
+#define DEBUGCANVAS_CAP_BUTT "butt"
+#define DEBUGCANVAS_CAP_ROUND "round"
+#define DEBUGCANVAS_CAP_SQUARE "square"
+
+#define DEBUGCANVAS_MITER_JOIN "miter"
+#define DEBUGCANVAS_ROUND_JOIN "round"
+#define DEBUGCANVAS_BEVEL_JOIN "bevel"
+
+#define DEBUGCANVAS_COLORTYPE_ARGB4444 "ARGB4444"
+#define DEBUGCANVAS_COLORTYPE_RGBA8888 "RGBA8888"
+#define DEBUGCANVAS_COLORTYPE_BGRA8888 "BGRA8888"
+#define DEBUGCANVAS_COLORTYPE_565 "565"
+#define DEBUGCANVAS_COLORTYPE_GRAY8 "Gray8"
+#define DEBUGCANVAS_COLORTYPE_INDEX8 "Index8"
+#define DEBUGCANVAS_COLORTYPE_ALPHA8 "Alpha8"
+
+#define DEBUGCANVAS_ALPHATYPE_OPAQUE "opaque"
+#define DEBUGCANVAS_ALPHATYPE_PREMUL "premul"
+#define DEBUGCANVAS_ALPHATYPE_UNPREMUL "unpremul"
+#define DEBUGCANVAS_ALPHATYPE_UNKNOWN "unknown"
+
+#define DEBUGCANVAS_FILTERQUALITY_NONE "none"
+#define DEBUGCANVAS_FILTERQUALITY_LOW "low"
+#define DEBUGCANVAS_FILTERQUALITY_MEDIUM "medium"
+#define DEBUGCANVAS_FILTERQUALITY_HIGH "high"
+
+#define DEBUGCANVAS_HINTING_NONE "none"
+#define DEBUGCANVAS_HINTING_SLIGHT "slight"
+#define DEBUGCANVAS_HINTING_NORMAL "normal"
+#define DEBUGCANVAS_HINTING_FULL "full"
+
+#define DEBUGCANVAS_EDGING_ALIAS "alias"
+#define DEBUGCANVAS_EDGING_ANTIALIAS "antialias"
+#define DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS "subpixelantialias"
+
+#define DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC "transparentOccluder"
+#define DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY "geometricOnly"
+
+static SkString* str_append(SkString* str, const SkRect& r) {
+ str->appendf(" [%g %g %g %g]", r.left(), r.top(), r.right(), r.bottom());
+ return str;
+}
+
+DrawCommand::DrawCommand(OpType type) : fOpType(type), fVisible(true) {}
+
+const char* DrawCommand::GetCommandString(OpType type) {
+ switch (type) {
+ case kBeginDrawPicture_OpType: return "BeginDrawPicture";
+ case kClear_OpType: return "DrawClear";
+ case kClipPath_OpType: return "ClipPath";
+ case kClipRegion_OpType: return "ClipRegion";
+ case kClipRect_OpType: return "ClipRect";
+ case kClipRRect_OpType: return "ClipRRect";
+ case kConcat_OpType: return "Concat";
+ case kDrawAnnotation_OpType: return "DrawAnnotation";
+ case kDrawBitmap_OpType: return "DrawBitmap";
+ case kDrawBitmapLattice_OpType: return "DrawBitmapLattice";
+ case kDrawBitmapNine_OpType: return "DrawBitmapNine";
+ case kDrawBitmapRect_OpType: return "DrawBitmapRect";
+ case kDrawDRRect_OpType: return "DrawDRRect";
+ case kDrawImage_OpType: return "DrawImage";
+ case kDrawImageLattice_OpType: return "DrawImageLattice";
+ case kDrawImageNine_OpType: return "DrawImageNine";
+ case kDrawImageRect_OpType: return "DrawImageRect";
+ case kDrawOval_OpType: return "DrawOval";
+ case kDrawPaint_OpType: return "DrawPaint";
+ case kDrawPatch_OpType: return "DrawPatch";
+ case kDrawPath_OpType: return "DrawPath";
+ case kDrawArc_OpType: return "DrawArc";
+ case kDrawPoints_OpType: return "DrawPoints";
+ case kDrawRect_OpType: return "DrawRect";
+ case kDrawRRect_OpType: return "DrawRRect";
+ case kDrawRegion_OpType: return "DrawRegion";
+ case kDrawShadow_OpType: return "DrawShadow";
+ case kDrawTextBlob_OpType: return "DrawTextBlob";
+ case kDrawVertices_OpType: return "DrawVertices";
+ case kDrawAtlas_OpType: return "DrawAtlas";
+ case kDrawDrawable_OpType: return "DrawDrawable";
+ case kDrawEdgeAAQuad_OpType: return "DrawEdgeAAQuad";
+ case kDrawEdgeAAImageSet_OpType: return "DrawEdgeAAImageSet";
+ case kEndDrawPicture_OpType: return "EndDrawPicture";
+ case kRestore_OpType: return "Restore";
+ case kSave_OpType: return "Save";
+ case kSaveLayer_OpType: return "SaveLayer";
+ case kSetMatrix_OpType: return "SetMatrix";
+ default:
+ SkDebugf("OpType error 0x%08x\n", type);
+ SkASSERT(0);
+ break;
+ }
+ SkDEBUGFAIL("DrawType UNUSED\n");
+ return nullptr;
+}
+
+void DrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType));
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible());
+}
+
+namespace {
+
+void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
+ const SkISize& size = canvas->getBaseLayerSize();
+
+ static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
+
+ canvas->translate(size.fWidth / 2.0f, size.fHeight / 2.0f);
+ if (bounds.width() > bounds.height()) {
+ canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.width()),
+ SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.width()));
+ } else {
+ canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.height()),
+ SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.height()));
+ }
+ canvas->translate(-bounds.centerX(), -bounds.centerY());
+}
+
+void render_path(SkCanvas* canvas, const SkPath& path) {
+ canvas->clear(0xFFFFFFFF);
+
+ const SkRect& bounds = path.getBounds();
+ if (bounds.isEmpty()) {
+ return;
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawPath(path, p);
+}
+
+void render_region(SkCanvas* canvas, const SkRegion& region) {
+ canvas->clear(0xFFFFFFFF);
+
+ const SkIRect& bounds = region.getBounds();
+ if (bounds.isEmpty()) {
+ return;
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+ xlate_and_scale_to_bounds(canvas, SkRect::Make(bounds));
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawRegion(region, p);
+}
+
+void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
+ const SkISize& size = canvas->getBaseLayerSize();
+
+ SkScalar xScale = SkIntToScalar(size.fWidth - 2) / input.width();
+ SkScalar yScale = SkIntToScalar(size.fHeight - 2) / input.height();
+
+ if (input.width() > input.height()) {
+ yScale *= input.height() / (float)input.width();
+ } else {
+ xScale *= input.width() / (float)input.height();
+ }
+
+ SkRect dst = SkRect::MakeXYWH(
+ SK_Scalar1, SK_Scalar1, xScale * input.width(), yScale * input.height());
+
+ static const int kNumBlocks = 8;
+
+ canvas->clear(0xFFFFFFFF);
+ SkISize block = {canvas->imageInfo().width() / kNumBlocks,
+ canvas->imageInfo().height() / kNumBlocks};
+ for (int y = 0; y < kNumBlocks; ++y) {
+ for (int x = 0; x < kNumBlocks; ++x) {
+ SkPaint paint;
+ paint.setColor((x + y) % 2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
+ SkRect r = SkRect::MakeXYWH(SkIntToScalar(x * block.width()),
+ SkIntToScalar(y * block.height()),
+ SkIntToScalar(block.width()),
+ SkIntToScalar(block.height()));
+ canvas->drawRect(r, paint);
+ }
+ }
+
+ canvas->drawBitmapRect(input, dst, nullptr);
+
+ if (srcRect) {
+ SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
+ srcRect->fTop * yScale + SK_Scalar1,
+ srcRect->fRight * xScale + SK_Scalar1,
+ srcRect->fBottom * yScale + SK_Scalar1);
+ SkPaint p;
+ p.setColor(SK_ColorRED);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawRect(r, p);
+ }
+}
+
+void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ const SkRect& bounds = rrect.getBounds();
+
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawRRect(rrect, p);
+ canvas->restore();
+}
+
+void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ const SkRect& bounds = outer.getBounds();
+
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawDRRect(outer, inner, p);
+ canvas->restore();
+}
+
+void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) {
+ canvas->clear(0xFFFFFFFF);
+
+ const SkRect& bounds = path.getBounds();
+ if (bounds.isEmpty()) {
+ return;
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ rec.fAmbientColor = SK_ColorBLACK;
+ rec.fSpotColor = SK_ColorBLACK;
+ canvas->private_draw_shadow_rec(path, rec);
+}
+
+static const char* const gBlendModeMap[] = {
+ "clear", "src", "dst", "srcOver", "dstOver", "srcIn", "dstIn",
+ "srcOut", "dstOut", "srcATop", "dstATop", "xor", "plus", "modulate",
+
+ "screen",
+
+ "overlay", "darken", "lighten", "colorDodge", "colorBurn", "hardLight", "softLight",
+ "difference", "exclusion", "multiply",
+
+ "hue", "saturation", "color", "luminosity",
+};
+
+static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
+ "blendMode mismatch");
+static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
+ "blendMode mismatch");
+
+void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
+ const auto mode = paint.getBlendMode();
+ if (mode != SkBlendMode::kSrcOver) {
+ SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE,
+ gBlendModeMap[static_cast<size_t>(mode)]);
+ }
+}
+
+}; // namespace
+
+void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
+ writer.beginArray(nullptr, false);
+ writer.appendS32(SkColorGetA(color));
+ writer.appendS32(SkColorGetR(color));
+ writer.appendS32(SkColorGetG(color));
+ writer.appendS32(SkColorGetB(color));
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
+ writer.beginArray(nullptr, false);
+ writer.appendFloat(color.fA);
+ writer.appendFloat(color.fR);
+ writer.appendFloat(color.fG);
+ writer.appendFloat(color.fB);
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
+ writer.beginArray(nullptr, false);
+ writer.appendFloat(point.x());
+ writer.appendFloat(point.y());
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
+ writer.beginArray(nullptr, false);
+ writer.appendFloat(x);
+ writer.appendFloat(y);
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
+ writer.beginArray(nullptr, false);
+ writer.appendFloat(point.x());
+ writer.appendFloat(point.y());
+ writer.appendFloat(point.z());
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
+ writer.beginArray(nullptr, false);
+ writer.appendFloat(rect.left());
+ writer.appendFloat(rect.top());
+ writer.appendFloat(rect.right());
+ writer.appendFloat(rect.bottom());
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
+ writer.beginArray(nullptr, false);
+ writer.appendS32(rect.left());
+ writer.appendS32(rect.top());
+ writer.appendS32(rect.right());
+ writer.appendS32(rect.bottom());
+ writer.endArray();
+}
+
+static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
+ writer.beginArray(nullptr, false);
+ DrawCommand::MakeJsonRect(writer, rrect.rect());
+ DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
+ DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
+ DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
+ DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
+ writer.beginArray();
+ for (int r = 0; r < 3; ++r) {
+ writer.beginArray(nullptr, false);
+ for (int c = 0; c < 3; ++c) {
+ writer.appendFloat(matrix[r * 3 + c]);
+ }
+ writer.endArray();
+ }
+ writer.endArray();
+}
+
+void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
+ writer.beginObject();
+ switch (path.getFillType()) {
+ case SkPath::kWinding_FillType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
+ break;
+ case SkPath::kEvenOdd_FillType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
+ break;
+ case SkPath::kInverseWinding_FillType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
+ DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
+ break;
+ case SkPath::kInverseEvenOdd_FillType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
+ DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
+ break;
+ }
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
+ SkPath::Iter iter(path, false);
+ SkPoint pts[4];
+ SkPath::Verb verb;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ if (verb == SkPath::kClose_Verb) {
+ writer.appendString(DEBUGCANVAS_VERB_CLOSE);
+ continue;
+ }
+ writer.beginObject(); // verb
+ switch (verb) {
+ case SkPath::kLine_Verb: {
+ writer.appendName(DEBUGCANVAS_VERB_LINE);
+ MakeJsonPoint(writer, pts[1]);
+ break;
+ }
+ case SkPath::kQuad_Verb: {
+ writer.beginArray(DEBUGCANVAS_VERB_QUAD);
+ MakeJsonPoint(writer, pts[1]);
+ MakeJsonPoint(writer, pts[2]);
+ writer.endArray(); // quad coords
+ break;
+ }
+ case SkPath::kCubic_Verb: {
+ writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
+ MakeJsonPoint(writer, pts[1]);
+ MakeJsonPoint(writer, pts[2]);
+ MakeJsonPoint(writer, pts[3]);
+ writer.endArray(); // cubic coords
+ break;
+ }
+ case SkPath::kConic_Verb: {
+ writer.beginArray(DEBUGCANVAS_VERB_CONIC);
+ MakeJsonPoint(writer, pts[1]);
+ MakeJsonPoint(writer, pts[2]);
+ writer.appendFloat(iter.conicWeight());
+ writer.endArray(); // conic coords
+ break;
+ }
+ case SkPath::kMove_Verb: {
+ writer.appendName(DEBUGCANVAS_VERB_MOVE);
+ MakeJsonPoint(writer, pts[0]);
+ break;
+ }
+ case SkPath::kClose_Verb:
+ case SkPath::kDone_Verb:
+ // Unreachable
+ break;
+ }
+ writer.endObject(); // verb
+ }
+ writer.endArray(); // verbs
+ writer.endObject(); // path
+}
+
+void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
+ // TODO: Actually serialize the rectangles, rather than just devolving to path
+ SkPath path;
+ region.getBoundaryPath(&path);
+ MakeJsonPath(writer, path);
+}
+
+static const char* regionop_name(SkClipOp op) {
+ switch (op) {
+ case kDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_DIFFERENCE;
+ case kIntersect_SkClipOp: return DEBUGCANVAS_REGIONOP_INTERSECT;
+ case kUnion_SkClipOp: return DEBUGCANVAS_REGIONOP_UNION;
+ case kXOR_SkClipOp: return DEBUGCANVAS_REGIONOP_XOR;
+ case kReverseDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE;
+ case kReplace_SkClipOp: return DEBUGCANVAS_REGIONOP_REPLACE;
+ default: SkASSERT(false); return "<invalid region op>";
+ }
+}
+
+static const char* pointmode_name(SkCanvas::PointMode mode) {
+ switch (mode) {
+ case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
+ case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
+ case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
+ default: SkASSERT(false); return "<invalid point mode>";
+ }
+}
+
+static void store_scalar(SkJSONWriter& writer,
+ const char* key,
+ SkScalar value,
+ SkScalar defaultValue) {
+ if (value != defaultValue) {
+ writer.appendFloat(key, value);
+ }
+}
+
+static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
+ if (value != defaultValue) {
+ writer.appendBool(key, value);
+ }
+}
+
+static SkString encode_data(const void* bytes,
+ size_t count,
+ const char* contentType,
+ UrlDataManager& urlDataManager) {
+ sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
+ return urlDataManager.addData(data.get(), contentType);
+}
+
+void DrawCommand::flatten(const SkFlattenable* flattenable,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ SkBinaryWriteBuffer buffer;
+ flattenable->flatten(buffer);
+ void* data = sk_malloc_throw(buffer.bytesWritten());
+ buffer.writeToMemory(data);
+ SkString url =
+ encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
+
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
+ JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
+ flattenable->flatten(jsonBuffer);
+ writer.endObject(); // values
+
+ sk_free(data);
+}
+
+void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
+ SkPixmap pm;
+ SkAssertResult(bitmap.peekPixels(&pm));
+
+ SkPngEncoder::Options options;
+ options.fZLibLevel = 1;
+ options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
+ SkPngEncoder::Encode(&out, pm, options);
+}
+
+bool DrawCommand::flatten(const SkImage& image,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ size_t rowBytes = 4 * image.width();
+ SkAutoMalloc buffer(rowBytes * image.height());
+ SkImageInfo dstInfo =
+ SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType);
+ if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
+ SkDebugf("readPixels failed\n");
+ return false;
+ }
+
+ SkBitmap bm;
+ bm.installPixels(dstInfo, buffer.get(), rowBytes);
+
+ SkDynamicMemoryWStream out;
+ DrawCommand::WritePNG(bm, out);
+ sk_sp<SkData> encoded = out.detachAsData();
+ SkString url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
+ return true;
+}
+
+static const char* color_type_name(SkColorType colorType) {
+ switch (colorType) {
+ case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
+ case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
+ case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
+ case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
+ case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
+ case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
+ default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
+ }
+}
+
+static const char* alpha_type_name(SkAlphaType alphaType) {
+ switch (alphaType) {
+ case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
+ case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
+ case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
+ default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
+ }
+}
+
+bool DrawCommand::flatten(const SkBitmap& bitmap,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
+ bool success = flatten(*image, writer, urlDataManager);
+ return success;
+}
+
+static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
+ SkFontHinting hinting = font.getHinting();
+ if (hinting != SkPaintDefaults_Hinting) {
+ switch (hinting) {
+ case SkFontHinting::kNone:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
+ break;
+ case SkFontHinting::kSlight:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
+ break;
+ case SkFontHinting::kNormal:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
+ break;
+ case SkFontHinting::kFull:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
+ break;
+ }
+ }
+}
+
+static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
+ switch (font.getEdging()) {
+ case SkFont::Edging::kAlias:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
+ break;
+ case SkFont::Edging::kAntiAlias:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
+ break;
+ case SkFont::Edging::kSubpixelAntiAlias:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
+ break;
+ }
+}
+
+static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
+ SkColor color = paint.getColor();
+ if (color != SK_ColorBLACK) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
+ DrawCommand::MakeJsonColor(writer, color);
+ }
+}
+
+static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
+ SkPaint::Style style = paint.getStyle();
+ if (style != SkPaint::kFill_Style) {
+ switch (style) {
+ case SkPaint::kStroke_Style: {
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
+ break;
+ }
+ case SkPaint::kStrokeAndFill_Style: {
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
+ break;
+ }
+ default: SkASSERT(false);
+ }
+ }
+}
+
+static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
+ SkPaint::Cap cap = paint.getStrokeCap();
+ if (cap != SkPaint::kDefault_Cap) {
+ switch (cap) {
+ case SkPaint::kButt_Cap:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
+ break;
+ case SkPaint::kRound_Cap:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
+ break;
+ case SkPaint::kSquare_Cap:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
+ break;
+ default: SkASSERT(false);
+ }
+ }
+}
+
+static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
+ SkPaint::Join join = paint.getStrokeJoin();
+ if (join != SkPaint::kDefault_Join) {
+ switch (join) {
+ case SkPaint::kMiter_Join:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
+ break;
+ case SkPaint::kRound_Join:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
+ break;
+ case SkPaint::kBevel_Join:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
+ break;
+ default: SkASSERT(false);
+ }
+ }
+}
+
+static void apply_paint_filterquality(const SkPaint& paint, SkJSONWriter& writer) {
+ SkFilterQuality quality = paint.getFilterQuality();
+ switch (quality) {
+ case kNone_SkFilterQuality: break;
+ case kLow_SkFilterQuality:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY, DEBUGCANVAS_FILTERQUALITY_LOW);
+ break;
+ case kMedium_SkFilterQuality:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
+ DEBUGCANVAS_FILTERQUALITY_MEDIUM);
+ break;
+ case kHigh_SkFilterQuality:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
+ DEBUGCANVAS_FILTERQUALITY_HIGH);
+ break;
+ }
+}
+
+static void apply_paint_maskfilter(const SkPaint& paint,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ SkMaskFilter* maskFilter = paint.getMaskFilter();
+ if (maskFilter != nullptr) {
+ SkMaskFilterBase::BlurRec blurRec;
+ if (as_MFB(maskFilter)->asABlur(&blurRec)) {
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
+ switch (blurRec.fStyle) {
+ case SkBlurStyle::kNormal_SkBlurStyle:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
+ break;
+ case SkBlurStyle::kSolid_SkBlurStyle:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
+ break;
+ case SkBlurStyle::kOuter_SkBlurStyle:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
+ break;
+ case SkBlurStyle::kInner_SkBlurStyle:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
+ break;
+ default: SkASSERT(false);
+ }
+ writer.endObject(); // blur
+ } else {
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
+ DrawCommand::flatten(maskFilter, writer, urlDataManager);
+ writer.endObject(); // maskFilter
+ }
+ }
+}
+
+static void apply_paint_patheffect(const SkPaint& paint,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ SkPathEffect* pathEffect = paint.getPathEffect();
+ if (pathEffect != nullptr) {
+ SkPathEffect::DashInfo dashInfo;
+ SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
+ if (dashType == SkPathEffect::kDash_DashType) {
+ dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
+ pathEffect->asADash(&dashInfo);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
+ for (int32_t i = 0; i < dashInfo.fCount; i++) {
+ writer.appendFloat(dashInfo.fIntervals[i]);
+ }
+ writer.endArray(); // intervals
+ sk_free(dashInfo.fIntervals);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
+ writer.endObject(); // dashing
+ } else {
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
+ DrawCommand::flatten(pathEffect, writer, urlDataManager);
+ writer.endObject(); // pathEffect
+ }
+ }
+}
+
+static void apply_font_typeface(const SkFont& font,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ SkTypeface* typeface = font.getTypefaceOrDefault();
+ if (typeface != nullptr) {
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
+ SkDynamicMemoryWStream buffer;
+ typeface->serialize(&buffer);
+ void* data = sk_malloc_throw(buffer.bytesWritten());
+ buffer.copyTo(data);
+ SkString url = encode_data(
+ data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
+ sk_free(data);
+ writer.endObject();
+ }
+}
+
+static void apply_flattenable(const char* key,
+ SkFlattenable* flattenable,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager) {
+ if (flattenable != nullptr) {
+ writer.beginObject(key);
+ DrawCommand::flatten(flattenable, writer, urlDataManager);
+ writer.endObject();
+ }
+}
+
+void DrawCommand::MakeJsonPaint(SkJSONWriter& writer,
+ const SkPaint& paint,
+ UrlDataManager& urlDataManager) {
+ writer.beginObject();
+ store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
+ store_scalar(writer,
+ DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
+ paint.getStrokeMiter(),
+ SkPaintDefaults_MiterLimit);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
+
+ apply_paint_color(paint, writer);
+ apply_paint_style(paint, writer);
+ apply_paint_blend_mode(paint, writer);
+ apply_paint_cap(paint, writer);
+ apply_paint_join(paint, writer);
+ apply_paint_filterquality(paint, writer);
+ apply_paint_patheffect(paint, writer, urlDataManager);
+ apply_paint_maskfilter(paint, writer, urlDataManager);
+ apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
+ apply_flattenable(
+ DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
+ apply_flattenable(
+ DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
+ writer.endObject(); // paint
+}
+
+static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
+ writer.beginObject();
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
+ store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
+
+ store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
+ store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
+ store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
+ apply_font_edging(font, writer);
+ apply_font_hinting(font, writer);
+ apply_font_typeface(font, writer, urlDataManager);
+ writer.endObject(); // font
+}
+
+void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
+ writer.beginObject();
+ writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
+ writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
+ if (nullptr != lattice.fBounds) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
+ MakeJsonIRect(writer, *lattice.fBounds);
+ }
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
+ for (int i = 0; i < lattice.fXCount; i++) {
+ writer.appendS32(lattice.fXDivs[i]);
+ }
+ writer.endArray(); // xdivs
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
+ for (int i = 0; i < lattice.fYCount; i++) {
+ writer.appendS32(lattice.fYDivs[i]);
+ }
+ writer.endArray(); // ydivs
+ if (nullptr != lattice.fRectTypes) {
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
+ int flagCount = 0;
+ for (int row = 0; row < lattice.fYCount + 1; row++) {
+ writer.beginArray();
+ for (int column = 0; column < lattice.fXCount + 1; column++) {
+ writer.appendS32(lattice.fRectTypes[flagCount++]);
+ }
+ writer.endArray(); // row
+ }
+ writer.endArray();
+ }
+ writer.endObject();
+}
+
+ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
+
+void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
+
+void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
+ MakeJsonColor(writer, fColor);
+}
+
+ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
+ : INHERITED(kClipPath_OpType) {
+ fPath = path;
+ fOp = op;
+ fDoAA = doAA;
+}
+
+void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
+
+bool ClipPathCommand::render(SkCanvas* canvas) const {
+ render_path(canvas, fPath);
+ return true;
+}
+
+void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
+ MakeJsonPath(writer, fPath);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
+}
+
+ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
+ : INHERITED(kClipRegion_OpType) {
+ fRegion = region;
+ fOp = op;
+}
+
+void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
+
+void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
+ MakeJsonRegion(writer, fRegion);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
+}
+
+ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
+ : INHERITED(kClipRect_OpType) {
+ fRect = rect;
+ fOp = op;
+ fDoAA = doAA;
+}
+
+void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
+
+void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, fRect);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
+}
+
+ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
+ : INHERITED(kClipRRect_OpType) {
+ fRRect = rrect;
+ fOp = op;
+ fDoAA = doAA;
+}
+
+void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
+
+bool ClipRRectCommand::render(SkCanvas* canvas) const {
+ render_rrect(canvas, fRRect);
+ return true;
+}
+
+void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ make_json_rrect(writer, fRRect);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
+}
+
+ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
+ fMatrix = matrix;
+}
+
+void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
+
+void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
+ MakeJsonMatrix(writer, fMatrix);
+}
+
+////
+
+DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
+ const char key[],
+ sk_sp<SkData> value)
+ : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
+
+void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
+ canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
+}
+
+void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, fRect);
+ writer.appendString("key", fKey.c_str());
+ if (fValue.get()) {
+ // TODO: dump out the "value"
+ }
+
+ SkString desc;
+ str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
+}
+
+////
+
+DrawBitmapCommand::DrawBitmapCommand(const SkBitmap& bitmap,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint)
+ : INHERITED(kDrawBitmap_OpType), fBitmap(bitmap), fLeft(left), fTop(top), fPaint(paint) {}
+
+void DrawBitmapCommand::execute(SkCanvas* canvas) const {
+ canvas->drawBitmap(fBitmap, fLeft, fTop, fPaint.getMaybeNull());
+}
+
+bool DrawBitmapCommand::render(SkCanvas* canvas) const {
+ render_bitmap(canvas, fBitmap);
+ return true;
+}
+
+void DrawBitmapCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
+ flatten(fBitmap, writer, urlDataManager);
+ writer.endObject();
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonPoint(writer, fLeft, fTop);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+}
+
+DrawBitmapLatticeCommand::DrawBitmapLatticeCommand(const SkBitmap& bitmap,
+ const SkCanvas::Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint)
+ : INHERITED(kDrawBitmapLattice_OpType)
+ , fBitmap(bitmap)
+ , fLattice(lattice)
+ , fDst(dst)
+ , fPaint(paint) {}
+
+void DrawBitmapLatticeCommand::execute(SkCanvas* canvas) const {
+ canvas->drawBitmapLattice(fBitmap, fLattice, fDst, fPaint.getMaybeNull());
+}
+
+bool DrawBitmapLatticeCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(canvas, fDst);
+
+ this->execute(canvas);
+ return true;
+}
+
+void DrawBitmapLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
+ flatten(fBitmap, writer, urlDataManager);
+ writer.endObject(); // bitmap
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
+ MakeJsonLattice(writer, fLattice);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
+}
+
+DrawBitmapNineCommand::DrawBitmapNineCommand(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint)
+ : INHERITED(kDrawBitmapNine_OpType)
+ , fBitmap(bitmap)
+ , fCenter(center)
+ , fDst(dst)
+ , fPaint(paint) {}
+
+void DrawBitmapNineCommand::execute(SkCanvas* canvas) const {
+ canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaint.getMaybeNull());
+}
+
+bool DrawBitmapNineCommand::render(SkCanvas* canvas) const {
+ SkRect tmp = SkRect::Make(fCenter);
+ render_bitmap(canvas, fBitmap, &tmp);
+ return true;
+}
+
+void DrawBitmapNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
+ flatten(fBitmap, writer, urlDataManager);
+ writer.endObject(); // bitmap
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
+ MakeJsonIRect(writer, fCenter);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+}
+
+DrawBitmapRectCommand::DrawBitmapRectCommand(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SkCanvas::SrcRectConstraint constraint)
+ : INHERITED(kDrawBitmapRect_OpType)
+ , fBitmap(bitmap)
+ , fSrc(src)
+ , fDst(dst)
+ , fPaint(paint)
+ , fConstraint(constraint) {}
+
+void DrawBitmapRectCommand::execute(SkCanvas* canvas) const {
+ canvas->legacy_drawBitmapRect(
+ fBitmap, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
+}
+
+bool DrawBitmapRectCommand::render(SkCanvas* canvas) const {
+ render_bitmap(canvas, fBitmap, fSrc.getMaybeNull());
+ return true;
+}
+
+void DrawBitmapRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
+ flatten(fBitmap, writer, urlDataManager);
+ writer.endObject(); // bitmap
+
+ if (fSrc.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
+ MakeJsonRect(writer, *fSrc);
+ }
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+ if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
+ }
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
+}
+
+DrawImageCommand::DrawImageCommand(const SkImage* image,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint)
+ : INHERITED(kDrawImage_OpType)
+ , fImage(SkRef(image))
+ , fLeft(left)
+ , fTop(top)
+ , fPaint(paint) {}
+
+void DrawImageCommand::execute(SkCanvas* canvas) const {
+ canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
+}
+
+bool DrawImageCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(
+ canvas,
+ SkRect::MakeXYWH(
+ fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
+ this->execute(canvas);
+ return true;
+}
+
+void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
+ flatten(*fImage, writer, urlDataManager);
+ writer.endObject(); // image
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonPoint(writer, fLeft, fTop);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+
+ writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
+ writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
+ writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
+ switch (fImage->alphaType()) {
+ case kOpaque_SkAlphaType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
+ break;
+ case kPremul_SkAlphaType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
+ break;
+ case kUnpremul_SkAlphaType:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
+ break;
+ default:
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
+ break;
+ }
+}
+
+DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage* image,
+ const SkCanvas::Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint)
+ : INHERITED(kDrawImageLattice_OpType)
+ , fImage(SkRef(image))
+ , fLattice(lattice)
+ , fDst(dst)
+ , fPaint(paint) {}
+
+void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
+ canvas->drawImageLattice(fImage.get(), fLattice, fDst, fPaint.getMaybeNull());
+}
+
+bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(canvas, fDst);
+
+ this->execute(canvas);
+ return true;
+}
+
+void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
+ flatten(*fImage, writer, urlDataManager);
+ writer.endObject(); // image
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
+ MakeJsonLattice(writer, fLattice);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
+}
+
+DrawImageRectCommand::DrawImageRectCommand(const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SkCanvas::SrcRectConstraint constraint)
+ : INHERITED(kDrawImageRect_OpType)
+ , fImage(SkRef(image))
+ , fSrc(src)
+ , fDst(dst)
+ , fPaint(paint)
+ , fConstraint(constraint) {}
+
+void DrawImageRectCommand::execute(SkCanvas* canvas) const {
+ canvas->legacy_drawImageRect(
+ fImage.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
+}
+
+bool DrawImageRectCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(canvas, fDst);
+
+ this->execute(canvas);
+ return true;
+}
+
+void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
+ flatten(*fImage, writer, urlDataManager);
+ writer.endObject(); // image
+
+ if (fSrc.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
+ MakeJsonRect(writer, *fSrc);
+ }
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+ if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
+ }
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
+}
+
+DrawImageNineCommand::DrawImageNineCommand(const SkImage* image,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint)
+ : INHERITED(kDrawImageNine_OpType)
+ , fImage(SkRef(image))
+ , fCenter(center)
+ , fDst(dst)
+ , fPaint(paint) {}
+
+void DrawImageNineCommand::execute(SkCanvas* canvas) const {
+ canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaint.getMaybeNull());
+}
+
+bool DrawImageNineCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(canvas, fDst);
+
+ this->execute(canvas);
+ return true;
+}
+
+void DrawImageNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
+ flatten(*fImage, writer, urlDataManager);
+ writer.endObject(); // image
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
+ MakeJsonIRect(writer, fCenter);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
+ MakeJsonRect(writer, fDst);
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+}
+
+DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
+ : INHERITED(kDrawOval_OpType) {
+ fOval = oval;
+ fPaint = paint;
+}
+
+void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
+
+bool DrawOvalCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ xlate_and_scale_to_bounds(canvas, fOval);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawOval(fOval, p);
+ canvas->restore();
+
+ return true;
+}
+
+void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, fOval);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawArcCommand::DrawArcCommand(const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const SkPaint& paint)
+ : INHERITED(kDrawArc_OpType) {
+ fOval = oval;
+ fStartAngle = startAngle;
+ fSweepAngle = sweepAngle;
+ fUseCenter = useCenter;
+ fPaint = paint;
+}
+
+void DrawArcCommand::execute(SkCanvas* canvas) const {
+ canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
+}
+
+bool DrawArcCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ xlate_and_scale_to_bounds(canvas, fOval);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
+ canvas->restore();
+
+ return true;
+}
+
+void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, fOval);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
+ writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
+ fPaint = paint;
+}
+
+void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
+
+bool DrawPaintCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ canvas->drawPaint(fPaint);
+ return true;
+}
+
+void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
+ fPaint = paint;
+}
+
+void DrawBehindCommand::execute(SkCanvas* canvas) const {
+ SkCanvasPriv::DrawBehind(canvas, fPaint);
+}
+
+bool DrawBehindCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ SkCanvasPriv::DrawBehind(canvas, fPaint);
+ return true;
+}
+
+void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
+ : INHERITED(kDrawPath_OpType) {
+ fPath = path;
+ fPaint = paint;
+}
+
+void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
+
+bool DrawPathCommand::render(SkCanvas* canvas) const {
+ render_path(canvas, fPath);
+ return true;
+}
+
+void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
+ MakeJsonPath(writer, fPath);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
+ : INHERITED(kDrawRegion_OpType) {
+ fRegion = region;
+ fPaint = paint;
+}
+
+void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
+
+bool DrawRegionCommand::render(SkCanvas* canvas) const {
+ render_region(canvas, fRegion);
+ return true;
+}
+
+void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
+ MakeJsonRegion(writer, fRegion);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint)
+ : INHERITED(kBeginDrawPicture_OpType)
+ , fPicture(SkRef(picture))
+ , fMatrix(matrix)
+ , fPaint(paint) {}
+
+void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
+ if (fPaint.isValid()) {
+ SkRect bounds = fPicture->cullRect();
+ if (fMatrix.isValid()) {
+ fMatrix->mapRect(&bounds);
+ }
+ canvas->saveLayer(&bounds, fPaint.get());
+ }
+
+ if (fMatrix.isValid()) {
+ if (!fPaint.isValid()) {
+ canvas->save();
+ }
+ canvas->concat(*fMatrix);
+ }
+}
+
+bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
+
+ canvas->drawPicture(fPicture.get());
+
+ canvas->restore();
+
+ return true;
+}
+
+EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
+ : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
+
+void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
+ if (fRestore) {
+ canvas->restore();
+ }
+}
+
+DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
+ size_t count,
+ const SkPoint pts[],
+ const SkPaint& paint)
+ : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
+
+void DrawPointsCommand::execute(SkCanvas* canvas) const {
+ canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
+}
+
+bool DrawPointsCommand::render(SkCanvas* canvas) const {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ SkRect bounds;
+
+ bounds.setEmpty();
+ for (int i = 0; i < fPts.count(); ++i) {
+ SkRectPriv::GrowToInclude(&bounds, fPts[i]);
+ }
+
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
+ canvas->restore();
+
+ return true;
+}
+
+void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
+ for (int i = 0; i < fPts.count(); i++) {
+ MakeJsonPoint(writer, fPts[i]);
+ }
+ writer.endArray(); // points
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
+ SkScalar x,
+ SkScalar y,
+ const SkPaint& paint)
+ : INHERITED(kDrawTextBlob_OpType)
+ , fBlob(std::move(blob))
+ , fXPos(x)
+ , fYPos(y)
+ , fPaint(paint) {}
+
+void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
+ canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
+}
+
+bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
+ canvas->clear(SK_ColorWHITE);
+ canvas->save();
+
+ SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
+
+ canvas->restore();
+
+ return true;
+}
+
+void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
+ SkTextBlobRunIterator iter(fBlob.get());
+ while (!iter.done()) {
+ writer.beginObject(); // run
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
+ for (uint32_t i = 0; i < iter.glyphCount(); i++) {
+ writer.appendU32(iter.glyphs()[i]);
+ }
+ writer.endArray(); // glyphs
+ if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
+ const SkScalar* iterPositions = iter.pos();
+ for (uint32_t i = 0; i < iter.glyphCount(); i++) {
+ switch (iter.positioning()) {
+ case SkTextBlobRunIterator::kFull_Positioning:
+ MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
+ break;
+ case SkTextBlobRunIterator::kHorizontal_Positioning:
+ writer.appendFloat(iterPositions[i]);
+ break;
+ case SkTextBlobRunIterator::kDefault_Positioning: break;
+ case SkTextBlobRunIterator::kRSXform_Positioning:
+ // TODO_RSXFORM_BLOB
+ break;
+ }
+ }
+ writer.endArray(); // positions
+ }
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
+ MakeJsonFont(iter.font(), writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonPoint(writer, iter.offset());
+
+ writer.endObject(); // run
+ iter.next();
+ }
+ writer.endArray(); // runs
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
+ SkRect bounds = fBlob->bounds();
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, bounds);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+
+ SkString desc;
+ // make the bounds local by applying the x,y
+ bounds.offset(fXPos, fYPos);
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
+}
+
+DrawPatchCommand::DrawPatchCommand(const SkPoint cubics[12],
+ const SkColor colors[4],
+ const SkPoint texCoords[4],
+ SkBlendMode bmode,
+ const SkPaint& paint)
+ : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
+ memcpy(fCubics, cubics, sizeof(fCubics));
+ if (colors != nullptr) {
+ memcpy(fColors, colors, sizeof(fColors));
+ fColorsPtr = fColors;
+ } else {
+ fColorsPtr = nullptr;
+ }
+ if (texCoords != nullptr) {
+ memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
+ fTexCoordsPtr = fTexCoords;
+ } else {
+ fTexCoordsPtr = nullptr;
+ }
+ fPaint = paint;
+}
+
+void DrawPatchCommand::execute(SkCanvas* canvas) const {
+ canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
+}
+
+void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
+ for (int i = 0; i < 12; i++) {
+ MakeJsonPoint(writer, fCubics[i]);
+ }
+ writer.endArray(); // cubics
+ if (fColorsPtr != nullptr) {
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
+ for (int i = 0; i < 4; i++) {
+ MakeJsonColor(writer, fColorsPtr[i]);
+ }
+ writer.endArray(); // colors
+ }
+ if (fTexCoordsPtr != nullptr) {
+ writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
+ for (int i = 0; i < 4; i++) {
+ MakeJsonPoint(writer, fTexCoords[i]);
+ }
+ writer.endArray(); // texCoords
+ }
+ // fBlendMode
+}
+
+DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
+ : INHERITED(kDrawRect_OpType) {
+ fRect = rect;
+ fPaint = paint;
+}
+
+void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
+
+void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ MakeJsonRect(writer, fRect);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+
+ SkString desc;
+ writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
+}
+
+DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
+ : INHERITED(kDrawRRect_OpType) {
+ fRRect = rrect;
+ fPaint = paint;
+}
+
+void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
+
+bool DrawRRectCommand::render(SkCanvas* canvas) const {
+ render_rrect(canvas, fRRect);
+ return true;
+}
+
+void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
+ make_json_rrect(writer, fRRect);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
+ const SkRRect& inner,
+ const SkPaint& paint)
+ : INHERITED(kDrawDRRect_OpType) {
+ fOuter = outer;
+ fInner = inner;
+ fPaint = paint;
+}
+
+void DrawDRRectCommand::execute(SkCanvas* canvas) const {
+ canvas->drawDRRect(fOuter, fInner, fPaint);
+}
+
+bool DrawDRRectCommand::render(SkCanvas* canvas) const {
+ render_drrect(canvas, fOuter, fInner);
+ return true;
+}
+
+void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
+ make_json_rrect(writer, fOuter);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
+ make_json_rrect(writer, fInner);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, fPaint, urlDataManager);
+}
+
+DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
+ : INHERITED(kDrawShadow_OpType) {
+ fPath = path;
+ fShadowRec = rec;
+}
+
+void DrawShadowCommand::execute(SkCanvas* canvas) const {
+ canvas->private_draw_shadow_rec(fPath, fShadowRec);
+}
+
+bool DrawShadowCommand::render(SkCanvas* canvas) const {
+ render_shadow(canvas, fPath, fShadowRec);
+ return true;
+}
+
+void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+
+ bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
+ bool transparentOccluder =
+ SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
+
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
+ MakeJsonPath(writer, fPath);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
+ MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
+ MakeJsonPoint3(writer, fShadowRec.fLightPos);
+ writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
+ MakeJsonColor(writer, fShadowRec.fAmbientColor);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
+ MakeJsonColor(writer, fShadowRec.fSpotColor);
+ store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
+ store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect& rect,
+ const SkPoint clip[],
+ SkCanvas::QuadAAFlags aa,
+ const SkColor4f& color,
+ SkBlendMode mode)
+ : INHERITED(kDrawEdgeAAQuad_OpType)
+ , fRect(rect)
+ , fHasClip(clip != nullptr)
+ , fAA(aa)
+ , fColor(color)
+ , fMode(mode) {
+ if (clip) {
+ for (int i = 0; i < 4; ++i) {
+ fClip[i] = clip[i];
+ }
+ }
+}
+
+void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
+ canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
+}
+
+DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
+ int count,
+ const SkPoint dstClips[],
+ const SkMatrix preViewMatrices[],
+ const SkPaint* paint,
+ SkCanvas::SrcRectConstraint constraint)
+ : INHERITED(kDrawEdgeAAImageSet_OpType)
+ , fSet(count)
+ , fCount(count)
+ , fPaint(paint)
+ , fConstraint(constraint) {
+ int totalDstClipCount, totalMatrixCount;
+ SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
+
+ std::copy_n(set, count, fSet.get());
+ fDstClips.reset(totalDstClipCount);
+ std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
+ fPreViewMatrices.reset(totalMatrixCount);
+ std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
+}
+
+void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
+ canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
+ fCount,
+ fDstClips.get(),
+ fPreViewMatrices.get(),
+ fPaint.getMaybeNull(),
+ fConstraint);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
+ : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
+
+void DrawDrawableCommand::execute(SkCanvas* canvas) const {
+ canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
+ SkBlendMode bmode,
+ const SkPaint& paint)
+ : INHERITED(kDrawVertices_OpType)
+ , fVertices(std::move(vertices))
+ , fBlendMode(bmode)
+ , fPaint(paint) {}
+
+void DrawVerticesCommand::execute(SkCanvas* canvas) const {
+ canvas->drawVertices(fVertices, fBlendMode, fPaint);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DrawAtlasCommand::DrawAtlasCommand(const SkImage* image,
+ const SkRSXform xform[],
+ const SkRect tex[],
+ const SkColor colors[],
+ int count,
+ SkBlendMode bmode,
+ const SkRect* cull,
+ const SkPaint* paint)
+ : INHERITED(kDrawAtlas_OpType)
+ , fImage(SkRef(image))
+ , fXform(xform, count)
+ , fTex(tex, count)
+ , fColors(colors, colors ? count : 0)
+ , fBlendMode(bmode)
+ , fCull(cull)
+ , fPaint(paint) {}
+
+void DrawAtlasCommand::execute(SkCanvas* canvas) const {
+ canvas->drawAtlas(fImage.get(),
+ fXform.begin(),
+ fTex.begin(),
+ fColors.isEmpty() ? nullptr : fColors.begin(),
+ fXform.count(),
+ fBlendMode,
+ fCull.getMaybeNull(),
+ fPaint.getMaybeNull());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
+
+void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
+
+SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
+
+void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
+
+SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
+ : INHERITED(kSaveLayer_OpType)
+ , fBounds(rec.fBounds)
+ , fPaint(rec.fPaint)
+ , fBackdrop(SkSafeRef(rec.fBackdrop))
+ , fSaveLayerFlags(rec.fSaveLayerFlags) {}
+
+void SaveLayerCommand::execute(SkCanvas* canvas) const {
+ canvas->saveLayer(
+ SkCanvas::SaveLayerRec(fBounds.getMaybeNull(), fPaint.getMaybeNull(), fSaveLayerFlags));
+}
+
+void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ if (fBounds.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
+ MakeJsonRect(writer, *fBounds);
+ }
+ if (fPaint.isValid()) {
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
+ MakeJsonPaint(writer, *fPaint, urlDataManager);
+ }
+ if (fBackdrop != nullptr) {
+ writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
+ flatten(fBackdrop.get(), writer, urlDataManager);
+ writer.endObject(); // backdrop
+ }
+ if (fSaveLayerFlags != 0) {
+ SkDebugf("unsupported: saveLayer flags\n");
+ SkASSERT(false);
+ }
+}
+
+SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
+ fMatrix = matrix;
+}
+
+void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
+
+void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
+ INHERITED::toJSON(writer, urlDataManager);
+ writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
+ MakeJsonMatrix(writer, fMatrix);
+}
diff --git a/src/third_party/skia/tools/debugger/DrawCommand.h b/src/third_party/skia/tools/debugger/DrawCommand.h
new file mode 100644
index 0000000..84e1ec0
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/DrawCommand.h
@@ -0,0 +1,728 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKDRAWCOMMAND_H_
+#define SKDRAWCOMMAND_H_
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkRRect.h"
+#include "include/core/SkRSXform.h"
+#include "include/core/SkRegion.h"
+#include "include/core/SkString.h"
+#include "include/core/SkVertices.h"
+#include "include/private/SkTDArray.h"
+#include "src/core/SkDrawShadowInfo.h"
+#include "src/core/SkTLazy.h"
+#include "src/utils/SkJSONWriter.h"
+#include "tools/UrlDataManager.h"
+
+class DrawCommand {
+public:
+ enum OpType {
+ kBeginDrawPicture_OpType,
+ kClear_OpType,
+ kClipPath_OpType,
+ kClipRegion_OpType,
+ kClipRect_OpType,
+ kClipRRect_OpType,
+ kConcat_OpType,
+ kDrawAnnotation_OpType,
+ kDrawBitmap_OpType,
+ kDrawBitmapLattice_OpType,
+ kDrawBitmapNine_OpType,
+ kDrawBitmapRect_OpType,
+ kDrawDRRect_OpType,
+ kDrawImage_OpType,
+ kDrawImageLattice_OpType,
+ kDrawImageNine_OpType,
+ kDrawImageRect_OpType,
+ kDrawOval_OpType,
+ kDrawArc_OpType,
+ kDrawPaint_OpType,
+ kDrawPatch_OpType,
+ kDrawPath_OpType,
+ kDrawPoints_OpType,
+ kDrawRect_OpType,
+ kDrawRRect_OpType,
+ kDrawRegion_OpType,
+ kDrawShadow_OpType,
+ kDrawTextBlob_OpType,
+ kDrawVertices_OpType,
+ kDrawAtlas_OpType,
+ kDrawDrawable_OpType,
+ kDrawEdgeAAQuad_OpType,
+ kDrawEdgeAAImageSet_OpType,
+ kEndDrawPicture_OpType,
+ kRestore_OpType,
+ kSave_OpType,
+ kSaveLayer_OpType,
+ kSetMatrix_OpType,
+
+ kLast_OpType = kSetMatrix_OpType
+ };
+
+ static const int kOpTypeCount = kLast_OpType + 1;
+
+ static void WritePNG(SkBitmap bitmap, SkWStream& out);
+
+ DrawCommand(OpType opType);
+
+ virtual ~DrawCommand() {}
+
+ bool isVisible() const { return fVisible; }
+
+ void setVisible(bool toggle) { fVisible = toggle; }
+
+ virtual void execute(SkCanvas*) const = 0;
+
+ virtual bool render(SkCanvas* canvas) const { return false; }
+
+ virtual void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const;
+
+ static const char* GetCommandString(OpType type);
+
+ // Helper methods for converting things to JSON
+ static void MakeJsonColor(SkJSONWriter&, const SkColor color);
+ static void MakeJsonColor4f(SkJSONWriter&, const SkColor4f& color);
+ static void MakeJsonPoint(SkJSONWriter&, const SkPoint& point);
+ static void MakeJsonPoint(SkJSONWriter&, SkScalar x, SkScalar y);
+ static void MakeJsonPoint3(SkJSONWriter&, const SkPoint3& point);
+ static void MakeJsonRect(SkJSONWriter&, const SkRect& rect);
+ static void MakeJsonIRect(SkJSONWriter&, const SkIRect&);
+ static void MakeJsonMatrix(SkJSONWriter&, const SkMatrix&);
+ static void MakeJsonPath(SkJSONWriter&, const SkPath& path);
+ static void MakeJsonRegion(SkJSONWriter&, const SkRegion& region);
+ static void MakeJsonPaint(SkJSONWriter&, const SkPaint& paint, UrlDataManager& urlDataManager);
+ static void MakeJsonLattice(SkJSONWriter&, const SkCanvas::Lattice& lattice);
+
+ static void flatten(const SkFlattenable* flattenable,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager);
+ static bool flatten(const SkImage& image, SkJSONWriter& writer, UrlDataManager& urlDataManager);
+ static bool flatten(const SkBitmap& bitmap,
+ SkJSONWriter& writer,
+ UrlDataManager& urlDataManager);
+
+private:
+ OpType fOpType;
+ bool fVisible;
+};
+
+class RestoreCommand : public DrawCommand {
+public:
+ RestoreCommand();
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ typedef DrawCommand INHERITED;
+};
+
+class ClearCommand : public DrawCommand {
+public:
+ ClearCommand(SkColor color);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkColor fColor;
+
+ typedef DrawCommand INHERITED;
+};
+
+class ClipPathCommand : public DrawCommand {
+public:
+ ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPath fPath;
+ SkClipOp fOp;
+ bool fDoAA;
+
+ typedef DrawCommand INHERITED;
+};
+
+class ClipRegionCommand : public DrawCommand {
+public:
+ ClipRegionCommand(const SkRegion& region, SkClipOp op);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRegion fRegion;
+ SkClipOp fOp;
+
+ typedef DrawCommand INHERITED;
+};
+
+class ClipRectCommand : public DrawCommand {
+public:
+ ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRect fRect;
+ SkClipOp fOp;
+ bool fDoAA;
+
+ typedef DrawCommand INHERITED;
+};
+
+class ClipRRectCommand : public DrawCommand {
+public:
+ ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRRect fRRect;
+ SkClipOp fOp;
+ bool fDoAA;
+
+ typedef DrawCommand INHERITED;
+};
+
+class ConcatCommand : public DrawCommand {
+public:
+ ConcatCommand(const SkMatrix& matrix);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkMatrix fMatrix;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawAnnotationCommand : public DrawCommand {
+public:
+ DrawAnnotationCommand(const SkRect&, const char key[], sk_sp<SkData> value);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRect fRect;
+ SkString fKey;
+ sk_sp<SkData> fValue;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawBitmapCommand : public DrawCommand {
+public:
+ DrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkBitmap fBitmap;
+ SkScalar fLeft;
+ SkScalar fTop;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawBitmapLatticeCommand : public DrawCommand {
+public:
+ DrawBitmapLatticeCommand(const SkBitmap& bitmap,
+ const SkCanvas::Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkBitmap fBitmap;
+ SkCanvas::Lattice fLattice;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawBitmapNineCommand : public DrawCommand {
+public:
+ DrawBitmapNineCommand(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkBitmap fBitmap;
+ SkIRect fCenter;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawBitmapRectCommand : public DrawCommand {
+public:
+ DrawBitmapRectCommand(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SkCanvas::SrcRectConstraint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkBitmap fBitmap;
+ SkTLazy<SkRect> fSrc;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+ SkCanvas::SrcRectConstraint fConstraint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawImageCommand : public DrawCommand {
+public:
+ DrawImageCommand(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ sk_sp<const SkImage> fImage;
+ SkScalar fLeft;
+ SkScalar fTop;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawImageLatticeCommand : public DrawCommand {
+public:
+ DrawImageLatticeCommand(const SkImage* image,
+ const SkCanvas::Lattice& lattice,
+ const SkRect& dst,
+ const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ sk_sp<const SkImage> fImage;
+ SkCanvas::Lattice fLattice;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawImageNineCommand : public DrawCommand {
+public:
+ DrawImageNineCommand(const SkImage* image,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ sk_sp<const SkImage> fImage;
+ SkIRect fCenter;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawImageRectCommand : public DrawCommand {
+public:
+ DrawImageRectCommand(const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SkCanvas::SrcRectConstraint constraint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ sk_sp<const SkImage> fImage;
+ SkTLazy<SkRect> fSrc;
+ SkRect fDst;
+ SkTLazy<SkPaint> fPaint;
+ SkCanvas::SrcRectConstraint fConstraint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawOvalCommand : public DrawCommand {
+public:
+ DrawOvalCommand(const SkRect& oval, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRect fOval;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawArcCommand : public DrawCommand {
+public:
+ DrawArcCommand(const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRect fOval;
+ SkScalar fStartAngle;
+ SkScalar fSweepAngle;
+ bool fUseCenter;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawPaintCommand : public DrawCommand {
+public:
+ DrawPaintCommand(const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawBehindCommand : public DrawCommand {
+public:
+ DrawBehindCommand(const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawPathCommand : public DrawCommand {
+public:
+ DrawPathCommand(const SkPath& path, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPath fPath;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class BeginDrawPictureCommand : public DrawCommand {
+public:
+ BeginDrawPictureCommand(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
+
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+
+private:
+ sk_sp<const SkPicture> fPicture;
+ SkTLazy<SkMatrix> fMatrix;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class EndDrawPictureCommand : public DrawCommand {
+public:
+ EndDrawPictureCommand(bool restore);
+
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ bool fRestore;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawPointsCommand : public DrawCommand {
+public:
+ DrawPointsCommand(SkCanvas::PointMode mode,
+ size_t count,
+ const SkPoint pts[],
+ const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkCanvas::PointMode fMode;
+ SkTDArray<SkPoint> fPts;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawRegionCommand : public DrawCommand {
+public:
+ DrawRegionCommand(const SkRegion& region, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRegion fRegion;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawTextBlobCommand : public DrawCommand {
+public:
+ DrawTextBlobCommand(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ sk_sp<SkTextBlob> fBlob;
+ SkScalar fXPos;
+ SkScalar fYPos;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawPatchCommand : public DrawCommand {
+public:
+ DrawPatchCommand(const SkPoint cubics[12],
+ const SkColor colors[4],
+ const SkPoint texCoords[4],
+ SkBlendMode bmode,
+ const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPoint fCubics[12];
+ SkColor* fColorsPtr;
+ SkColor fColors[4];
+ SkPoint* fTexCoordsPtr;
+ SkPoint fTexCoords[4];
+ SkBlendMode fBlendMode;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawRectCommand : public DrawCommand {
+public:
+ DrawRectCommand(const SkRect& rect, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRect fRect;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawRRectCommand : public DrawCommand {
+public:
+ DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRRect fRRect;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawDRRectCommand : public DrawCommand {
+public:
+ DrawDRRectCommand(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkRRect fOuter;
+ SkRRect fInner;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawVerticesCommand : public DrawCommand {
+public:
+ DrawVerticesCommand(sk_sp<SkVertices>, SkBlendMode, const SkPaint&);
+
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ sk_sp<SkVertices> fVertices;
+ SkBlendMode fBlendMode;
+ SkPaint fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawAtlasCommand : public DrawCommand {
+public:
+ DrawAtlasCommand(const SkImage*,
+ const SkRSXform[],
+ const SkRect[],
+ const SkColor[],
+ int,
+ SkBlendMode,
+ const SkRect*,
+ const SkPaint*);
+
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ sk_sp<const SkImage> fImage;
+ SkTDArray<SkRSXform> fXform;
+ SkTDArray<SkRect> fTex;
+ SkTDArray<SkColor> fColors;
+ SkBlendMode fBlendMode;
+ SkTLazy<SkRect> fCull;
+ SkTLazy<SkPaint> fPaint;
+
+ typedef DrawCommand INHERITED;
+};
+
+class SaveCommand : public DrawCommand {
+public:
+ SaveCommand();
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ typedef DrawCommand INHERITED;
+};
+
+class SaveLayerCommand : public DrawCommand {
+public:
+ SaveLayerCommand(const SkCanvas::SaveLayerRec&);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkTLazy<SkRect> fBounds;
+ SkTLazy<SkPaint> fPaint;
+ sk_sp<const SkImageFilter> fBackdrop;
+ uint32_t fSaveLayerFlags;
+
+ typedef DrawCommand INHERITED;
+};
+
+class SetMatrixCommand : public DrawCommand {
+public:
+ SetMatrixCommand(const SkMatrix& matrix);
+ void execute(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkMatrix fMatrix;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawShadowCommand : public DrawCommand {
+public:
+ DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec);
+ void execute(SkCanvas* canvas) const override;
+ bool render(SkCanvas* canvas) const override;
+ void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
+
+private:
+ SkPath fPath;
+ SkDrawShadowRec fShadowRec;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawDrawableCommand : public DrawCommand {
+public:
+ DrawDrawableCommand(SkDrawable*, const SkMatrix*);
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ sk_sp<SkDrawable> fDrawable;
+ SkTLazy<SkMatrix> fMatrix;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawEdgeAAQuadCommand : public DrawCommand {
+public:
+ DrawEdgeAAQuadCommand(const SkRect& rect,
+ const SkPoint clip[4],
+ SkCanvas::QuadAAFlags aa,
+ const SkColor4f& color,
+ SkBlendMode mode);
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ SkRect fRect;
+ SkPoint fClip[4];
+ int fHasClip;
+ SkCanvas::QuadAAFlags fAA;
+ SkColor4f fColor;
+ SkBlendMode fMode;
+
+ typedef DrawCommand INHERITED;
+};
+
+class DrawEdgeAAImageSetCommand : public DrawCommand {
+public:
+ DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry[],
+ int count,
+ const SkPoint[],
+ const SkMatrix[],
+ const SkPaint*,
+ SkCanvas::SrcRectConstraint);
+ void execute(SkCanvas* canvas) const override;
+
+private:
+ SkAutoTArray<SkCanvas::ImageSetEntry> fSet;
+ int fCount;
+ SkAutoTArray<SkPoint> fDstClips;
+ SkAutoTArray<SkMatrix> fPreViewMatrices;
+ SkTLazy<SkPaint> fPaint;
+ SkCanvas::SrcRectConstraint fConstraint;
+
+ typedef DrawCommand INHERITED;
+};
+#endif
diff --git a/src/third_party/skia/tools/debugger/JsonWriteBuffer.cpp b/src/third_party/skia/tools/debugger/JsonWriteBuffer.cpp
new file mode 100644
index 0000000..7257167
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/JsonWriteBuffer.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/debugger/JsonWriteBuffer.h"
+
+#include "tools/debugger/DrawCommand.h"
+
+void JsonWriteBuffer::append(const char* type) {
+ SkString fullName = SkStringPrintf("%02d_%s", fCount++, type);
+ fWriter->appendName(fullName.c_str());
+}
+
+void JsonWriteBuffer::writePad32(const void* data, size_t size) {
+ this->append("rawBytes");
+ fWriter->beginArray();
+ const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
+ for (size_t i = 0; i < size; ++i) {
+ SkString hexByte = SkStringPrintf("%02x", bytes[i]);
+ fWriter->appendString(hexByte.c_str());
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeByteArray(const void* data, size_t size) {
+ this->append("byteArray");
+ fWriter->beginArray();
+ const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
+ for (size_t i = 0; i < size; ++i) {
+ SkString hexByte = SkStringPrintf("%02x", bytes[i]);
+ fWriter->appendString(hexByte.c_str());
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeBool(bool value) {
+ this->append("bool");
+ fWriter->appendBool(value);
+}
+
+void JsonWriteBuffer::writeScalar(SkScalar value) {
+ this->append("scalar");
+ fWriter->appendFloat(value);
+}
+
+void JsonWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
+ this->append("scalarArray");
+ fWriter->beginArray();
+ for (uint32_t i = 0; i < count; ++i) {
+ fWriter->appendFloat(value[i]);
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeInt(int32_t value) {
+ this->append("int");
+ fWriter->appendS32(value);
+}
+
+void JsonWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
+ this->append("intArray");
+ fWriter->beginArray();
+ for (uint32_t i = 0; i < count; ++i) {
+ fWriter->appendS32(value[i]);
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeUInt(uint32_t value) {
+ this->append("uint");
+ fWriter->appendU32(value);
+}
+
+void JsonWriteBuffer::writeString(const char* value) {
+ this->append("string");
+ fWriter->appendString(value);
+}
+
+void JsonWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
+ if (flattenable) {
+ this->append(flattenable->getTypeName());
+ fWriter->beginObject();
+ JsonWriteBuffer flattenableBuffer(fWriter, fUrlDataManager);
+ flattenable->flatten(flattenableBuffer);
+ fWriter->endObject();
+ } else {
+ this->append("flattenable");
+ fWriter->appendPointer(nullptr);
+ }
+}
+
+void JsonWriteBuffer::writeColor(SkColor color) {
+ this->append("color");
+ DrawCommand::MakeJsonColor(*fWriter, color);
+}
+
+void JsonWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
+ this->append("colorArray");
+ fWriter->beginArray();
+ for (uint32_t i = 0; i < count; ++i) {
+ DrawCommand::MakeJsonColor(*fWriter, color[i]);
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeColor4f(const SkColor4f& color) {
+ this->append("color");
+ DrawCommand::MakeJsonColor4f(*fWriter, color);
+}
+
+void JsonWriteBuffer::writeColor4fArray(const SkColor4f* color, uint32_t count) {
+ this->append("colorArray");
+ fWriter->beginArray();
+ for (uint32_t i = 0; i < count; ++i) {
+ DrawCommand::MakeJsonColor4f(*fWriter, color[i]);
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writePoint(const SkPoint& point) {
+ this->append("point");
+ DrawCommand::MakeJsonPoint(*fWriter, point);
+}
+
+void JsonWriteBuffer::writePoint3(const SkPoint3& point) {
+ this->append("point3");
+ DrawCommand::MakeJsonPoint3(*fWriter, point);
+}
+
+void JsonWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
+ this->append("pointArray");
+ fWriter->beginArray();
+ for (uint32_t i = 0; i < count; ++i) {
+ DrawCommand::MakeJsonPoint(*fWriter, point[i]);
+ }
+ fWriter->endArray();
+}
+
+void JsonWriteBuffer::writeMatrix(const SkMatrix& matrix) {
+ this->append("matrix");
+ DrawCommand::MakeJsonMatrix(*fWriter, matrix);
+}
+
+void JsonWriteBuffer::writeIRect(const SkIRect& rect) {
+ this->append("irect");
+ DrawCommand::MakeJsonIRect(*fWriter, rect);
+}
+
+void JsonWriteBuffer::writeRect(const SkRect& rect) {
+ this->append("rect");
+ DrawCommand::MakeJsonRect(*fWriter, rect);
+}
+
+void JsonWriteBuffer::writeRegion(const SkRegion& region) {
+ this->append("region");
+ DrawCommand::MakeJsonRegion(*fWriter, region);
+}
+
+void JsonWriteBuffer::writePath(const SkPath& path) {
+ this->append("path");
+ DrawCommand::MakeJsonPath(*fWriter, path);
+}
+
+size_t JsonWriteBuffer::writeStream(SkStream* stream, size_t length) {
+ // Contents not supported
+ this->append("stream");
+ fWriter->appendU64(static_cast<uint64_t>(length));
+ return 0;
+}
+
+void JsonWriteBuffer::writeImage(const SkImage* image) {
+ this->append("image");
+ fWriter->beginObject();
+ DrawCommand::flatten(*image, *fWriter, *fUrlDataManager);
+ fWriter->endObject();
+}
+
+void JsonWriteBuffer::writeTypeface(SkTypeface* typeface) {
+ // Unsupported
+ this->append("typeface");
+ fWriter->appendPointer(typeface);
+}
+
+void JsonWriteBuffer::writePaint(const SkPaint& paint) {
+ this->append("paint");
+ DrawCommand::MakeJsonPaint(*fWriter, paint, *fUrlDataManager);
+}
diff --git a/src/third_party/skia/tools/debugger/JsonWriteBuffer.h b/src/third_party/skia/tools/debugger/JsonWriteBuffer.h
new file mode 100644
index 0000000..78ed4d2
--- /dev/null
+++ b/src/third_party/skia/tools/debugger/JsonWriteBuffer.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef JsonWriteBuffer_DEFINED
+#define JsonWriteBuffer_DEFINED
+
+#include "src/core/SkWriteBuffer.h"
+
+class SkJSONWriter;
+class SkPath;
+class UrlDataManager;
+
+class JsonWriteBuffer final : public SkWriteBuffer {
+public:
+ JsonWriteBuffer(SkJSONWriter* writer, UrlDataManager* urlDataManager)
+ : fUrlDataManager(urlDataManager), fWriter(writer), fCount(0) {}
+
+ void writePad32(const void* buffer, size_t bytes) override;
+ void writeByteArray(const void* data, size_t size) override;
+ void writeBool(bool value) override;
+ void writeScalar(SkScalar value) override;
+ void writeScalarArray(const SkScalar* value, uint32_t count) override;
+ void writeInt(int32_t value) override;
+ void writeIntArray(const int32_t* value, uint32_t count) override;
+ void writeUInt(uint32_t value) override;
+ void writeString(const char* value) override;
+
+ void writeFlattenable(const SkFlattenable* flattenable) override;
+ void writeColor(SkColor color) override;
+ void writeColorArray(const SkColor* color, uint32_t count) override;
+ void writeColor4f(const SkColor4f& color) override;
+ void writeColor4fArray(const SkColor4f* color, uint32_t count) override;
+ void writePoint(const SkPoint& point) override;
+ void writePointArray(const SkPoint* point, uint32_t count) override;
+ void writePoint3(const SkPoint3& point) override;
+ void writeMatrix(const SkMatrix& matrix) override;
+ void writeIRect(const SkIRect& rect) override;
+ void writeRect(const SkRect& rect) override;
+ void writeRegion(const SkRegion& region) override;
+ void writePath(const SkPath& path) override;
+ size_t writeStream(SkStream* stream, size_t length) override;
+ void writeImage(const SkImage*) override;
+ void writeTypeface(SkTypeface* typeface) override;
+ void writePaint(const SkPaint& paint) override;
+
+private:
+ void append(const char* type);
+
+ UrlDataManager* fUrlDataManager;
+ SkJSONWriter* fWriter;
+ int fCount;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/debugger/SkDebugCanvas.cpp b/src/third_party/skia/tools/debugger/SkDebugCanvas.cpp
deleted file mode 100644
index fdde0a6..0000000
--- a/src/third_party/skia/tools/debugger/SkDebugCanvas.cpp
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCanvasPriv.h"
-#include "SkClipStack.h"
-#include "SkDebugCanvas.h"
-#include "SkDrawCommand.h"
-#include "SkPaintFilterCanvas.h"
-#include "SkTextBlob.h"
-#include "SkClipOpPriv.h"
-
-#if SK_SUPPORT_GPU
-#include "GrAuditTrail.h"
-#include "GrContext.h"
-#include "GrRenderTargetContext.h"
-#endif
-
-#define SKDEBUGCANVAS_VERSION 1
-#define SKDEBUGCANVAS_ATTRIBUTE_VERSION "version"
-#define SKDEBUGCANVAS_ATTRIBUTE_COMMANDS "commands"
-#define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL "auditTrail"
-
-class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
-public:
- DebugPaintFilterCanvas(SkCanvas* canvas,
- bool overdrawViz,
- bool overrideFilterQuality,
- SkFilterQuality quality)
- : INHERITED(canvas)
- , fOverdrawViz(overdrawViz)
- , fOverrideFilterQuality(overrideFilterQuality)
- , fFilterQuality(quality) {}
-
-protected:
- bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
- if (*paint) {
- if (fOverdrawViz) {
- paint->writable()->setColor(SK_ColorRED);
- paint->writable()->setAlpha(0x08);
- paint->writable()->setBlendMode(SkBlendMode::kSrcOver);
- }
-
- if (fOverrideFilterQuality) {
- paint->writable()->setFilterQuality(fFilterQuality);
- }
- }
- return true;
- }
-
- void onDrawPicture(const SkPicture* picture,
- const SkMatrix* matrix,
- const SkPaint* paint) override {
- // We need to replay the picture onto this canvas in order to filter its internal paints.
- this->SkCanvas::onDrawPicture(picture, matrix, paint);
- }
-
-private:
- bool fOverdrawViz;
- bool fOverrideFilterQuality;
- SkFilterQuality fFilterQuality;
-
- typedef SkPaintFilterCanvas INHERITED;
-};
-
-SkDebugCanvas::SkDebugCanvas(int width, int height)
- : INHERITED(width, height)
- , fPicture(nullptr)
- , fFilter(false)
- , fMegaVizMode(false)
- , fOverdrawViz(false)
- , fOverrideFilterQuality(false)
- , fFilterQuality(kNone_SkFilterQuality)
- , fClipVizColor(SK_ColorTRANSPARENT)
- , fDrawGpuOpBounds(false) {
- fUserMatrix.reset();
-
- // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
- // operations. This can lead to problems in the debugger which expects all
- // the operations in the captured skp to appear in the debug canvas. To
- // circumvent this we create a wide open clip here (an empty clip rect
- // is not sufficient).
- // Internally, the SkRect passed to clipRect is converted to an SkIRect and
- // rounded out. The following code creates a nearly maximal rect that will
- // not get collapsed by the coming conversions (Due to precision loss the
- // inset has to be surprisingly large).
- SkIRect largeIRect = SkIRect::MakeLargest();
- largeIRect.inset(1024, 1024);
- SkRect large = SkRect::Make(largeIRect);
-#ifdef SK_DEBUG
- SkASSERT(!large.roundOut().isEmpty());
-#endif
- // call the base class' version to avoid adding a draw command
- this->INHERITED::onClipRect(large, kReplace_SkClipOp, kHard_ClipEdgeStyle);
-}
-
-SkDebugCanvas::~SkDebugCanvas() {
- fCommandVector.deleteAll();
-}
-
-void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
- fCommandVector.push(command);
-}
-
-void SkDebugCanvas::draw(SkCanvas* canvas) {
- if (!fCommandVector.isEmpty()) {
- this->drawTo(canvas, fCommandVector.count() - 1);
- }
-}
-
-void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
- canvas->concat(fUserMatrix);
-}
-
-int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
- SkBitmap bitmap;
- bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
-
- SkCanvas canvas(bitmap);
- canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
- this->applyUserTransform(&canvas);
-
- int layer = 0;
- SkColor prev = bitmap.getColor(0,0);
- for (int i = 0; i < index; i++) {
- if (fCommandVector[i]->isVisible()) {
- fCommandVector[i]->setUserMatrix(fUserMatrix);
- fCommandVector[i]->execute(&canvas);
- }
- if (prev != bitmap.getColor(0,0)) {
- layer = i;
- }
- prev = bitmap.getColor(0,0);
- }
- return layer;
-}
-
-// set up the saveLayer commands so that the active ones
-// return true in their 'active' method
-void SkDebugCanvas::markActiveCommands(int index) {
- fActiveLayers.rewind();
-
- for (int i = 0; i < fCommandVector.count(); ++i) {
- fCommandVector[i]->setActive(false);
- }
-
- for (int i = 0; i < index; ++i) {
- SkDrawCommand::Action result = fCommandVector[i]->action();
- if (SkDrawCommand::kPushLayer_Action == result) {
- fActiveLayers.push(fCommandVector[i]);
- } else if (SkDrawCommand::kPopLayer_Action == result) {
- fActiveLayers.pop();
- }
- }
-
- for (int i = 0; i < fActiveLayers.count(); ++i) {
- fActiveLayers[i]->setActive(true);
- }
-
-}
-
-void SkDebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
- SkASSERT(!fCommandVector.isEmpty());
- SkASSERT(index < fCommandVector.count());
-
- int saveCount = originalCanvas->save();
-
- SkRect windowRect = SkRect::MakeWH(SkIntToScalar(originalCanvas->getBaseLayerSize().width()),
- SkIntToScalar(originalCanvas->getBaseLayerSize().height()));
-
- bool pathOpsMode = getAllowSimplifyClip();
- originalCanvas->setAllowSimplifyClip(pathOpsMode);
- originalCanvas->clear(SK_ColorWHITE);
- originalCanvas->resetMatrix();
- if (!windowRect.isEmpty()) {
- originalCanvas->clipRect(windowRect, kReplace_SkClipOp);
- }
- this->applyUserTransform(originalCanvas);
-
- DebugPaintFilterCanvas filterCanvas(originalCanvas, fOverdrawViz, fOverrideFilterQuality,
- fFilterQuality);
-
- if (fMegaVizMode) {
- this->markActiveCommands(index);
- }
-
-#if SK_SUPPORT_GPU
- // If we have a GPU backend we can also visualize the op information
- GrAuditTrail* at = nullptr;
- if (fDrawGpuOpBounds || m != -1) {
- // The audit trail must be obtained from the original canvas.
- at = this->getAuditTrail(originalCanvas);
- }
-#endif
-
- for (int i = 0; i <= index; i++) {
- if (i == index && fFilter) {
- filterCanvas.clear(0xAAFFFFFF);
- }
-
-#if SK_SUPPORT_GPU
- // We need to flush any pending operations, or they might combine with commands below.
- // Previous operations were not registered with the audit trail when they were
- // created, so if we allow them to combine, the audit trail will fail to find them.
- filterCanvas.flush();
-
- GrAuditTrail::AutoCollectOps* acb = nullptr;
- if (at) {
- acb = new GrAuditTrail::AutoCollectOps(at, i);
- }
-#endif
-
- if (fCommandVector[i]->isVisible()) {
- if (fMegaVizMode && fCommandVector[i]->active()) {
- // "active" commands execute their visualization behaviors:
- // All active saveLayers get replaced with saves so all draws go to the
- // visible canvas.
- // All active culls draw their cull box
- fCommandVector[i]->vizExecute(&filterCanvas);
- } else {
- fCommandVector[i]->setUserMatrix(fUserMatrix);
- fCommandVector[i]->execute(&filterCanvas);
- }
- }
-#if SK_SUPPORT_GPU
- if (at && acb) {
- delete acb;
- }
-#endif
- }
-
- if (SkColorGetA(fClipVizColor) != 0) {
- filterCanvas.save();
- #define LARGE_COORD 1000000000
- filterCanvas.clipRect(
- SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD),
- kReverseDifference_SkClipOp);
- SkPaint clipPaint;
- clipPaint.setColor(fClipVizColor);
- filterCanvas.drawPaint(clipPaint);
- filterCanvas.restore();
- }
-
- if (pathOpsMode) {
- this->resetClipStackData();
- const SkClipStack* clipStack = nullptr;//HACK filterCanvas.getClipStack();
- SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Element* element;
- SkPath devPath;
- while ((element = iter.next())) {
- SkClipStack::Element::Type type = element->getType();
- SkPath operand;
- if (type != SkClipStack::Element::kEmpty_Type) {
- element->asPath(&operand);
- }
- SkClipOp elementOp = element->getOp();
- this->addClipStackData(devPath, operand, elementOp);
- if (elementOp == kReplace_SkClipOp) {
- devPath = operand;
- } else {
- Op(devPath, operand, (SkPathOp) elementOp, &devPath);
- }
- }
- this->lastClipStackData(devPath);
- }
- fMatrix = filterCanvas.getTotalMatrix();
- fClip = filterCanvas.getDeviceClipBounds();
- filterCanvas.restoreToCount(saveCount);
-
-#if SK_SUPPORT_GPU
- // draw any ops if required and issue a full reset onto GrAuditTrail
- if (at) {
- // just in case there is global reordering, we flush the canvas before querying
- // GrAuditTrail
- GrAuditTrail::AutoEnable ae(at);
- filterCanvas.flush();
-
- // we pick three colorblind-safe colors, 75% alpha
- static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
- static const SkColor kCommandOpBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
- static const SkColor kOtherOpBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
-
- // get the render target of the top device (from the original canvas) so we can ignore ops
- // drawn offscreen
- GrRenderTargetContext* rtc =
- originalCanvas->internal_private_accessTopLayerRenderTargetContext();
- GrSurfaceProxy::UniqueID proxyID = rtc->asSurfaceProxy()->uniqueID();
-
- // get the bounding boxes to draw
- SkTArray<GrAuditTrail::OpInfo> childrenBounds;
- if (m == -1) {
- at->getBoundsByClientID(&childrenBounds, index);
- } else {
- // the client wants us to draw the mth op
- at->getBoundsByOpListID(&childrenBounds.push_back(), m);
- }
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(1);
- for (int i = 0; i < childrenBounds.count(); i++) {
- if (childrenBounds[i].fProxyUniqueID != proxyID) {
- // offscreen draw, ignore for now
- continue;
- }
- paint.setColor(kTotalBounds);
- filterCanvas.drawRect(childrenBounds[i].fBounds, paint);
- for (int j = 0; j < childrenBounds[i].fOps.count(); j++) {
- const GrAuditTrail::OpInfo::Op& op = childrenBounds[i].fOps[j];
- if (op.fClientID != index) {
- paint.setColor(kOtherOpBounds);
- } else {
- paint.setColor(kCommandOpBounds);
- }
- filterCanvas.drawRect(op.fBounds, paint);
- }
- }
- }
-#endif
- this->cleanupAuditTrail(originalCanvas);
-}
-
-void SkDebugCanvas::deleteDrawCommandAt(int index) {
- SkASSERT(index < fCommandVector.count());
- delete fCommandVector[index];
- fCommandVector.remove(index);
-}
-
-SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
- SkASSERT(index < fCommandVector.count());
- return fCommandVector[index];
-}
-
-void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) {
- SkASSERT(index < fCommandVector.count());
- delete fCommandVector[index];
- fCommandVector[index] = command;
-}
-
-const SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) const {
- SkASSERT(index < fCommandVector.count());
- return fCommandVector[index]->Info();
-}
-
-bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
- SkASSERT(index < fCommandVector.count());
- return fCommandVector[index]->isVisible();
-}
-
-const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
- return fCommandVector;
-}
-
-SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() {
- return fCommandVector;
-}
-
-GrAuditTrail* SkDebugCanvas::getAuditTrail(SkCanvas* canvas) {
- GrAuditTrail* at = nullptr;
-#if SK_SUPPORT_GPU
- GrContext* ctx = canvas->getGrContext();
- if (ctx) {
- at = ctx->getAuditTrail();
- }
-#endif
- return at;
-}
-
-void SkDebugCanvas::drawAndCollectOps(int n, SkCanvas* canvas) {
-#if SK_SUPPORT_GPU
- GrAuditTrail* at = this->getAuditTrail(canvas);
- if (at) {
- // loop over all of the commands and draw them, this is to collect reordering
- // information
- for (int i = 0; i < this->getSize() && i <= n; i++) {
- GrAuditTrail::AutoCollectOps enable(at, i);
- fCommandVector[i]->execute(canvas);
- }
-
- // in case there is some kind of global reordering
- {
- GrAuditTrail::AutoEnable ae(at);
- canvas->flush();
- }
- }
-#endif
-}
-
-void SkDebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
- GrAuditTrail* at = this->getAuditTrail(canvas);
- if (at) {
-#if SK_SUPPORT_GPU
- GrAuditTrail::AutoEnable ae(at);
- at->fullReset();
-#endif
- }
-}
-
-Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanvas* canvas) {
- this->drawAndCollectOps(n, canvas);
-
- // now collect json
-#if SK_SUPPORT_GPU
- GrAuditTrail* at = this->getAuditTrail(canvas);
-#endif
- Json::Value result = Json::Value(Json::objectValue);
- result[SKDEBUGCANVAS_ATTRIBUTE_VERSION] = Json::Value(SKDEBUGCANVAS_VERSION);
- Json::Value commands = Json::Value(Json::arrayValue);
- for (int i = 0; i < this->getSize() && i <= n; i++) {
- commands[i] = this->getDrawCommandAt(i)->toJSON(urlDataManager);
-#if SK_SUPPORT_GPU
- if (at) {
- // TODO if this is inefficient we could add a method to GrAuditTrail which takes
- // a Json::Value and is only compiled in this file
- Json::Value parsedFromString;
- Json::Reader reader;
- SkAssertResult(reader.parse(at->toJson(i).c_str(), parsedFromString));
-
- commands[i][SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString;
- }
-#endif
- }
- this->cleanupAuditTrail(canvas);
- result[SKDEBUGCANVAS_ATTRIBUTE_COMMANDS] = commands;
- return result;
-}
-
-Json::Value SkDebugCanvas::toJSONOpList(int n, SkCanvas* canvas) {
- this->drawAndCollectOps(n, canvas);
-
- Json::Value parsedFromString;
-#if SK_SUPPORT_GPU
- GrAuditTrail* at = this->getAuditTrail(canvas);
- if (at) {
- GrAuditTrail::AutoManageOpList enable(at);
- Json::Reader reader;
- SkAssertResult(reader.parse(at->toJson().c_str(), parsedFromString));
- }
-#endif
- this->cleanupAuditTrail(canvas);
- return parsedFromString;
-}
-
-void SkDebugCanvas::setOverdrawViz(bool overdrawViz) {
- fOverdrawViz = overdrawViz;
-}
-
-void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkFilterQuality quality) {
- fOverrideFilterQuality = overrideTexFiltering;
- fFilterQuality = quality;
-}
-
-void SkDebugCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
- this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
-}
-
-void SkDebugCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
- this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
-}
-
-void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
- this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
-}
-
-void SkDebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
- this->addDrawCommand(new SkClipRegionCommand(region, op));
-}
-
-void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
- this->addDrawCommand(new SkConcatCommand(matrix));
- this->INHERITED::didConcat(matrix);
-}
-
-void SkDebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
- this->addDrawCommand(new SkDrawAnnotationCommand(rect, key, sk_ref_sp(value)));
-}
-
-void SkDebugCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
- SkScalar top, const SkPaint* paint) {
- this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
-}
-
-void SkDebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
- const SkPaint* paint, SrcRectConstraint constraint) {
- this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint,
- (SrcRectConstraint)constraint));
-}
-
-void SkDebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint) {
- this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
-}
-
-void SkDebugCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
- const SkPaint* paint) {
- this->addDrawCommand(new SkDrawImageCommand(image, left, top, paint));
-}
-
-void SkDebugCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
- const SkRect& dst, const SkPaint* paint) {
- this->addDrawCommand(new SkDrawImageLatticeCommand(image, lattice, dst, paint));
-}
-
-void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
- const SkPaint* paint, SrcRectConstraint constraint) {
- this->addDrawCommand(new SkDrawImageRectCommand(image, src, dst, paint, constraint));
-}
-
-void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
- this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
-}
-
-void SkDebugCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
- bool useCenter, const SkPaint& paint) {
- this->addDrawCommand(new SkDrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
-}
-
-void SkDebugCanvas::onDrawPaint(const SkPaint& paint) {
- this->addDrawCommand(new SkDrawPaintCommand(paint));
-}
-
-void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
- this->addDrawCommand(new SkDrawPathCommand(path, paint));
-}
-
-void SkDebugCanvas::onDrawPicture(const SkPicture* picture,
- const SkMatrix* matrix,
- const SkPaint* paint) {
- this->addDrawCommand(new SkBeginDrawPictureCommand(picture, matrix, paint));
- SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
- picture->playback(this);
- this->addDrawCommand(new SkEndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
-}
-
-void SkDebugCanvas::onDrawPoints(PointMode mode, size_t count,
- const SkPoint pts[], const SkPaint& paint) {
- this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
-}
-
-void SkDebugCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
-}
-
-void SkDebugCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint& paint) {
- this->addDrawCommand(
- new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
-}
-
-void SkDebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
- // NOTE(chudy): Messing up when renamed to DrawRect... Why?
- addDrawCommand(new SkDrawRectCommand(rect, paint));
-}
-
-void SkDebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
- this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
-}
-
-void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
-}
-
-void SkDebugCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
-}
-
-void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint& paint) {
- this->addDrawCommand(
- new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
-}
-
-void SkDebugCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
- const SkRect* cull, const SkPaint& paint) {
- this->addDrawCommand(new SkDrawTextRSXformCommand(text, byteLength, xform, cull, paint));
-}
-
-void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)),
- x, y, paint));
-}
-
-void SkDebugCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkBlendMode bmode,
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawPatchCommand(cubics, colors, texCoords, bmode, paint));
-}
-
-void SkDebugCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
- const SkPaint& paint) {
- this->addDrawCommand(new SkDrawVerticesCommand(sk_ref_sp(const_cast<SkVertices*>(vertices)),
- bmode, paint));
-}
-
-void SkDebugCanvas::willRestore() {
- this->addDrawCommand(new SkRestoreCommand());
- this->INHERITED::willRestore();
-}
-
-void SkDebugCanvas::willSave() {
- this->addDrawCommand(new SkSaveCommand());
- this->INHERITED::willSave();
-}
-
-SkCanvas::SaveLayerStrategy SkDebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
- this->addDrawCommand(new SkSaveLayerCommand(rec));
- (void)this->INHERITED::getSaveLayerStrategy(rec);
- // No need for a full layer.
- return kNoLayer_SaveLayerStrategy;
-}
-
-void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
- this->addDrawCommand(new SkSetMatrixCommand(matrix));
- this->INHERITED::didSetMatrix(matrix);
-}
-
-void SkDebugCanvas::toggleCommand(int index, bool toggle) {
- SkASSERT(index < fCommandVector.count());
- fCommandVector[index]->setVisible(toggle);
-}
-
-static const char* gFillTypeStrs[] = {
- "kWinding_FillType",
- "kEvenOdd_FillType",
- "kInverseWinding_FillType",
- "kInverseEvenOdd_FillType"
-};
-
-static const char* gOpStrs[] = {
- "kDifference_PathOp",
- "kIntersect_PathOp",
- "kUnion_PathOp",
- "kXor_PathOp",
- "kReverseDifference_PathOp",
-};
-
-static const char kHTML4SpaceIndent[] = " ";
-
-void SkDebugCanvas::outputScalar(SkScalar num) {
- if (num == (int) num) {
- fClipStackData.appendf("%d", (int) num);
- } else {
- SkString str;
- str.printf("%1.9g", num);
- int width = (int) str.size();
- const char* cStr = str.c_str();
- while (cStr[width - 1] == '0') {
- --width;
- }
- str.resize(width);
- fClipStackData.appendf("%sf", str.c_str());
- }
-}
-
-void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
- for (int index = 0; index < count; ++index) {
- this->outputScalar(pts[index].fX);
- fClipStackData.appendf(", ");
- this->outputScalar(pts[index].fY);
- if (index + 1 < count) {
- fClipStackData.appendf(", ");
- }
- }
-}
-
-void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
- this->outputPointsCommon(pts, count);
- fClipStackData.appendf(");<br>");
-}
-
-void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
- this->outputPointsCommon(pts, 2);
- fClipStackData.appendf(", ");
- this->outputScalar(weight);
- fClipStackData.appendf(");<br>");
-}
-
-void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
- SkPath::RawIter iter(path);
- SkPath::FillType fillType = path.getFillType();
- fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
- fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
- gFillTypeStrs[fillType]);
- iter.setPath(path);
- uint8_t verb;
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
- this->outputPoints(&pts[0], 1);
- continue;
- case SkPath::kLine_Verb:
- fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
- this->outputPoints(&pts[1], 1);
- break;
- case SkPath::kQuad_Verb:
- fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
- this->outputPoints(&pts[1], 2);
- break;
- case SkPath::kConic_Verb:
- fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
- this->outputConicPoints(&pts[1], iter.conicWeight());
- break;
- case SkPath::kCubic_Verb:
- fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
- this->outputPoints(&pts[1], 3);
- break;
- case SkPath::kClose_Verb:
- fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- }
-}
-
-void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
- SkClipOp elementOp) {
- if (elementOp == kReplace_SkClipOp) {
- if (!lastClipStackData(devPath)) {
- fSaveDevPath = operand;
- }
- fCalledAddStackData = false;
- } else {
- fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
- " const char* filename) {<br>");
- addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
- addPathData(operand, "pathB");
- fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
- kHTML4SpaceIndent, gOpStrs[static_cast<int>(elementOp)]);
- fClipStackData.appendf("}<br>");
- fCalledAddStackData = true;
- }
-}
-
-bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
- if (fCalledAddStackData) {
- fClipStackData.appendf("<br>");
- addPathData(devPath, "pathOut");
- return true;
- }
- return false;
-}
diff --git a/src/third_party/skia/tools/debugger/SkDebugCanvas.h b/src/third_party/skia/tools/debugger/SkDebugCanvas.h
deleted file mode 100644
index 9b944f7..0000000
--- a/src/third_party/skia/tools/debugger/SkDebugCanvas.h
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SKDEBUGCANVAS_H_
-#define SKDEBUGCANVAS_H_
-
-#include "SkCanvas.h"
-#include "SkDrawCommand.h"
-#include "SkPath.h"
-#include "SkPathOps.h"
-#include "SkPicture.h"
-#include "SkString.h"
-#include "SkTArray.h"
-#include "SkVertices.h"
-#include "UrlDataManager.h"
-
-class GrAuditTrail;
-class SkNWayCanvas;
-
-class SkDebugCanvas : public SkCanvas {
-public:
- SkDebugCanvas(int width, int height);
-
- ~SkDebugCanvas() override;
-
- void toggleFilter(bool toggle) { fFilter = toggle; }
-
- void setMegaVizMode(bool megaVizMode) { fMegaVizMode = megaVizMode; }
-
- bool getMegaVizMode() const { return fMegaVizMode; }
-
- /**
- * Enable or disable overdraw visualization
- */
- void setOverdrawViz(bool overdrawViz);
-
- bool getOverdrawViz() const { return fOverdrawViz; }
-
- /**
- * Set the color of the clip visualization. An alpha of zero renders the clip invisible.
- */
- void setClipVizColor(SkColor clipVizColor) { this->fClipVizColor = clipVizColor; }
-
- SkColor getClipVizColor() const { return fClipVizColor; }
-
- void setDrawGpuOpBounds(bool drawGpuOpBounds) { fDrawGpuOpBounds = drawGpuOpBounds; }
-
- bool getDrawGpuOpBounds() const { return fDrawGpuOpBounds; }
-
- bool getAllowSimplifyClip() const { return fAllowSimplifyClip; }
-
- void setPicture(SkPicture *picture) { fPicture = picture; }
-
- /**
- * Enable or disable texure filtering override
- */
- void overrideTexFiltering(bool overrideTexFiltering, SkFilterQuality);
-
- /**
- Executes all draw calls to the canvas.
- @param canvas The canvas being drawn to
- */
- void draw(SkCanvas *canvas);
-
- /**
- Executes the draw calls up to the specified index.
- @param canvas The canvas being drawn to
- @param index The index of the final command being executed
- @param m an optional Mth gpu op to highlight, or -1
- */
- void drawTo(SkCanvas *canvas, int index, int m = -1);
-
- /**
- Returns the most recently calculated transformation matrix
- */
- const SkMatrix &getCurrentMatrix() {
- return fMatrix;
- }
-
- /**
- Returns the most recently calculated clip
- */
- const SkIRect &getCurrentClip() {
- return fClip;
- }
-
- /**
- Returns the index of the last draw command to write to the pixel at (x,y)
- */
- int getCommandAtPoint(int x, int y, int index);
-
- /**
- Removes the command at the specified index
- @param index The index of the command to delete
- */
- void deleteDrawCommandAt(int index);
-
- /**
- Returns the draw command at the given index.
- @param index The index of the command
- */
- SkDrawCommand *getDrawCommandAt(int index);
-
- /**
- Sets the draw command for a given index.
- @param index The index to overwrite
- @param command The new command
- */
- void setDrawCommandAt(int index, SkDrawCommand *command);
-
- /**
- Returns information about the command at the given index.
- @param index The index of the command
- */
- const SkTDArray<SkString *> *getCommandInfo(int index) const;
-
- /**
- Returns the visibility of the command at the given index.
- @param index The index of the command
- */
- bool getDrawCommandVisibilityAt(int index);
-
- /**
- Returns the vector of draw commands
- */
- SK_ATTR_DEPRECATED("please use getDrawCommandAt and getSize instead")
- const SkTDArray<SkDrawCommand *> &getDrawCommands() const;
-
- /**
- Returns the vector of draw commands. Do not use this entry
- point - it is going away!
- */
- SkTDArray<SkDrawCommand *> &getDrawCommands();
-
- /**
- Returns length of draw command vector.
- */
- int getSize() const {
- return fCommandVector.count();
- }
-
- /**
- Toggles the visibility / execution of the draw command at index i with
- the value of toggle.
- */
- void toggleCommand(int index, bool toggle);
-
- void setUserMatrix(SkMatrix matrix) {
- fUserMatrix = matrix;
- }
-
- SkString clipStackData() const { return fClipStackData; }
-
- /**
- Returns a JSON object representing up to the Nth draw, where N is less than
- SkDebugCanvas::getSize(). The encoder may use the UrlDataManager to store binary data such
- as images, referring to them via URLs embedded in the JSON.
- */
- Json::Value toJSON(UrlDataManager &urlDataManager, int n, SkCanvas *);
-
- Json::Value toJSONOpList(int n, SkCanvas*);
-
- ////////////////////////////////////////////////////////////////////////////////
- // Inherited from SkCanvas
- ////////////////////////////////////////////////////////////////////////////////
-
- static const int kVizImageHeight = 256;
- static const int kVizImageWidth = 256;
-
- bool isClipEmpty() const override { return false; }
-
- bool isClipRect() const override { return true; }
-
- SkRect onGetLocalClipBounds() const override {
- return SkRect::MakeIWH(this->imageInfo().width(), this->imageInfo().height());
- }
-
- SkIRect onGetDeviceClipBounds() const override {
- return SkIRect::MakeWH(this->imageInfo().width(), this->imageInfo().height());
- }
-
-protected:
- void willSave() override;
-
- SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec &) override;
-
- void willRestore() override;
-
- void didConcat(const SkMatrix &) override;
-
- void didSetMatrix(const SkMatrix &) override;
-
- void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
- void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
- void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint&) override;
- void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint&) override;
- void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint&) override;
- void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint&) override;
- void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[], const SkRect*,
- const SkPaint&) override;
- void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) override;
-
- void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint) override;
- void onDrawPaint(const SkPaint&) override;
-
- void onDrawRect(const SkRect&, const SkPaint&) override;
- void onDrawOval(const SkRect&, const SkPaint&) override;
- void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
- void onDrawRRect(const SkRRect&, const SkPaint&) override;
- void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
- void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
- void onDrawPath(const SkPath&, const SkPaint&) override;
- void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
- void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
- SrcRectConstraint) override;
- void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
- void onDrawImageLattice(const SkImage* image, const Lattice& lattice,
- const SkRect& dst, const SkPaint* paint) override;
- void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
- const SkPaint*, SrcRectConstraint) override;
- void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
- const SkPaint*) override;
- void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
- void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
- void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
- void onClipRegion(const SkRegion& region, SkClipOp) override;
-
- void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
-
- void markActiveCommands(int index);
-
-private:
- SkTDArray<SkDrawCommand*> fCommandVector;
- SkPicture* fPicture;
- bool fFilter;
- bool fMegaVizMode;
- SkMatrix fUserMatrix;
- SkMatrix fMatrix;
- SkIRect fClip;
-
- SkString fClipStackData;
- bool fCalledAddStackData;
- SkPath fSaveDevPath;
-
- bool fOverdrawViz;
- bool fOverrideFilterQuality;
- SkFilterQuality fFilterQuality;
- SkColor fClipVizColor;
- bool fDrawGpuOpBounds;
-
- /**
- The active saveLayer commands at a given point in the renderering.
- Only used when "mega" visualization is enabled.
- */
- SkTDArray<SkDrawCommand*> fActiveLayers;
-
- /**
- Adds the command to the classes vector of commands.
- @param command The draw command for execution
- */
- void addDrawCommand(SkDrawCommand* command);
-
- /**
- Applies any panning and zooming the user has specified before
- drawing anything else into the canvas.
- */
- void applyUserTransform(SkCanvas* canvas);
-
- void resetClipStackData() { fClipStackData.reset(); fCalledAddStackData = false; }
-
- void addClipStackData(const SkPath& devPath, const SkPath& operand, SkClipOp elementOp);
- void addPathData(const SkPath& path, const char* pathName);
- bool lastClipStackData(const SkPath& devPath);
- void outputConicPoints(const SkPoint* pts, SkScalar weight);
- void outputPoints(const SkPoint* pts, int count);
- void outputPointsCommon(const SkPoint* pts, int count);
- void outputScalar(SkScalar num);
-
- GrAuditTrail* getAuditTrail(SkCanvas*);
-
- void drawAndCollectOps(int n, SkCanvas*);
- void cleanupAuditTrail(SkCanvas*);
-
- typedef SkCanvas INHERITED;
-};
-
-#endif
diff --git a/src/third_party/skia/tools/debugger/SkDrawCommand.cpp b/src/third_party/skia/tools/debugger/SkDrawCommand.cpp
deleted file mode 100644
index 5ae0307..0000000
--- a/src/third_party/skia/tools/debugger/SkDrawCommand.cpp
+++ /dev/null
@@ -1,3591 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkDrawCommand.h"
-
-#include "png.h"
-
-#include "SkAutoMalloc.h"
-#include "SkBlurMaskFilter.h"
-#include "SkColorFilter.h"
-#include "SkDashPathEffect.h"
-#include "SkImageFilter.h"
-#include "SkJsonWriteBuffer.h"
-#include "SkMaskFilter.h"
-#include "SkObjectParser.h"
-#include "SkPaintDefaults.h"
-#include "SkPathEffect.h"
-#include "SkPicture.h"
-#include "SkTextBlob.h"
-#include "SkTextBlobRunIterator.h"
-#include "SkTHash.h"
-#include "SkTypeface.h"
-#include "SkValidatingReadBuffer.h"
-#include "SkWriteBuffer.h"
-#include "picture_utils.h"
-#include "SkClipOpPriv.h"
-#include <SkLatticeIter.h>
-
-#define SKDEBUGCANVAS_ATTRIBUTE_COMMAND "command"
-#define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE "visible"
-#define SKDEBUGCANVAS_ATTRIBUTE_MATRIX "matrix"
-#define SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation"
-#define SKDEBUGCANVAS_ATTRIBUTE_COORDS "coords"
-#define SKDEBUGCANVAS_ATTRIBUTE_HINTING "hinting"
-#define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds"
-#define SKDEBUGCANVAS_ATTRIBUTE_PAINT "paint"
-#define SKDEBUGCANVAS_ATTRIBUTE_OUTER "outer"
-#define SKDEBUGCANVAS_ATTRIBUTE_INNER "inner"
-#define SKDEBUGCANVAS_ATTRIBUTE_MODE "mode"
-#define SKDEBUGCANVAS_ATTRIBUTE_POINTS "points"
-#define SKDEBUGCANVAS_ATTRIBUTE_PATH "path"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXT "text"
-#define SKDEBUGCANVAS_ATTRIBUTE_COLOR "color"
-#define SKDEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
-#define SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE "blendMode"
-#define SKDEBUGCANVAS_ATTRIBUTE_STYLE "style"
-#define SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH "strokeWidth"
-#define SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER "strokeMiter"
-#define SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN "strokeJoin"
-#define SKDEBUGCANVAS_ATTRIBUTE_CAP "cap"
-#define SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS "antiAlias"
-#define SKDEBUGCANVAS_ATTRIBUTE_DITHER "dither"
-#define SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT "fakeBoldText"
-#define SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT "linearText"
-#define SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT "subpixelText"
-#define SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT "devKernText"
-#define SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT "lcdRenderText"
-#define SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText"
-#define SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING "forceAutoHinting"
-#define SKDEBUGCANVAS_ATTRIBUTE_VERTICALTEXT "verticalText"
-#define SKDEBUGCANVAS_ATTRIBUTE_REGION "region"
-#define SKDEBUGCANVAS_ATTRIBUTE_REGIONOP "op"
-#define SKDEBUGCANVAS_ATTRIBUTE_EDGESTYLE "edgeStyle"
-#define SKDEBUGCANVAS_ATTRIBUTE_DEVICEREGION "deviceRegion"
-#define SKDEBUGCANVAS_ATTRIBUTE_BLUR "blur"
-#define SKDEBUGCANVAS_ATTRIBUTE_SIGMA "sigma"
-#define SKDEBUGCANVAS_ATTRIBUTE_QUALITY "quality"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN "textAlign"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE "textSize"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX "textScaleX"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX "textSkewX"
-#define SKDEBUGCANVAS_ATTRIBUTE_DASHING "dashing"
-#define SKDEBUGCANVAS_ATTRIBUTE_INTERVALS "intervals"
-#define SKDEBUGCANVAS_ATTRIBUTE_PHASE "phase"
-#define SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE "fillType"
-#define SKDEBUGCANVAS_ATTRIBUTE_VERBS "verbs"
-#define SKDEBUGCANVAS_ATTRIBUTE_NAME "name"
-#define SKDEBUGCANVAS_ATTRIBUTE_DATA "data"
-#define SKDEBUGCANVAS_ATTRIBUTE_VALUES "values"
-#define SKDEBUGCANVAS_ATTRIBUTE_SHADER "shader"
-#define SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT "pathEffect"
-#define SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER "maskFilter"
-#define SKDEBUGCANVAS_ATTRIBUTE_XFERMODE "xfermode"
-#define SKDEBUGCANVAS_ATTRIBUTE_LOOPER "looper"
-#define SKDEBUGCANVAS_ATTRIBUTE_BACKDROP "backdrop"
-#define SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER "colorfilter"
-#define SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter"
-#define SKDEBUGCANVAS_ATTRIBUTE_IMAGE "image"
-#define SKDEBUGCANVAS_ATTRIBUTE_BITMAP "bitmap"
-#define SKDEBUGCANVAS_ATTRIBUTE_SRC "src"
-#define SKDEBUGCANVAS_ATTRIBUTE_DST "dst"
-#define SKDEBUGCANVAS_ATTRIBUTE_CENTER "center"
-#define SKDEBUGCANVAS_ATTRIBUTE_STRICT "strict"
-#define SKDEBUGCANVAS_ATTRIBUTE_DESCRIPTION "description"
-#define SKDEBUGCANVAS_ATTRIBUTE_X "x"
-#define SKDEBUGCANVAS_ATTRIBUTE_Y "y"
-#define SKDEBUGCANVAS_ATTRIBUTE_RUNS "runs"
-#define SKDEBUGCANVAS_ATTRIBUTE_POSITIONS "positions"
-#define SKDEBUGCANVAS_ATTRIBUTE_GLYPHS "glyphs"
-#define SKDEBUGCANVAS_ATTRIBUTE_FONT "font"
-#define SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE "typeface"
-#define SKDEBUGCANVAS_ATTRIBUTE_CUBICS "cubics"
-#define SKDEBUGCANVAS_ATTRIBUTE_COLORS "colors"
-#define SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS "textureCoords"
-#define SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY "filterQuality"
-#define SKDEBUGCANVAS_ATTRIBUTE_STARTANGLE "startAngle"
-#define SKDEBUGCANVAS_ATTRIBUTE_SWEEPANGLE "sweepAngle"
-#define SKDEBUGCANVAS_ATTRIBUTE_USECENTER "useCenter"
-#define SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC "shortDesc"
-#define SKDEBUGCANVAS_ATTRIBUTE_UNIQUE_ID "uniqueID"
-#define SKDEBUGCANVAS_ATTRIBUTE_WIDTH "width"
-#define SKDEBUGCANVAS_ATTRIBUTE_HEIGHT "height"
-#define SKDEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICE "lattice"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT "xCount"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT "yCount"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS "xDivs"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS "yDivs"
-#define SKDEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS "flags"
-
-#define SKDEBUGCANVAS_VERB_MOVE "move"
-#define SKDEBUGCANVAS_VERB_LINE "line"
-#define SKDEBUGCANVAS_VERB_QUAD "quad"
-#define SKDEBUGCANVAS_VERB_CUBIC "cubic"
-#define SKDEBUGCANVAS_VERB_CONIC "conic"
-#define SKDEBUGCANVAS_VERB_CLOSE "close"
-
-#define SKDEBUGCANVAS_STYLE_FILL "fill"
-#define SKDEBUGCANVAS_STYLE_STROKE "stroke"
-#define SKDEBUGCANVAS_STYLE_STROKEANDFILL "strokeAndFill"
-
-#define SKDEBUGCANVAS_POINTMODE_POINTS "points"
-#define SKDEBUGCANVAS_POINTMODE_LINES "lines"
-#define SKDEBUGCANVAS_POINTMODE_POLYGON "polygon"
-
-#define SKDEBUGCANVAS_REGIONOP_DIFFERENCE "difference"
-#define SKDEBUGCANVAS_REGIONOP_INTERSECT "intersect"
-#define SKDEBUGCANVAS_REGIONOP_UNION "union"
-#define SKDEBUGCANVAS_REGIONOP_XOR "xor"
-#define SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
-#define SKDEBUGCANVAS_REGIONOP_REPLACE "replace"
-
-#define SKDEBUGCANVAS_BLURSTYLE_NORMAL "normal"
-#define SKDEBUGCANVAS_BLURSTYLE_SOLID "solid"
-#define SKDEBUGCANVAS_BLURSTYLE_OUTER "outer"
-#define SKDEBUGCANVAS_BLURSTYLE_INNER "inner"
-
-#define SKDEBUGCANVAS_BLURQUALITY_LOW "low"
-#define SKDEBUGCANVAS_BLURQUALITY_HIGH "high"
-
-#define SKDEBUGCANVAS_ALIGN_LEFT "left"
-#define SKDEBUGCANVAS_ALIGN_CENTER "center"
-#define SKDEBUGCANVAS_ALIGN_RIGHT "right"
-
-#define SKDEBUGCANVAS_FILLTYPE_WINDING "winding"
-#define SKDEBUGCANVAS_FILLTYPE_EVENODD "evenOdd"
-#define SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING "inverseWinding"
-#define SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD "inverseEvenOdd"
-
-#define SKDEBUGCANVAS_CAP_BUTT "butt"
-#define SKDEBUGCANVAS_CAP_ROUND "round"
-#define SKDEBUGCANVAS_CAP_SQUARE "square"
-
-#define SKDEBUGCANVAS_MITER_JOIN "miter"
-#define SKDEBUGCANVAS_ROUND_JOIN "round"
-#define SKDEBUGCANVAS_BEVEL_JOIN "bevel"
-
-#define SKDEBUGCANVAS_COLORTYPE_ARGB4444 "ARGB4444"
-#define SKDEBUGCANVAS_COLORTYPE_RGBA8888 "RGBA8888"
-#define SKDEBUGCANVAS_COLORTYPE_BGRA8888 "BGRA8888"
-#define SKDEBUGCANVAS_COLORTYPE_565 "565"
-#define SKDEBUGCANVAS_COLORTYPE_GRAY8 "Gray8"
-#define SKDEBUGCANVAS_COLORTYPE_INDEX8 "Index8"
-#define SKDEBUGCANVAS_COLORTYPE_ALPHA8 "Alpha8"
-
-#define SKDEBUGCANVAS_ALPHATYPE_OPAQUE "opaque"
-#define SKDEBUGCANVAS_ALPHATYPE_PREMUL "premul"
-#define SKDEBUGCANVAS_ALPHATYPE_UNPREMUL "unpremul"
-#define SKDEBUGCANVAS_ALPHATYPE_UNKNOWN "unknown"
-
-#define SKDEBUGCANVAS_FILTERQUALITY_NONE "none"
-#define SKDEBUGCANVAS_FILTERQUALITY_LOW "low"
-#define SKDEBUGCANVAS_FILTERQUALITY_MEDIUM "medium"
-#define SKDEBUGCANVAS_FILTERQUALITY_HIGH "high"
-
-#define SKDEBUGCANVAS_HINTING_NONE "none"
-#define SKDEBUGCANVAS_HINTING_SLIGHT "slight"
-#define SKDEBUGCANVAS_HINTING_NORMAL "normal"
-#define SKDEBUGCANVAS_HINTING_FULL "full"
-
-typedef SkDrawCommand* (*FROM_JSON)(Json::Value&, UrlDataManager&);
-
-static SkString* str_append(SkString* str, const SkRect& r) {
- str->appendf(" [%g %g %g %g]", r.left(), r.top(), r.right(), r.bottom());
- return str;
-}
-
-// TODO(chudy): Refactor into non subclass model.
-
-SkDrawCommand::SkDrawCommand(OpType type)
- : fOpType(type)
- , fVisible(true) {
-}
-
-SkDrawCommand::~SkDrawCommand() {
- fInfo.deleteAll();
-}
-
-const char* SkDrawCommand::GetCommandString(OpType type) {
- switch (type) {
- case kBeginDrawPicture_OpType: return "BeginDrawPicture";
- case kClipPath_OpType: return "ClipPath";
- case kClipRegion_OpType: return "ClipRegion";
- case kClipRect_OpType: return "ClipRect";
- case kClipRRect_OpType: return "ClipRRect";
- case kConcat_OpType: return "Concat";
- case kDrawAnnotation_OpType: return "DrawAnnotation";
- case kDrawBitmap_OpType: return "DrawBitmap";
- case kDrawBitmapNine_OpType: return "DrawBitmapNine";
- case kDrawBitmapRect_OpType: return "DrawBitmapRect";
- case kDrawClear_OpType: return "DrawClear";
- case kDrawDRRect_OpType: return "DrawDRRect";
- case kDrawImage_OpType: return "DrawImage";
- case kDrawImageLattice_OpType: return "DrawImageLattice";
- case kDrawImageRect_OpType: return "DrawImageRect";
- case kDrawOval_OpType: return "DrawOval";
- case kDrawPaint_OpType: return "DrawPaint";
- case kDrawPatch_OpType: return "DrawPatch";
- case kDrawPath_OpType: return "DrawPath";
- case kDrawPoints_OpType: return "DrawPoints";
- case kDrawPosText_OpType: return "DrawPosText";
- case kDrawPosTextH_OpType: return "DrawPosTextH";
- case kDrawRect_OpType: return "DrawRect";
- case kDrawRRect_OpType: return "DrawRRect";
- case kDrawText_OpType: return "DrawText";
- case kDrawTextBlob_OpType: return "DrawTextBlob";
- case kDrawTextOnPath_OpType: return "DrawTextOnPath";
- case kDrawTextRSXform_OpType: return "DrawTextRSXform";
- case kDrawVertices_OpType: return "DrawVertices";
- case kEndDrawPicture_OpType: return "EndDrawPicture";
- case kRestore_OpType: return "Restore";
- case kSave_OpType: return "Save";
- case kSaveLayer_OpType: return "SaveLayer";
- case kSetMatrix_OpType: return "SetMatrix";
- default:
- SkDebugf("OpType error 0x%08x\n", type);
- SkASSERT(0);
- break;
- }
- SkDEBUGFAIL("DrawType UNUSED\n");
- return nullptr;
-}
-
-SkString SkDrawCommand::toString() const {
- return SkString(GetCommandString(fOpType));
-}
-
-Json::Value SkDrawCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result;
- result[SKDEBUGCANVAS_ATTRIBUTE_COMMAND] = this->GetCommandString(fOpType);
- result[SKDEBUGCANVAS_ATTRIBUTE_VISIBLE] = Json::Value(this->isVisible());
- return result;
-}
-
-#define INSTALL_FACTORY(name) factories.set(SkString(GetCommandString(k ## name ##_OpType)), \
- (FROM_JSON) Sk ## name ## Command::fromJSON)
-SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
- static SkTHashMap<SkString, FROM_JSON> factories;
- static bool initialized = false;
- if (!initialized) {
- initialized = true;
- INSTALL_FACTORY(Restore);
- INSTALL_FACTORY(ClipPath);
- INSTALL_FACTORY(ClipRegion);
- INSTALL_FACTORY(ClipRect);
- INSTALL_FACTORY(ClipRRect);
- INSTALL_FACTORY(Concat);
- INSTALL_FACTORY(DrawAnnotation);
- INSTALL_FACTORY(DrawBitmap);
- INSTALL_FACTORY(DrawBitmapRect);
- INSTALL_FACTORY(DrawBitmapNine);
- INSTALL_FACTORY(DrawImage);
- INSTALL_FACTORY(DrawImageRect);
- INSTALL_FACTORY(DrawOval);
- INSTALL_FACTORY(DrawPaint);
- INSTALL_FACTORY(DrawPath);
- INSTALL_FACTORY(DrawPoints);
- INSTALL_FACTORY(DrawText);
- INSTALL_FACTORY(DrawPosText);
- INSTALL_FACTORY(DrawPosTextH);
- INSTALL_FACTORY(DrawTextOnPath);
- INSTALL_FACTORY(DrawTextRSXform);
- INSTALL_FACTORY(DrawTextBlob);
-
- INSTALL_FACTORY(DrawRect);
- INSTALL_FACTORY(DrawRRect);
- INSTALL_FACTORY(DrawDRRect);
- INSTALL_FACTORY(DrawPatch);
- INSTALL_FACTORY(Save);
- INSTALL_FACTORY(SaveLayer);
- INSTALL_FACTORY(SetMatrix);
- }
- SkString name = SkString(command[SKDEBUGCANVAS_ATTRIBUTE_COMMAND].asCString());
- FROM_JSON* factory = factories.find(name);
- if (factory == nullptr) {
- SkDebugf("no JSON factory for '%s'\n", name.c_str());
- return nullptr;
- }
- return (*factory)(command, urlDataManager);
-}
-
-namespace {
-
-void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
- const SkISize& size = canvas->getBaseLayerSize();
-
- static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
-
- canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
- if (bounds.width() > bounds.height()) {
- canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
- SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
- } else {
- canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
- SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
- }
- canvas->translate(-bounds.centerX(), -bounds.centerY());
-}
-
-
-void render_path(SkCanvas* canvas, const SkPath& path) {
- canvas->clear(0xFFFFFFFF);
-
- const SkRect& bounds = path.getBounds();
- if (bounds.isEmpty()) {
- return;
- }
-
- SkAutoCanvasRestore acr(canvas, true);
- xlate_and_scale_to_bounds(canvas, bounds);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawPath(path, p);
-}
-
-void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
- const SkISize& size = canvas->getBaseLayerSize();
-
- SkScalar xScale = SkIntToScalar(size.fWidth-2) / input.width();
- SkScalar yScale = SkIntToScalar(size.fHeight-2) / input.height();
-
- if (input.width() > input.height()) {
- yScale *= input.height() / (float) input.width();
- } else {
- xScale *= input.width() / (float) input.height();
- }
-
- SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1,
- xScale * input.width(),
- yScale * input.height());
-
- static const int kNumBlocks = 8;
-
- canvas->clear(0xFFFFFFFF);
- SkISize block = {
- canvas->imageInfo().width()/kNumBlocks,
- canvas->imageInfo().height()/kNumBlocks
- };
- for (int y = 0; y < kNumBlocks; ++y) {
- for (int x = 0; x < kNumBlocks; ++x) {
- SkPaint paint;
- paint.setColor((x+y)%2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
- SkRect r = SkRect::MakeXYWH(SkIntToScalar(x*block.width()),
- SkIntToScalar(y*block.height()),
- SkIntToScalar(block.width()),
- SkIntToScalar(block.height()));
- canvas->drawRect(r, paint);
- }
- }
-
- canvas->drawBitmapRect(input, dst, nullptr);
-
- if (srcRect) {
- SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
- srcRect->fTop * yScale + SK_Scalar1,
- srcRect->fRight * xScale + SK_Scalar1,
- srcRect->fBottom * yScale + SK_Scalar1);
- SkPaint p;
- p.setColor(SK_ColorRED);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawRect(r, p);
- }
-}
-
-void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- const SkRect& bounds = rrect.getBounds();
-
- xlate_and_scale_to_bounds(canvas, bounds);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawRRect(rrect, p);
- canvas->restore();
-}
-
-void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- const SkRect& bounds = outer.getBounds();
-
- xlate_and_scale_to_bounds(canvas, bounds);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawDRRect(outer, inner, p);
- canvas->restore();
-}
-
-static const char* const gBlendModeMap[] = {
- "clear",
- "src",
- "dst",
- "srcOver",
- "dstOver",
- "srcIn",
- "dstIn",
- "srcOut",
- "dstOut",
- "srcATop",
- "dstATop",
- "xor",
- "plus",
- "modulate",
-
- "screen",
-
- "overlay",
- "darken",
- "lighten",
- "colorDodge",
- "colorBurn",
- "hardLight",
- "softLight",
- "difference",
- "exclusion",
- "multiply",
-
- "hue",
- "saturation",
- "color",
- "luminosity",
-};
-
-static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
- "blendMode mismatch");
-static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
- "blendMode mismatch");
-
-void apply_paint_blend_mode(const SkPaint& paint, Json::Value* target) {
- const auto mode = paint.getBlendMode();
- if (mode != SkBlendMode::kSrcOver) {
- SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE] =
- Json::Value(gBlendModeMap[static_cast<size_t>(mode)]);
- }
-}
-
-void extract_json_paint_blend_mode(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE)) {
- const char* mode = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE].asCString();
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gBlendModeMap); ++i) {
- if (!strcmp(mode, gBlendModeMap[i])) {
- target->setBlendMode(static_cast<SkBlendMode>(i));
- break;
- }
- }
- }
-}
-
-};
-
-Json::Value SkDrawCommand::MakeJsonColor(const SkColor color) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(SkColorGetA(color)));
- result.append(Json::Value(SkColorGetR(color)));
- result.append(Json::Value(SkColorGetG(color)));
- result.append(Json::Value(SkColorGetB(color)));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonColor4f(const SkColor4f& color) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(color.fA));
- result.append(Json::Value(color.fR));
- result.append(Json::Value(color.fG));
- result.append(Json::Value(color.fB));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonPoint(const SkPoint& point) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(point.x()));
- result.append(Json::Value(point.y()));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonPoint(SkScalar x, SkScalar y) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(x));
- result.append(Json::Value(y));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonRect(const SkRect& rect) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(rect.left()));
- result.append(Json::Value(rect.top()));
- result.append(Json::Value(rect.right()));
- result.append(Json::Value(rect.bottom()));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonIRect(const SkIRect& rect) {
- Json::Value result(Json::arrayValue);
- result.append(Json::Value(rect.left()));
- result.append(Json::Value(rect.top()));
- result.append(Json::Value(rect.right()));
- result.append(Json::Value(rect.bottom()));
- return result;
-}
-
-static Json::Value make_json_rrect(const SkRRect& rrect) {
- Json::Value result(Json::arrayValue);
- result.append(SkDrawCommand::MakeJsonRect(rrect.rect()));
- result.append(SkDrawCommand::MakeJsonPoint(rrect.radii(SkRRect::kUpperLeft_Corner)));
- result.append(SkDrawCommand::MakeJsonPoint(rrect.radii(SkRRect::kUpperRight_Corner)));
- result.append(SkDrawCommand::MakeJsonPoint(rrect.radii(SkRRect::kLowerRight_Corner)));
- result.append(SkDrawCommand::MakeJsonPoint(rrect.radii(SkRRect::kLowerLeft_Corner)));
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonMatrix(const SkMatrix& matrix) {
- Json::Value result(Json::arrayValue);
- Json::Value row1(Json::arrayValue);
- row1.append(Json::Value(matrix[0]));
- row1.append(Json::Value(matrix[1]));
- row1.append(Json::Value(matrix[2]));
- result.append(row1);
- Json::Value row2(Json::arrayValue);
- row2.append(Json::Value(matrix[3]));
- row2.append(Json::Value(matrix[4]));
- row2.append(Json::Value(matrix[5]));
- result.append(row2);
- Json::Value row3(Json::arrayValue);
- row3.append(Json::Value(matrix[6]));
- row3.append(Json::Value(matrix[7]));
- row3.append(Json::Value(matrix[8]));
- result.append(row3);
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonScalar(SkScalar z) {
- Json::Value result(z);
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonPath(const SkPath& path) {
- Json::Value result(Json::objectValue);
- switch (path.getFillType()) {
- case SkPath::kWinding_FillType:
- result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_WINDING;
- break;
- case SkPath::kEvenOdd_FillType:
- result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_EVENODD;
- break;
- case SkPath::kInverseWinding_FillType:
- result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING;
- break;
- case SkPath::kInverseEvenOdd_FillType:
- result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD;
- break;
- }
- Json::Value verbs(Json::arrayValue);
- SkPath::Iter iter(path, false);
- SkPoint pts[4];
- SkPath::Verb verb;
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kLine_Verb: {
- Json::Value line(Json::objectValue);
- line[SKDEBUGCANVAS_VERB_LINE] = MakeJsonPoint(pts[1]);
- verbs.append(line);
- break;
- }
- case SkPath::kQuad_Verb: {
- Json::Value quad(Json::objectValue);
- Json::Value coords(Json::arrayValue);
- coords.append(MakeJsonPoint(pts[1]));
- coords.append(MakeJsonPoint(pts[2]));
- quad[SKDEBUGCANVAS_VERB_QUAD] = coords;
- verbs.append(quad);
- break;
- }
- case SkPath::kCubic_Verb: {
- Json::Value cubic(Json::objectValue);
- Json::Value coords(Json::arrayValue);
- coords.append(MakeJsonPoint(pts[1]));
- coords.append(MakeJsonPoint(pts[2]));
- coords.append(MakeJsonPoint(pts[3]));
- cubic[SKDEBUGCANVAS_VERB_CUBIC] = coords;
- verbs.append(cubic);
- break;
- }
- case SkPath::kConic_Verb: {
- Json::Value conic(Json::objectValue);
- Json::Value coords(Json::arrayValue);
- coords.append(MakeJsonPoint(pts[1]));
- coords.append(MakeJsonPoint(pts[2]));
- coords.append(Json::Value(iter.conicWeight()));
- conic[SKDEBUGCANVAS_VERB_CONIC] = coords;
- verbs.append(conic);
- break;
- }
- case SkPath::kMove_Verb: {
- Json::Value move(Json::objectValue);
- move[SKDEBUGCANVAS_VERB_MOVE] = MakeJsonPoint(pts[0]);
- verbs.append(move);
- break;
- }
- case SkPath::kClose_Verb:
- verbs.append(Json::Value(SKDEBUGCANVAS_VERB_CLOSE));
- break;
- case SkPath::kDone_Verb:
- break;
- }
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_VERBS] = verbs;
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonRegion(const SkRegion& region) {
- return Json::Value("<unimplemented>");
-}
-
-static Json::Value make_json_regionop(SkClipOp op) {
- switch (op) {
- case kDifference_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_DIFFERENCE);
- case kIntersect_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_INTERSECT);
- case kUnion_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_UNION);
- case kXOR_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_XOR);
- case kReverseDifference_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE);
- case kReplace_SkClipOp:
- return Json::Value(SKDEBUGCANVAS_REGIONOP_REPLACE);
- default:
- SkASSERT(false);
- return Json::Value("<invalid region op>");
- };
-}
-
-static Json::Value make_json_pointmode(SkCanvas::PointMode mode) {
- switch (mode) {
- case SkCanvas::kPoints_PointMode:
- return Json::Value(SKDEBUGCANVAS_POINTMODE_POINTS);
- case SkCanvas::kLines_PointMode:
- return Json::Value(SKDEBUGCANVAS_POINTMODE_LINES);
- case SkCanvas::kPolygon_PointMode:
- return Json::Value(SKDEBUGCANVAS_POINTMODE_POLYGON);
- default:
- SkASSERT(false);
- return Json::Value("<invalid point mode>");
- };
-}
-
-static void store_scalar(Json::Value* target, const char* key, SkScalar value,
- SkScalar defaultValue) {
- if (value != defaultValue) {
- (*target)[key] = Json::Value(value);
- }
-}
-
-static void store_bool(Json::Value* target, const char* key, bool value, bool defaultValue) {
- if (value != defaultValue) {
- (*target)[key] = Json::Value(value);
- }
-}
-
-static void encode_data(const void* bytes, size_t count, const char* contentType,
- UrlDataManager& urlDataManager, Json::Value* target) {
- sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
- SkString url = urlDataManager.addData(data.get(), contentType);
- *target = Json::Value(url.c_str());
-}
-
-void SkDrawCommand::flatten(const SkFlattenable* flattenable, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkBinaryWriteBuffer buffer;
- flattenable->flatten(buffer);
- void* data = sk_malloc_throw(buffer.bytesWritten());
- buffer.writeToMemory(data);
- Json::Value jsonData;
- encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager, &jsonData);
- Json::Value jsonFlattenable;
- jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME] = Json::Value(flattenable->getTypeName());
- jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
-
- SkJsonWriteBuffer jsonBuffer(&urlDataManager);
- flattenable->flatten(jsonBuffer);
- jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_VALUES] = jsonBuffer.getValue();
-
- (*target) = jsonFlattenable;
- sk_free(data);
-}
-
-static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
- SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr);
- out->write(data, length);
-}
-
-void SkDrawCommand::WritePNG(const uint8_t* rgba, unsigned width, unsigned height,
- SkWStream& out, bool isOpaque) {
- png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- SkASSERT(png != nullptr);
- png_infop info_ptr = png_create_info_struct(png);
- SkASSERT(info_ptr != nullptr);
- if (setjmp(png_jmpbuf(png))) {
- SkFAIL("png encode error");
- }
- png_set_write_fn(png, &out, write_png_callback, NULL);
- int colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA;
- png_set_IHDR(png, info_ptr, width, height, 8, colorType, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- png_set_compression_level(png, 1);
- png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*));
- png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 4);
- for (png_size_t y = 0; y < height; ++y) {
- const uint8_t* src = rgba + y * width * 4;
- rows[y] = pixels + y * width * 4;
- for (png_size_t x = 0; x < width; ++x) {
- rows[y][x * 4] = src[x * 4];
- rows[y][x * 4 + 1] = src[x * 4 + 1];
- rows[y][x * 4 + 2] = src[x * 4 + 2];
- rows[y][x * 4 + 3] = src[x * 4 + 3];
- }
- }
- png_write_info(png, info_ptr);
- if (isOpaque) {
- png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
- }
- png_set_filter(png, 0, PNG_NO_FILTERS);
- png_write_image(png, &rows[0]);
- png_destroy_write_struct(&png, NULL);
- sk_free(rows);
- sk_free(pixels);
-}
-
-bool SkDrawCommand::flatten(const SkImage& image, Json::Value* target,
- UrlDataManager& urlDataManager) {
- size_t rowBytes = 4 * image.width();
- SkAutoMalloc buffer(rowBytes * image.height());
- SkImageInfo dstInfo = SkImageInfo::Make(image.width(), image.height(),
- kN32_SkColorType, kPremul_SkAlphaType);
- if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
- SkDebugf("readPixels failed\n");
- return false;
- }
-
- SkBitmap bm;
- bm.installPixels(dstInfo, buffer.get(), rowBytes);
- sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(bm);
-
- SkDynamicMemoryWStream out;
- SkDrawCommand::WritePNG(encodedBitmap->bytes(), image.width(), image.height(),
- out, false);
- sk_sp<SkData> encoded = out.detachAsData();
- Json::Value jsonData;
- encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager, &jsonData);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
- return true;
-}
-
-static const char* color_type_name(SkColorType colorType) {
- switch (colorType) {
- case kARGB_4444_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_ARGB4444;
- case kRGBA_8888_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
- case kBGRA_8888_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_BGRA8888;
- case kRGB_565_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_565;
- case kGray_8_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_GRAY8;
- case kAlpha_8_SkColorType:
- return SKDEBUGCANVAS_COLORTYPE_ALPHA8;
- default:
- SkASSERT(false);
- return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
- }
-}
-
-static const char* alpha_type_name(SkAlphaType alphaType) {
- switch (alphaType) {
- case kOpaque_SkAlphaType:
- return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
- case kPremul_SkAlphaType:
- return SKDEBUGCANVAS_ALPHATYPE_PREMUL;
- case kUnpremul_SkAlphaType:
- return SKDEBUGCANVAS_ALPHATYPE_UNPREMUL;
- default:
- SkASSERT(false);
- return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
- }
-}
-
-static Json::ArrayIndex decode_data(Json::Value data, UrlDataManager& urlDataManager,
- const void** target) {
- UrlDataManager::UrlData* urlData = urlDataManager.getDataFromUrl(SkString(data.asCString()));
- if (urlData == nullptr) {
- SkASSERT(false);
- *target = nullptr;
- return 0;
- }
- *target = urlData->fData->data();
- // cast should be safe for any reasonably-sized object...
- return (Json::ArrayIndex) urlData->fData->size();
-}
-
-static SkFlattenable* load_flattenable(Json::Value jsonFlattenable,
- UrlDataManager& urlDataManager) {
- if (!jsonFlattenable.isMember(SKDEBUGCANVAS_ATTRIBUTE_NAME)) {
- return nullptr;
- }
- const char* name = jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME].asCString();
- SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
- if (factory == nullptr) {
- SkDebugf("no factory for loading '%s'\n", name);
- return nullptr;
- }
- const void* data;
- int size = decode_data(jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
- SkValidatingReadBuffer buffer(data, size);
- sk_sp<SkFlattenable> result = factory(buffer);
- if (!buffer.isValid()) {
- SkDebugf("invalid buffer loading flattenable\n");
- return nullptr;
- }
- return result.release();
-}
-
-static SkColorType colortype_from_name(const char* name) {
- if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ARGB4444)) {
- return kARGB_4444_SkColorType;
- }
- else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_RGBA8888)) {
- return kRGBA_8888_SkColorType;
- }
- else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_BGRA8888)) {
- return kBGRA_8888_SkColorType;
- }
- else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_565)) {
- return kRGB_565_SkColorType;
- }
- else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_GRAY8)) {
- return kGray_8_SkColorType;
- }
- else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ALPHA8)) {
- return kAlpha_8_SkColorType;
- }
- SkASSERT(false);
- return kN32_SkColorType;
-}
-
-static SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
- if (bitmap->colorType() == colorType ) {
- return bitmap;
- }
- SkBitmap* dst = new SkBitmap();
- if (dst->tryAllocPixels(bitmap->info().makeColorType(colorType)) &&
- bitmap->readPixels(dst->info(), dst->getPixels(), dst->rowBytes(), 0, 0))
- {
- delete bitmap;
- return dst;
- }
- SkASSERT(false);
- delete dst;
- return bitmap;
-}
-
-// caller is responsible for freeing return value
-static SkBitmap* load_bitmap(const Json::Value& jsonBitmap, UrlDataManager& urlDataManager) {
- if (!jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_DATA)) {
- SkDebugf("invalid bitmap\n");
- return nullptr;
- }
- const void* data;
- int size = decode_data(jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
- sk_sp<SkData> encoded(SkData::MakeWithoutCopy(data, size));
- sk_sp<SkImage> image(SkImage::MakeFromEncoded(std::move(encoded), nullptr));
-
- std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
- if (nullptr != image) {
- if (!image->asLegacyBitmap(bitmap.get(), SkImage::kRW_LegacyBitmapMode)) {
- SkDebugf("image decode failed\n");
- return nullptr;
- }
-
- if (jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
- const char* ctName = jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_COLOR].asCString();
- SkColorType ct = colortype_from_name(ctName);
- bitmap.reset(convert_colortype(bitmap.release(), ct));
- }
- return bitmap.release();
- }
- SkDebugf("image decode failed\n");
- return nullptr;
-}
-
-static sk_sp<SkImage> load_image(const Json::Value& jsonImage, UrlDataManager& urlDataManager) {
- SkBitmap* bitmap = load_bitmap(jsonImage, urlDataManager);
- if (bitmap == nullptr) {
- return nullptr;
- }
- auto result = SkImage::MakeFromBitmap(*bitmap);
- delete bitmap;
- return result;
-}
-
-bool SkDrawCommand::flatten(const SkBitmap& bitmap, Json::Value* target,
- UrlDataManager& urlDataManager) {
- sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = Json::Value(color_type_name(bitmap.colorType()));
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = Json::Value(alpha_type_name(bitmap.alphaType()));
- bool success = flatten(*image, target, urlDataManager);
- return success;
-}
-
-static void apply_paint_hinting(const SkPaint& paint, Json::Value* target) {
- SkPaint::Hinting hinting = paint.getHinting();
- if (hinting != SkPaintDefaults_Hinting) {
- switch (hinting) {
- case SkPaint::kNo_Hinting:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_HINTING] = SKDEBUGCANVAS_HINTING_NONE;
- break;
- case SkPaint::kSlight_Hinting:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_HINTING] = SKDEBUGCANVAS_HINTING_SLIGHT;
- break;
- case SkPaint::kNormal_Hinting:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_HINTING] = SKDEBUGCANVAS_HINTING_NORMAL;
- break;
- case SkPaint::kFull_Hinting:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_HINTING] = SKDEBUGCANVAS_HINTING_FULL;
- break;
- }
- }
-}
-
-static void apply_paint_color(const SkPaint& paint, Json::Value* target) {
- SkColor color = paint.getColor();
- if (color != SK_ColorBLACK) {
- Json::Value colorValue(Json::arrayValue);
- colorValue.append(Json::Value(SkColorGetA(color)));
- colorValue.append(Json::Value(SkColorGetR(color)));
- colorValue.append(Json::Value(SkColorGetG(color)));
- colorValue.append(Json::Value(SkColorGetB(color)));
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = colorValue;;
- }
-}
-
-static void apply_paint_style(const SkPaint& paint, Json::Value* target) {
- SkPaint::Style style = paint.getStyle();
- if (style != SkPaint::kFill_Style) {
- switch (style) {
- case SkPaint::kStroke_Style: {
- Json::Value stroke(SKDEBUGCANVAS_STYLE_STROKE);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = stroke;
- break;
- }
- case SkPaint::kStrokeAndFill_Style: {
- Json::Value strokeAndFill(SKDEBUGCANVAS_STYLE_STROKEANDFILL);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = strokeAndFill;
- break;
- }
- default: SkASSERT(false);
- }
- }
-}
-
-static void apply_paint_cap(const SkPaint& paint, Json::Value* target) {
- SkPaint::Cap cap = paint.getStrokeCap();
- if (cap != SkPaint::kDefault_Cap) {
- switch (cap) {
- case SkPaint::kButt_Cap:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_BUTT);
- break;
- case SkPaint::kRound_Cap:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_ROUND);
- break;
- case SkPaint::kSquare_Cap:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_SQUARE);
- break;
- default: SkASSERT(false);
- }
- }
-}
-
-static void apply_paint_join(const SkPaint& paint, Json::Value* target) {
- SkPaint::Join join = paint.getStrokeJoin();
- if (join != SkPaint::kDefault_Join) {
- switch (join) {
- case SkPaint::kMiter_Join:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
- SKDEBUGCANVAS_MITER_JOIN);
- break;
- case SkPaint::kRound_Join:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
- SKDEBUGCANVAS_ROUND_JOIN);
- break;
- case SkPaint::kBevel_Join:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
- SKDEBUGCANVAS_BEVEL_JOIN);
- break;
- default: SkASSERT(false);
- }
- }
-}
-
-static void apply_paint_filterquality(const SkPaint& paint, Json::Value* target) {
- SkFilterQuality quality = paint.getFilterQuality();
- switch (quality) {
- case kNone_SkFilterQuality:
- break;
- case kLow_SkFilterQuality:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
- SKDEBUGCANVAS_FILTERQUALITY_LOW);
- break;
- case kMedium_SkFilterQuality:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
- SKDEBUGCANVAS_FILTERQUALITY_MEDIUM);
- break;
- case kHigh_SkFilterQuality:
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
- SKDEBUGCANVAS_FILTERQUALITY_HIGH);
- break;
- }
-}
-
-static void apply_paint_maskfilter(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkMaskFilter* maskFilter = paint.getMaskFilter();
- if (maskFilter != nullptr) {
- SkMaskFilter::BlurRec blurRec;
- if (maskFilter->asABlur(&blurRec)) {
- Json::Value blur(Json::objectValue);
- blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
- switch (blurRec.fStyle) {
- case SkBlurStyle::kNormal_SkBlurStyle:
- blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
- SKDEBUGCANVAS_BLURSTYLE_NORMAL);
- break;
- case SkBlurStyle::kSolid_SkBlurStyle:
- blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
- SKDEBUGCANVAS_BLURSTYLE_SOLID);
- break;
- case SkBlurStyle::kOuter_SkBlurStyle:
- blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
- SKDEBUGCANVAS_BLURSTYLE_OUTER);
- break;
- case SkBlurStyle::kInner_SkBlurStyle:
- blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
- SKDEBUGCANVAS_BLURSTYLE_INNER);
- break;
- default:
- SkASSERT(false);
- }
- switch (blurRec.fQuality) {
- case SkBlurQuality::kLow_SkBlurQuality:
- blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
- SKDEBUGCANVAS_BLURQUALITY_LOW);
- break;
- case SkBlurQuality::kHigh_SkBlurQuality:
- blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
- SKDEBUGCANVAS_BLURQUALITY_HIGH);
- break;
- default:
- SkASSERT(false);
- }
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_BLUR] = blur;
- } else {
- Json::Value jsonMaskFilter;
- SkDrawCommand::flatten(maskFilter, &jsonMaskFilter, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER] = jsonMaskFilter;
- }
- }
-}
-
-static void apply_paint_patheffect(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkPathEffect* pathEffect = paint.getPathEffect();
- if (pathEffect != nullptr) {
- SkPathEffect::DashInfo dashInfo;
- SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
- if (dashType == SkPathEffect::kDash_DashType) {
- dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
- pathEffect->asADash(&dashInfo);
- Json::Value dashing(Json::objectValue);
- Json::Value intervals(Json::arrayValue);
- for (int32_t i = 0; i < dashInfo.fCount; i++) {
- intervals.append(Json::Value(dashInfo.fIntervals[i]));
- }
- sk_free(dashInfo.fIntervals);
- dashing[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS] = intervals;
- dashing[SKDEBUGCANVAS_ATTRIBUTE_PHASE] = dashInfo.fPhase;
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_DASHING] = dashing;
- } else {
- Json::Value jsonPathEffect;
- SkDrawCommand::flatten(pathEffect, &jsonPathEffect, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT] = jsonPathEffect;
- }
- }
-}
-
-static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) {
- SkPaint::Align textAlign = paint.getTextAlign();
- if (textAlign != SkPaint::kLeft_Align) {
- switch (textAlign) {
- case SkPaint::kCenter_Align: {
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_CENTER;
- break;
- }
- case SkPaint::kRight_Align: {
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_RIGHT;
- break;
- }
- default: SkASSERT(false);
- }
- }
-}
-
-static void apply_paint_typeface(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkTypeface* typeface = paint.getTypeface();
- if (typeface != nullptr) {
- Json::Value jsonTypeface;
- SkDynamicMemoryWStream buffer;
- typeface->serialize(&buffer);
- void* data = sk_malloc_throw(buffer.bytesWritten());
- buffer.copyTo(data);
- Json::Value jsonData;
- encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager,
- &jsonData);
- jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
- sk_free(data);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE] = jsonTypeface;
- }
-}
-
-static void apply_paint_shader(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkFlattenable* shader = paint.getShader();
- if (shader != nullptr) {
- Json::Value jsonShader;
- SkDrawCommand::flatten(shader, &jsonShader, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_SHADER] = jsonShader;
- }
-}
-
-static void apply_paint_imagefilter(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkFlattenable* imageFilter = paint.getImageFilter();
- if (imageFilter != nullptr) {
- Json::Value jsonImageFilter;
- SkDrawCommand::flatten(imageFilter, &jsonImageFilter, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER] = jsonImageFilter;
- }
-}
-
-static void apply_paint_colorfilter(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkFlattenable* colorFilter = paint.getColorFilter();
- if (colorFilter != nullptr) {
- Json::Value jsonColorFilter;
- SkDrawCommand::flatten(colorFilter, &jsonColorFilter, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER] = jsonColorFilter;
- }
-}
-
-static void apply_paint_looper(const SkPaint& paint, Json::Value* target,
- UrlDataManager& urlDataManager) {
- SkFlattenable* looper = paint.getLooper();
- if (looper != nullptr) {
- Json::Value jsonLooper;
- SkDrawCommand::flatten(looper, &jsonLooper, urlDataManager);
- (*target)[SKDEBUGCANVAS_ATTRIBUTE_LOOPER] = jsonLooper;
- }
-}
-
-Json::Value SkDrawCommand::MakeJsonPaint(const SkPaint& paint, UrlDataManager& urlDataManager) {
- Json::Value result(Json::objectValue);
- store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
- store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(),
- SkPaintDefaults_MiterLimit);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, paint.isFakeBoldText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT, paint.isLinearText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, paint.isSubpixelText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT, paint.isDevKernText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT, paint.isLCDRenderText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, paint.isEmbeddedBitmapText(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING, paint.isAutohinted(), false);
- store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_VERTICALTEXT, paint.isVerticalText(), false);
- //kGenA8FromLCD_Flag
-
- store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE, paint.getTextSize(),
- SkPaintDefaults_TextSize);
- store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextScaleX(), SK_Scalar1);
- store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextSkewX(), 0.0f);
- apply_paint_hinting(paint, &result);
- apply_paint_color(paint, &result);
- apply_paint_style(paint, &result);
- apply_paint_blend_mode(paint, &result);
- apply_paint_cap(paint, &result);
- apply_paint_join(paint, &result);
- apply_paint_filterquality(paint, &result);
- apply_paint_textalign(paint, &result);
- apply_paint_patheffect(paint, &result, urlDataManager);
- apply_paint_maskfilter(paint, &result, urlDataManager);
- apply_paint_shader(paint, &result, urlDataManager);
- apply_paint_looper(paint, &result, urlDataManager);
- apply_paint_imagefilter(paint, &result, urlDataManager);
- apply_paint_colorfilter(paint, &result, urlDataManager);
- apply_paint_typeface(paint, &result, urlDataManager);
- return result;
-}
-
-Json::Value SkDrawCommand::MakeJsonLattice(const SkCanvas::Lattice& lattice) {
- Json::Value result(Json::objectValue);
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT] = Json::Value(lattice.fXCount);
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT] = Json::Value(lattice.fYCount);
- if (nullptr != lattice.fBounds) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS] = MakeJsonIRect(*lattice.fBounds);
- }
- Json::Value XDivs(Json::arrayValue);
- for (int i = 0; i < lattice.fXCount; i++) {
- XDivs.append(Json::Value(lattice.fXDivs[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS] = XDivs;
- Json::Value YDivs(Json::arrayValue);
- for (int i = 0; i < lattice.fYCount; i++) {
- YDivs.append(Json::Value(lattice.fYDivs[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS] = YDivs;
- if (nullptr != lattice.fFlags) {
- Json::Value flags(Json::arrayValue);
- int flagCount = 0;
- for (int row = 0; row < lattice.fYCount+1; row++) {
- Json::Value flagsRow(Json::arrayValue);
- for (int column = 0; column < lattice.fXCount+1; column++) {
- flagsRow.append(Json::Value(lattice.fFlags[flagCount++]));
- }
- flags.append(flagsRow);
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS] = flags;
- }
- return result;
-}
-
-static SkPoint get_json_point(Json::Value point) {
- return SkPoint::Make(point[0].asFloat(), point[1].asFloat());
-}
-
-static SkColor get_json_color(Json::Value color) {
- return SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(), color[3].asInt());
-}
-
-static void extract_json_paint_color(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
- target->setColor(get_json_color(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLOR]));
- }
-}
-
-static void extract_json_paint_shader(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_SHADER)) {
- Json::Value jsonShader = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_SHADER];
- SkShader* shader = (SkShader*) load_flattenable(jsonShader, urlDataManager);
- if (shader != nullptr) {
- target->setShader(sk_ref_sp(shader));
- }
- }
-}
-
-static void extract_json_paint_patheffect(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT)) {
- Json::Value jsonPathEffect = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT];
- sk_sp<SkPathEffect> pathEffect((SkPathEffect*)load_flattenable(jsonPathEffect,
- urlDataManager));
- if (pathEffect != nullptr) {
- target->setPathEffect(pathEffect);
- }
- }
-}
-
-static void extract_json_paint_maskfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER)) {
- Json::Value jsonMaskFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER];
- sk_sp<SkMaskFilter> maskFilter((SkMaskFilter*)load_flattenable(jsonMaskFilter,
- urlDataManager));
- if (maskFilter) {
- target->setMaskFilter(std::move(maskFilter));
- }
- }
-}
-
-static void extract_json_paint_colorfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER)) {
- Json::Value jsonColorFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER];
- sk_sp<SkColorFilter> colorFilter((SkColorFilter*)load_flattenable(jsonColorFilter,
- urlDataManager));
- if (colorFilter != nullptr) {
- target->setColorFilter(colorFilter);
- }
- }
-}
-
-static void extract_json_paint_looper(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LOOPER)) {
- Json::Value jsonLooper = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_LOOPER];
- sk_sp<SkDrawLooper> looper((SkDrawLooper*) load_flattenable(jsonLooper, urlDataManager));
- if (looper != nullptr) {
- target->setLooper(std::move(looper));
- }
- }
-}
-
-static void extract_json_paint_imagefilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER)) {
- Json::Value jsonImageFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER];
- sk_sp<SkImageFilter> imageFilter((SkImageFilter*) load_flattenable(jsonImageFilter,
- urlDataManager));
- if (imageFilter != nullptr) {
- target->setImageFilter(imageFilter);
- }
- }
-}
-
-static void extract_json_paint_typeface(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
- SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE)) {
- Json::Value jsonTypeface = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE];
- Json::Value jsonData = jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA];
- const void* data;
- Json::ArrayIndex length = decode_data(jsonData, urlDataManager, &data);
- SkMemoryStream buffer(data, length);
- target->setTypeface(SkTypeface::MakeDeserialize(&buffer));
- }
-}
-
-static void extract_json_paint_hinting(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_HINTING)) {
- const char* hinting = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_HINTING].asCString();
- if (!strcmp(hinting, SKDEBUGCANVAS_HINTING_NONE)) {
- target->setHinting(SkPaint::kNo_Hinting);
- } else if (!strcmp(hinting, SKDEBUGCANVAS_HINTING_SLIGHT)) {
- target->setHinting(SkPaint::kSlight_Hinting);
- } else if (!strcmp(hinting, SKDEBUGCANVAS_HINTING_NORMAL)) {
- target->setHinting(SkPaint::kNormal_Hinting);
- } else if (!strcmp(hinting, SKDEBUGCANVAS_HINTING_FULL)) {
- target->setHinting(SkPaint::kFull_Hinting);
- }
- }
-}
-
-static void extract_json_paint_style(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STYLE)) {
- const char* style = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
- if (!strcmp(style, SKDEBUGCANVAS_STYLE_FILL)) {
- target->setStyle(SkPaint::kFill_Style);
- }
- else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKE)) {
- target->setStyle(SkPaint::kStroke_Style);
- }
- else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKEANDFILL)) {
- target->setStyle(SkPaint::kStrokeAndFill_Style);
- }
- }
-}
-
-static void extract_json_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH)) {
- float strokeWidth = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
- target->setStrokeWidth(strokeWidth);
- }
-}
-
-static void extract_json_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER)) {
- float strokeMiter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
- target->setStrokeMiter(strokeMiter);
- }
-}
-
-static void extract_json_paint_strokejoin(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN)) {
- const char* join = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN].asCString();
- if (!strcmp(join, SKDEBUGCANVAS_MITER_JOIN)) {
- target->setStrokeJoin(SkPaint::kMiter_Join);
- }
- else if (!strcmp(join, SKDEBUGCANVAS_ROUND_JOIN)) {
- target->setStrokeJoin(SkPaint::kRound_Join);
- }
- else if (!strcmp(join, SKDEBUGCANVAS_BEVEL_JOIN)) {
- target->setStrokeJoin(SkPaint::kBevel_Join);
- }
- else {
- SkASSERT(false);
- }
- }
-}
-
-static void extract_json_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_CAP)) {
- const char* cap = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_CAP].asCString();
- if (!strcmp(cap, SKDEBUGCANVAS_CAP_BUTT)) {
- target->setStrokeCap(SkPaint::kButt_Cap);
- }
- else if (!strcmp(cap, SKDEBUGCANVAS_CAP_ROUND)) {
- target->setStrokeCap(SkPaint::kRound_Cap);
- }
- else if (!strcmp(cap, SKDEBUGCANVAS_CAP_SQUARE)) {
- target->setStrokeCap(SkPaint::kSquare_Cap);
- }
- }
-}
-
-static void extract_json_paint_filterquality(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY)) {
- const char* quality = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY].asCString();
- if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_NONE)) {
- target->setFilterQuality(kNone_SkFilterQuality);
- }
- else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_LOW)) {
- target->setFilterQuality(kLow_SkFilterQuality);
- }
- else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_MEDIUM)) {
- target->setFilterQuality(kMedium_SkFilterQuality);
- }
- else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_HIGH)) {
- target->setFilterQuality(kHigh_SkFilterQuality);
- }
- }
-}
-
-static void extract_json_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS)) {
- target->setAntiAlias(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
- }
-}
-
-static void extract_json_paint_dither(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DITHER)) {
- target->setDither(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DITHER].asBool());
- }
-}
-
-static void extract_json_paint_fakeboldtext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT)) {
- target->setFakeBoldText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT].asBool());
- }
-}
-
-static void extract_json_paint_lineartext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT)) {
- target->setLinearText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT].asBool());
- }
-}
-
-static void extract_json_paint_subpixeltext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT)) {
- target->setSubpixelText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT].asBool());
- }
-}
-
-static void extract_json_paint_devkerntext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT)) {
- target->setDevKernText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT].asBool());
- }
-}
-
-static void extract_json_paint_lcdrendertext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT)) {
- target->setLCDRenderText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT].asBool());
- }
-}
-
-static void extract_json_paint_embeddedbitmaptext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT)) {
- target->setEmbeddedBitmapText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT].asBool());
- }
-}
-
-static void extract_json_paint_autohinting(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING)) {
- target->setAutohinted(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING].asBool());
- }
-}
-
-static void extract_json_paint_verticaltext(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_VERTICALTEXT)) {
- target->setVerticalText(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_VERTICALTEXT].asBool());
- }
-}
-
-static void extract_json_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_BLUR)) {
- Json::Value blur = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_BLUR];
- SkScalar sigma = blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA].asFloat();
- SkBlurStyle style;
- const char* jsonStyle = blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
- if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_NORMAL)) {
- style = SkBlurStyle::kNormal_SkBlurStyle;
- }
- else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_SOLID)) {
- style = SkBlurStyle::kSolid_SkBlurStyle;
- }
- else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_OUTER)) {
- style = SkBlurStyle::kOuter_SkBlurStyle;
- }
- else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_INNER)) {
- style = SkBlurStyle::kInner_SkBlurStyle;
- }
- else {
- SkASSERT(false);
- style = SkBlurStyle::kNormal_SkBlurStyle;
- }
- SkBlurMaskFilter::BlurFlags flags;
- const char* jsonQuality = blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY].asCString();
- if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_LOW)) {
- flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
- }
- else if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_HIGH)) {
- flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
- }
- else {
- SkASSERT(false);
- flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
- }
- target->setMaskFilter(SkBlurMaskFilter::Make(style, sigma, flags));
- }
-}
-
-static void extract_json_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DASHING)) {
- Json::Value dash = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DASHING];
- Json::Value jsonIntervals = dash[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS];
- Json::ArrayIndex count = jsonIntervals.size();
- SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
- for (Json::ArrayIndex i = 0; i < count; i++) {
- intervals[i] = jsonIntervals[i].asFloat();
- }
- SkScalar phase = dash[SKDEBUGCANVAS_ATTRIBUTE_PHASE].asFloat();
- target->setPathEffect(SkDashPathEffect::Make(intervals, count, phase));
- sk_free(intervals);
- }
-}
-
-static void extract_json_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN)) {
- SkPaint::Align textAlign;
- const char* jsonAlign = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
- if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_LEFT)) {
- textAlign = SkPaint::kLeft_Align;
- }
- else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_CENTER)) {
- textAlign = SkPaint::kCenter_Align;
- }
- else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_RIGHT)) {
- textAlign = SkPaint::kRight_Align;
- }
- else {
- SkASSERT(false);
- textAlign = SkPaint::kLeft_Align;
- }
- target->setTextAlign(textAlign);
- }
-}
-
-static void extract_json_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE)) {
- float textSize = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
- target->setTextSize(textSize);
- }
-}
-
-static void extract_json_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX)) {
- float textScaleX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
- target->setTextScaleX(textScaleX);
- }
-}
-
-static void extract_json_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
- if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX)) {
- float textSkewX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
- target->setTextSkewX(textSkewX);
- }
-}
-
-static void extract_json_paint(Json::Value& paint, UrlDataManager& urlDataManager,
- SkPaint* result) {
- extract_json_paint_hinting(paint, result);
- extract_json_paint_color(paint, result);
- extract_json_paint_shader(paint, urlDataManager, result);
- extract_json_paint_patheffect(paint, urlDataManager, result);
- extract_json_paint_maskfilter(paint, urlDataManager, result);
- extract_json_paint_colorfilter(paint, urlDataManager, result);
- extract_json_paint_looper(paint, urlDataManager, result);
- extract_json_paint_imagefilter(paint, urlDataManager, result);
- extract_json_paint_typeface(paint, urlDataManager, result);
- extract_json_paint_style(paint, result);
- extract_json_paint_blend_mode(paint, result);
- extract_json_paint_strokewidth(paint, result);
- extract_json_paint_strokemiter(paint, result);
- extract_json_paint_strokejoin(paint, result);
- extract_json_paint_cap(paint, result);
- extract_json_paint_filterquality(paint, result);
- extract_json_paint_antialias(paint, result);
- extract_json_paint_dither(paint, result);
- extract_json_paint_fakeboldtext(paint, result);
- extract_json_paint_lineartext(paint, result);
- extract_json_paint_subpixeltext(paint, result);
- extract_json_paint_devkerntext(paint, result);
- extract_json_paint_lcdrendertext(paint, result);
- extract_json_paint_embeddedbitmaptext(paint, result);
- extract_json_paint_autohinting(paint, result);
- extract_json_paint_verticaltext(paint, result);
- extract_json_paint_blur(paint, result);
- extract_json_paint_dashing(paint, result);
- extract_json_paint_textalign(paint, result);
- extract_json_paint_textsize(paint, result);
- extract_json_paint_textscalex(paint, result);
- extract_json_paint_textskewx(paint, result);
-}
-
-static void extract_json_rect(Json::Value& rect, SkRect* result) {
- result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
-}
-
-static void extract_json_irect(Json::Value& rect, SkIRect* result) {
- result->set(rect[0].asInt(), rect[1].asInt(), rect[2].asInt(), rect[3].asInt());
-}
-
-static void extract_json_rrect(Json::Value& rrect, SkRRect* result) {
- SkVector radii[4] = {
- { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
- { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
- { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
- { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
- };
- result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
- rrect[0][2].asFloat(), rrect[0][3].asFloat()),
- radii);
-}
-
-static void extract_json_matrix(Json::Value& matrix, SkMatrix* result) {
- SkScalar values[] = {
- matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
- matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
- matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
- };
- result->set9(values);
-}
-
-static void extract_json_path(Json::Value& path, SkPath* result) {
- const char* fillType = path[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE].asCString();
- if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_WINDING)) {
- result->setFillType(SkPath::kWinding_FillType);
- }
- else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_EVENODD)) {
- result->setFillType(SkPath::kEvenOdd_FillType);
- }
- else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING)) {
- result->setFillType(SkPath::kInverseWinding_FillType);
- }
- else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD)) {
- result->setFillType(SkPath::kInverseEvenOdd_FillType);
- }
- Json::Value verbs = path[SKDEBUGCANVAS_ATTRIBUTE_VERBS];
- for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
- Json::Value verb = verbs[i];
- if (verb.isString()) {
- SkASSERT(!strcmp(verb.asCString(), SKDEBUGCANVAS_VERB_CLOSE));
- result->close();
- }
- else {
- if (verb.isMember(SKDEBUGCANVAS_VERB_MOVE)) {
- Json::Value move = verb[SKDEBUGCANVAS_VERB_MOVE];
- result->moveTo(move[0].asFloat(), move[1].asFloat());
- }
- else if (verb.isMember(SKDEBUGCANVAS_VERB_LINE)) {
- Json::Value line = verb[SKDEBUGCANVAS_VERB_LINE];
- result->lineTo(line[0].asFloat(), line[1].asFloat());
- }
- else if (verb.isMember(SKDEBUGCANVAS_VERB_QUAD)) {
- Json::Value quad = verb[SKDEBUGCANVAS_VERB_QUAD];
- result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
- quad[1][0].asFloat(), quad[1][1].asFloat());
- }
- else if (verb.isMember(SKDEBUGCANVAS_VERB_CUBIC)) {
- Json::Value cubic = verb[SKDEBUGCANVAS_VERB_CUBIC];
- result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
- cubic[1][0].asFloat(), cubic[1][1].asFloat(),
- cubic[2][0].asFloat(), cubic[2][1].asFloat());
- }
- else if (verb.isMember(SKDEBUGCANVAS_VERB_CONIC)) {
- Json::Value conic = verb[SKDEBUGCANVAS_VERB_CONIC];
- result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
- conic[1][0].asFloat(), conic[1][1].asFloat(),
- conic[2].asFloat());
- }
- else {
- SkASSERT(false);
- }
- }
- }
-}
-
-SkClipOp get_json_clipop(Json::Value& jsonOp) {
- const char* op = jsonOp.asCString();
- if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_DIFFERENCE)) {
- return kDifference_SkClipOp;
- }
- else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_INTERSECT)) {
- return kIntersect_SkClipOp;
- }
- else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_UNION)) {
- return kUnion_SkClipOp;
- }
- else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_XOR)) {
- return kXOR_SkClipOp;
- }
- else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
- return kReverseDifference_SkClipOp;
- }
- else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REPLACE)) {
- return kReplace_SkClipOp;
- }
- SkASSERT(false);
- return kIntersect_SkClipOp;
-}
-
-SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kDrawClear_OpType) {
- fColor = color;
- fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
-}
-
-void SkClearCommand::execute(SkCanvas* canvas) const {
- canvas->clear(fColor);
-}
-
-Json::Value SkClearCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = MakeJsonColor(fColor);
- return result;
-}
-
- SkClearCommand* SkClearCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
- Json::Value color = command[SKDEBUGCANVAS_ATTRIBUTE_COLOR];
- return new SkClearCommand(get_json_color(color));
-}
-
-SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
- : INHERITED(kClipPath_OpType) {
- fPath = path;
- fOp = op;
- fDoAA = doAA;
-
- fInfo.push(SkObjectParser::PathToString(path));
- fInfo.push(SkObjectParser::ClipOpToString(op));
- fInfo.push(SkObjectParser::BoolToString(doAA));
-}
-
-void SkClipPathCommand::execute(SkCanvas* canvas) const {
- canvas->clipPath(fPath, fOp, fDoAA);
-}
-
-bool SkClipPathCommand::render(SkCanvas* canvas) const {
- render_path(canvas, fPath);
- return true;
-}
-
-Json::Value SkClipPathCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = MakeJsonPath(fPath);
- result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
- result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = fDoAA;
- return result;
-}
-
-SkClipPathCommand* SkClipPathCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkPath path;
- extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
- return new SkClipPathCommand(path, get_json_clipop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
- command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
-}
-
-SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkClipOp op)
- : INHERITED(kClipRegion_OpType) {
- fRegion = region;
- fOp = op;
-
- fInfo.push(SkObjectParser::RegionToString(region));
- fInfo.push(SkObjectParser::ClipOpToString(op));
-}
-
-void SkClipRegionCommand::execute(SkCanvas* canvas) const {
- canvas->clipRegion(fRegion, fOp);
-}
-
-Json::Value SkClipRegionCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_REGION] = MakeJsonRegion(fRegion);
- result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
- return result;
-}
-
-SkClipRegionCommand* SkClipRegionCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkASSERT(false);
- return nullptr;
-}
-
-SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
- : INHERITED(kClipRect_OpType) {
- fRect = rect;
- fOp = op;
- fDoAA = doAA;
-
- fInfo.push(SkObjectParser::RectToString(rect));
- fInfo.push(SkObjectParser::ClipOpToString(op));
- fInfo.push(SkObjectParser::BoolToString(doAA));
-}
-
-void SkClipRectCommand::execute(SkCanvas* canvas) const {
- canvas->clipRect(fRect, fOp, fDoAA);
-}
-
-Json::Value SkClipRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(fRect);
- result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
- result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
-
- SkString desc;
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, fRect)->c_str());
-
- return result;
-}
-
-SkClipRectCommand* SkClipRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRect rect;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rect);
- return new SkClipRectCommand(rect, get_json_clipop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
- command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
-}
-
-SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
- : INHERITED(kClipRRect_OpType) {
- fRRect = rrect;
- fOp = op;
- fDoAA = doAA;
-
- fInfo.push(SkObjectParser::RRectToString(rrect));
- fInfo.push(SkObjectParser::ClipOpToString(op));
- fInfo.push(SkObjectParser::BoolToString(doAA));
-}
-
-void SkClipRRectCommand::execute(SkCanvas* canvas) const {
- canvas->clipRRect(fRRect, fOp, fDoAA);
-}
-
-bool SkClipRRectCommand::render(SkCanvas* canvas) const {
- render_rrect(canvas, fRRect);
- return true;
-}
-
-Json::Value SkClipRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
- result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
- result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
- return result;
-}
-
-SkClipRRectCommand* SkClipRRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRRect rrect;
- extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rrect);
- return new SkClipRRectCommand(rrect,
- get_json_clipop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
- command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
-}
-
-SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
- : INHERITED(kConcat_OpType) {
- fMatrix = matrix;
-
- fInfo.push(SkObjectParser::MatrixToString(matrix));
-}
-
-void SkConcatCommand::execute(SkCanvas* canvas) const {
- canvas->concat(fMatrix);
-}
-
-Json::Value SkConcatCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = MakeJsonMatrix(fMatrix);
- return result;
-}
-
-SkConcatCommand* SkConcatCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
- SkMatrix matrix;
- extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
- return new SkConcatCommand(matrix);
-}
-
-////
-
-SkDrawAnnotationCommand::SkDrawAnnotationCommand(const SkRect& rect, const char key[],
- sk_sp<SkData> value)
- : INHERITED(kDrawAnnotation_OpType)
- , fRect(rect)
- , fKey(key)
- , fValue(std::move(value))
-{
- SkString str;
- str.appendf("Key: %s Value: ", key);
- if (fValue && fValue->size()) {
- str.append((const char*) fValue->bytes(), fValue->size());
- } else {
- str.appendf("no value");
- }
- str.appendf("\n");
- fInfo.push(new SkString(str));
-}
-
-void SkDrawAnnotationCommand::execute(SkCanvas* canvas) const {
- canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
-}
-
-Json::Value SkDrawAnnotationCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
-
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(fRect);
- result["key"] = Json::Value(fKey.c_str());
- if (fValue.get()) {
- // TODO: dump out the "value"
- }
-
- SkString desc;
- str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(desc.c_str());
-
- return result;
-}
-
-SkDrawAnnotationCommand* SkDrawAnnotationCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRect rect;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rect);
- sk_sp<SkData> data(nullptr); // TODO: extract "value" from the Json
- return new SkDrawAnnotationCommand(rect, command["key"].asCString(), data);
-}
-
-////
-
-SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint)
- : INHERITED(kDrawBitmap_OpType) {
- fBitmap = bitmap;
- fLeft = left;
- fTop = top;
- if (paint) {
- fPaint = *paint;
- fPaintPtr = &fPaint;
- } else {
- fPaintPtr = nullptr;
- }
-
- fInfo.push(SkObjectParser::BitmapToString(bitmap));
- fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
- fInfo.push(SkObjectParser::ScalarToString(top, "SkScalar top: "));
- if (paint) {
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
-}
-
-void SkDrawBitmapCommand::execute(SkCanvas* canvas) const {
- canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
-}
-
-bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
- render_bitmap(canvas, fBitmap);
- return true;
-}
-
-Json::Value SkDrawBitmapCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(fBitmap, &encoded, urlDataManager)) {
- Json::Value command(Json::objectValue);
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonPoint(fLeft, fTop);
- if (fPaintPtr != nullptr) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaintPtr, urlDataManager);
- }
- }
- return result;
-}
-
-SkDrawBitmapCommand* SkDrawBitmapCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
- if (bitmap == nullptr) {
- return nullptr;
- }
- Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
- SkPaint* paintPtr;
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- paintPtr = &paint;
- }
- else {
- paintPtr = nullptr;
- }
- SkDrawBitmapCommand* result = new SkDrawBitmapCommand(*bitmap, point[0].asFloat(),
- point[1].asFloat(), paintPtr);
- delete bitmap;
- return result;
-}
-
-SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint)
- : INHERITED(kDrawBitmapNine_OpType) {
- fBitmap = bitmap;
- fCenter = center;
- fDst = dst;
- if (paint) {
- fPaint = *paint;
- fPaintPtr = &fPaint;
- } else {
- fPaintPtr = nullptr;
- }
-
- fInfo.push(SkObjectParser::BitmapToString(bitmap));
- fInfo.push(SkObjectParser::IRectToString(center));
- fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
- if (paint) {
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
-}
-
-void SkDrawBitmapNineCommand::execute(SkCanvas* canvas) const {
- canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
-}
-
-bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
- SkRect tmp = SkRect::Make(fCenter);
- render_bitmap(canvas, fBitmap, &tmp);
- return true;
-}
-
-Json::Value SkDrawBitmapNineCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(fBitmap, &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
- result[SKDEBUGCANVAS_ATTRIBUTE_CENTER] = MakeJsonIRect(fCenter);
- result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
- if (fPaintPtr != nullptr) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaintPtr, urlDataManager);
- }
- }
- return result;
-}
-
-SkDrawBitmapNineCommand* SkDrawBitmapNineCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
- if (bitmap == nullptr) {
- return nullptr;
- }
- SkIRect center;
- extract_json_irect(command[SKDEBUGCANVAS_ATTRIBUTE_CENTER], ¢er);
- SkRect dst;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
- SkPaint* paintPtr;
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- paintPtr = &paint;
- }
- else {
- paintPtr = nullptr;
- }
- SkDrawBitmapNineCommand* result = new SkDrawBitmapNineCommand(*bitmap, center, dst, paintPtr);
- delete bitmap;
- return result;
-}
-
-SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
- const SkRect& dst, const SkPaint* paint,
- SkCanvas::SrcRectConstraint constraint)
- : INHERITED(kDrawBitmapRect_OpType) {
- fBitmap = bitmap;
- if (src) {
- fSrc = *src;
- } else {
- fSrc.setEmpty();
- }
- fDst = dst;
-
- if (paint) {
- fPaint = *paint;
- fPaintPtr = &fPaint;
- } else {
- fPaintPtr = nullptr;
- }
- fConstraint = constraint;
-
- fInfo.push(SkObjectParser::BitmapToString(bitmap));
- if (src) {
- fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
- }
- fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
- if (paint) {
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
- fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
-}
-
-void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) const {
- canvas->legacy_drawBitmapRect(fBitmap, this->srcRect(), fDst, fPaintPtr, fConstraint);
-}
-
-bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
- render_bitmap(canvas, fBitmap, this->srcRect());
- return true;
-}
-
-Json::Value SkDrawBitmapRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(fBitmap, &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
- if (!fSrc.isEmpty()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = MakeJsonRect(fSrc);
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
- if (fPaintPtr != nullptr) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaintPtr, urlDataManager);
- }
- if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
- result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
- }
- }
-
- SkString desc;
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, fDst)->c_str());
-
- return result;
-}
-
-SkDrawBitmapRectCommand* SkDrawBitmapRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
- if (bitmap == nullptr) {
- return nullptr;
- }
- SkRect dst;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
- SkPaint* paintPtr;
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- paintPtr = &paint;
- }
- else {
- paintPtr = nullptr;
- }
- SkCanvas::SrcRectConstraint constraint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
- command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
- constraint = SkCanvas::kStrict_SrcRectConstraint;
- }
- else {
- constraint = SkCanvas::kFast_SrcRectConstraint;
- }
- SkRect* srcPtr;
- SkRect src;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
- srcPtr = &src;
- }
- else {
- srcPtr = nullptr;
- }
- SkDrawBitmapRectCommand* result = new SkDrawBitmapRectCommand(*bitmap, srcPtr, dst, paintPtr,
- constraint);
- delete bitmap;
- return result;
-}
-
-SkDrawImageCommand::SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top,
- const SkPaint* paint)
- : INHERITED(kDrawImage_OpType)
- , fImage(SkRef(image))
- , fLeft(left)
- , fTop(top) {
-
- fInfo.push(SkObjectParser::ImageToString(image));
- fInfo.push(SkObjectParser::ScalarToString(left, "Left: "));
- fInfo.push(SkObjectParser::ScalarToString(top, "Top: "));
-
- if (paint) {
- fPaint.set(*paint);
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
-}
-
-void SkDrawImageCommand::execute(SkCanvas* canvas) const {
- canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
-}
-
-bool SkDrawImageCommand::render(SkCanvas* canvas) const {
- SkAutoCanvasRestore acr(canvas, true);
- canvas->clear(0xFFFFFFFF);
-
- xlate_and_scale_to_bounds(canvas, SkRect::MakeXYWH(fLeft, fTop,
- SkIntToScalar(fImage->width()),
- SkIntToScalar(fImage->height())));
- this->execute(canvas);
- return true;
-}
-
-Json::Value SkDrawImageCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(*fImage, &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonPoint(fLeft, fTop);
- if (fPaint.isValid()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaint.get(), urlDataManager);
- }
-
- result[SKDEBUGCANVAS_ATTRIBUTE_UNIQUE_ID] = fImage->uniqueID();
- result[SKDEBUGCANVAS_ATTRIBUTE_WIDTH] = fImage->width();
- result[SKDEBUGCANVAS_ATTRIBUTE_HEIGHT] = fImage->height();
- switch (fImage->alphaType()) {
- case kOpaque_SkAlphaType:
- result[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
- break;
- case kPremul_SkAlphaType:
- result[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = SKDEBUGCANVAS_ALPHATYPE_PREMUL;
- break;
- case kUnpremul_SkAlphaType:
- result[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = SKDEBUGCANVAS_ALPHATYPE_UNPREMUL;
- break;
- default:
- result[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = SKDEBUGCANVAS_ALPHATYPE_UNKNOWN;
- break;
- }
- }
- return result;
-}
-
-SkDrawImageCommand* SkDrawImageCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- sk_sp<SkImage> image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
- if (image == nullptr) {
- return nullptr;
- }
- Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
- SkPaint* paintPtr;
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- paintPtr = &paint;
- }
- else {
- paintPtr = nullptr;
- }
- SkDrawImageCommand* result = new SkDrawImageCommand(image.get(), point[0].asFloat(),
- point[1].asFloat(), paintPtr);
- return result;
-}
-
-SkDrawImageLatticeCommand::SkDrawImageLatticeCommand(const SkImage* image,
- const SkCanvas::Lattice& lattice,
- const SkRect& dst, const SkPaint* paint)
- : INHERITED(kDrawImageLattice_OpType)
- , fImage(SkRef(image))
- , fLattice(lattice)
- , fDst(dst) {
-
- fInfo.push(SkObjectParser::ImageToString(image));
- fInfo.push(SkObjectParser::LatticeToString(lattice));
- fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
- if (paint) {
- fPaint.set(*paint);
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
-}
-
-void SkDrawImageLatticeCommand::execute(SkCanvas* canvas) const {
- SkLatticeIter iter(fLattice, fDst);
- SkRect srcR, dstR;
- while (iter.next(&srcR, &dstR)) {
- canvas->legacy_drawImageRect(fImage.get(), &srcR, dstR,
- fPaint.getMaybeNull(), SkCanvas::kStrict_SrcRectConstraint);
- }
-}
-
-bool SkDrawImageLatticeCommand::render(SkCanvas* canvas) const {
- SkAutoCanvasRestore acr(canvas, true);
- canvas->clear(0xFFFFFFFF);
-
- xlate_and_scale_to_bounds(canvas, fDst);
-
- this->execute(canvas);
- return true;
-}
-
-Json::Value SkDrawImageLatticeCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(*fImage.get(), &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
- result[SKDEBUGCANVAS_ATTRIBUTE_LATTICE] = MakeJsonLattice(fLattice);
- result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
- if (fPaint.isValid()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaint.get(), urlDataManager);
- }
- }
-
- SkString desc;
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, fDst)->c_str());
-
- return result;
-}
-
-SkDrawImageRectCommand::SkDrawImageRectCommand(const SkImage* image, const SkRect* src,
- const SkRect& dst, const SkPaint* paint,
- SkCanvas::SrcRectConstraint constraint)
- : INHERITED(kDrawImageRect_OpType)
- , fImage(SkRef(image))
- , fDst(dst)
- , fConstraint(constraint) {
-
- if (src) {
- fSrc.set(*src);
- }
-
- if (paint) {
- fPaint.set(*paint);
- }
-
- fInfo.push(SkObjectParser::ImageToString(image));
- if (src) {
- fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
- }
- fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
- if (paint) {
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
- fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
-}
-
-void SkDrawImageRectCommand::execute(SkCanvas* canvas) const {
- canvas->legacy_drawImageRect(fImage.get(), fSrc.getMaybeNull(), fDst,
- fPaint.getMaybeNull(), fConstraint);
-}
-
-bool SkDrawImageRectCommand::render(SkCanvas* canvas) const {
- SkAutoCanvasRestore acr(canvas, true);
- canvas->clear(0xFFFFFFFF);
-
- xlate_and_scale_to_bounds(canvas, fDst);
-
- this->execute(canvas);
- return true;
-}
-
-Json::Value SkDrawImageRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value encoded;
- if (flatten(*fImage.get(), &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
- if (fSrc.isValid()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = MakeJsonRect(*fSrc.get());
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
- if (fPaint.isValid()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaint.get(), urlDataManager);
- }
- if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
- result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
- }
- }
-
- SkString desc;
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, fDst)->c_str());
-
- return result;
-}
-
-SkDrawImageRectCommand* SkDrawImageRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- sk_sp<SkImage> image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
- if (image == nullptr) {
- return nullptr;
- }
- SkRect dst;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
- SkPaint* paintPtr;
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- paintPtr = &paint;
- }
- else {
- paintPtr = nullptr;
- }
- SkCanvas::SrcRectConstraint constraint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
- command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
- constraint = SkCanvas::kStrict_SrcRectConstraint;
- }
- else {
- constraint = SkCanvas::kFast_SrcRectConstraint;
- }
- SkRect* srcPtr;
- SkRect src;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
- srcPtr = &src;
- }
- else {
- srcPtr = nullptr;
- }
- SkDrawImageRectCommand* result = new SkDrawImageRectCommand(image.get(), srcPtr, dst, paintPtr,
- constraint);
- return result;
-}
-
-SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
- : INHERITED(kDrawOval_OpType) {
- fOval = oval;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::RectToString(oval));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawOvalCommand::execute(SkCanvas* canvas) const {
- canvas->drawOval(fOval, fPaint);
-}
-
-bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- xlate_and_scale_to_bounds(canvas, fOval);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawOval(fOval, p);
- canvas->restore();
-
- return true;
-}
-
-Json::Value SkDrawOvalCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(fOval);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawOvalCommand* SkDrawOvalCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRect coords;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawOvalCommand(coords, paint);
-}
-
-SkDrawArcCommand::SkDrawArcCommand(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
- bool useCenter, const SkPaint& paint)
- : INHERITED(kDrawOval_OpType) {
- fOval = oval;
- fStartAngle = startAngle;
- fSweepAngle = sweepAngle;
- fUseCenter = useCenter;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::RectToString(oval));
- fInfo.push(SkObjectParser::ScalarToString(startAngle, "StartAngle: "));
- fInfo.push(SkObjectParser::ScalarToString(sweepAngle, "SweepAngle: "));
- fInfo.push(SkObjectParser::BoolToString(useCenter));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawArcCommand::execute(SkCanvas* canvas) const {
- canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
-}
-
-bool SkDrawArcCommand::render(SkCanvas* canvas) const {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- xlate_and_scale_to_bounds(canvas, fOval);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
- canvas->restore();
-
- return true;
-}
-
-Json::Value SkDrawArcCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(fOval);
- result[SKDEBUGCANVAS_ATTRIBUTE_STARTANGLE] = MakeJsonScalar(fStartAngle);
- result[SKDEBUGCANVAS_ATTRIBUTE_SWEEPANGLE] = MakeJsonScalar(fSweepAngle);
- result[SKDEBUGCANVAS_ATTRIBUTE_USECENTER] = fUseCenter;
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawArcCommand* SkDrawArcCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRect coords;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
- SkScalar startAngle = command[SKDEBUGCANVAS_ATTRIBUTE_STARTANGLE].asFloat();
- SkScalar sweepAngle = command[SKDEBUGCANVAS_ATTRIBUTE_SWEEPANGLE].asFloat();
- bool useCenter = command[SKDEBUGCANVAS_ATTRIBUTE_USECENTER].asBool();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawArcCommand(coords, startAngle, sweepAngle, useCenter, paint);
-}
-
-SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
- : INHERITED(kDrawPaint_OpType) {
- fPaint = paint;
-
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPaintCommand::execute(SkCanvas* canvas) const {
- canvas->drawPaint(fPaint);
-}
-
-bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
- canvas->clear(0xFFFFFFFF);
- canvas->drawPaint(fPaint);
- return true;
-}
-
-Json::Value SkDrawPaintCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawPaintCommand* SkDrawPaintCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawPaintCommand(paint);
-}
-
-SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
- : INHERITED(kDrawPath_OpType) {
- fPath = path;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::PathToString(path));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPathCommand::execute(SkCanvas* canvas) const {
- canvas->drawPath(fPath, fPaint);
-}
-
-bool SkDrawPathCommand::render(SkCanvas* canvas) const {
- render_path(canvas, fPath);
- return true;
-}
-
-Json::Value SkDrawPathCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = MakeJsonPath(fPath);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawPathCommand* SkDrawPathCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkPath path;
- extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawPathCommand(path, paint);
-}
-
-SkBeginDrawPictureCommand::SkBeginDrawPictureCommand(const SkPicture* picture,
- const SkMatrix* matrix,
- const SkPaint* paint)
- : INHERITED(kBeginDrawPicture_OpType)
- , fPicture(SkRef(picture)) {
-
- SkString* str = new SkString;
- str->appendf("SkPicture: L: %f T: %f R: %f B: %f",
- picture->cullRect().fLeft, picture->cullRect().fTop,
- picture->cullRect().fRight, picture->cullRect().fBottom);
- fInfo.push(str);
-
- if (matrix) {
- fMatrix.set(*matrix);
- fInfo.push(SkObjectParser::MatrixToString(*matrix));
- }
-
- if (paint) {
- fPaint.set(*paint);
- fInfo.push(SkObjectParser::PaintToString(*paint));
- }
-
-}
-
-void SkBeginDrawPictureCommand::execute(SkCanvas* canvas) const {
- if (fPaint.isValid()) {
- SkRect bounds = fPicture->cullRect();
- if (fMatrix.isValid()) {
- fMatrix.get()->mapRect(&bounds);
- }
- canvas->saveLayer(&bounds, fPaint.get());
- }
-
- if (fMatrix.isValid()) {
- if (!fPaint.isValid()) {
- canvas->save();
- }
- canvas->concat(*fMatrix.get());
- }
-}
-
-bool SkBeginDrawPictureCommand::render(SkCanvas* canvas) const {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
-
- canvas->drawPicture(fPicture.get());
-
- canvas->restore();
-
- return true;
-}
-
-SkEndDrawPictureCommand::SkEndDrawPictureCommand(bool restore)
- : INHERITED(kEndDrawPicture_OpType) , fRestore(restore) { }
-
-void SkEndDrawPictureCommand::execute(SkCanvas* canvas) const {
- if (fRestore) {
- canvas->restore();
- }
-}
-
-SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
- const SkPoint pts[], const SkPaint& paint)
- : INHERITED(kDrawPoints_OpType) {
- fMode = mode;
- fCount = count;
- fPts = new SkPoint[count];
- memcpy(fPts, pts, count * sizeof(SkPoint));
- fPaint = paint;
-
- fInfo.push(SkObjectParser::PointsToString(pts, count));
- fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
- "Points: "));
- fInfo.push(SkObjectParser::PointModeToString(mode));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPointsCommand::execute(SkCanvas* canvas) const {
- canvas->drawPoints(fMode, fCount, fPts, fPaint);
-}
-
-bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
- canvas->clear(0xFFFFFFFF);
- canvas->save();
-
- SkRect bounds;
-
- bounds.setEmpty();
- for (unsigned int i = 0; i < fCount; ++i) {
- bounds.growToInclude(fPts[i].fX, fPts[i].fY);
- }
-
- xlate_and_scale_to_bounds(canvas, bounds);
-
- SkPaint p;
- p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
-
- canvas->drawPoints(fMode, fCount, fPts, p);
- canvas->restore();
-
- return true;
-}
-
-Json::Value SkDrawPointsCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_MODE] = make_json_pointmode(fMode);
- Json::Value points(Json::arrayValue);
- for (size_t i = 0; i < fCount; i++) {
- points.append(MakeJsonPoint(fPts[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_POINTS] = points;
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawPointsCommand* SkDrawPointsCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkCanvas::PointMode mode;
- const char* jsonMode = command[SKDEBUGCANVAS_ATTRIBUTE_MODE].asCString();
- if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POINTS)) {
- mode = SkCanvas::kPoints_PointMode;
- }
- else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_LINES)) {
- mode = SkCanvas::kLines_PointMode;
- }
- else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POLYGON)) {
- mode = SkCanvas::kPolygon_PointMode;
- }
- else {
- SkASSERT(false);
- return nullptr;
- }
- Json::Value jsonPoints = command[SKDEBUGCANVAS_ATTRIBUTE_POINTS];
- int count = (int) jsonPoints.size();
- SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
- for (int i = 0; i < count; i++) {
- points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
- }
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- SkDrawPointsCommand* result = new SkDrawPointsCommand(mode, count, points, paint);
- sk_free(points);
- return result;
-}
-
-SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint)
- : INHERITED(kDrawPosText_OpType) {
- size_t numPts = paint.countText(text, byteLength);
-
- fText = new char[byteLength];
- memcpy(fText, text, byteLength);
- fByteLength = byteLength;
-
- fPos = new SkPoint[numPts];
- memcpy(fPos, pos, numPts * sizeof(SkPoint));
-
- fPaint = paint;
-
- fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
- // TODO(chudy): Test that this works.
- fInfo.push(SkObjectParser::PointsToString(pos, 1));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPosTextCommand::execute(SkCanvas* canvas) const {
- canvas->drawPosText(fText, fByteLength, fPos, fPaint);
-}
-
-Json::Value SkDrawPosTextCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
- ((const char*) fText) + fByteLength);
- Json::Value coords(Json::arrayValue);
- size_t numCoords = fPaint.textToGlyphs(fText, fByteLength, nullptr);
- for (size_t i = 0; i < numCoords; i++) {
- coords.append(MakeJsonPoint(fPos[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = coords;
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawPosTextCommand* SkDrawPosTextCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
- int count = (int) coords.size();
- SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
- for (int i = 0; i < count; i++) {
- points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
- }
- return new SkDrawPosTextCommand(text, strlen(text), points, paint);
-}
-
-SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint)
- : INHERITED(kDrawPosTextH_OpType) {
- size_t numPts = paint.countText(text, byteLength);
-
- fText = new char[byteLength];
- memcpy(fText, text, byteLength);
- fByteLength = byteLength;
-
- fXpos = new SkScalar[numPts];
- memcpy(fXpos, xpos, numPts * sizeof(SkScalar));
-
- fConstY = constY;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
- fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
- fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPosTextHCommand::execute(SkCanvas* canvas) const {
- canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
-}
-
-Json::Value SkDrawPosTextHCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
- ((const char*) fText) + fByteLength);
- result[SKDEBUGCANVAS_ATTRIBUTE_Y] = Json::Value(fConstY);
- Json::Value xpos(Json::arrayValue);
- size_t numXpos = fPaint.textToGlyphs(fText, fByteLength, nullptr);
- for (size_t i = 0; i < numXpos; i++) {
- xpos.append(Json::Value(fXpos[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS] = xpos;
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawPosTextHCommand* SkDrawPosTextHCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- Json::Value jsonXpos = command[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS];
- int count = (int) jsonXpos.size();
- SkScalar* xpos = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
- for (int i = 0; i < count; i++) {
- xpos[i] = jsonXpos[i].asFloat();
- }
- SkScalar y = command[SKDEBUGCANVAS_ATTRIBUTE_Y].asFloat();
- return new SkDrawPosTextHCommand(text, strlen(text), xpos, y, paint);
-}
-
-static const char* gPositioningLabels[] = {
- "kDefault_Positioning",
- "kHorizontal_Positioning",
- "kFull_Positioning",
-};
-
-SkDrawTextBlobCommand::SkDrawTextBlobCommand(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y,
- const SkPaint& paint)
- : INHERITED(kDrawTextBlob_OpType)
- , fBlob(std::move(blob))
- , fXPos(x)
- , fYPos(y)
- , fPaint(paint) {
-
- std::unique_ptr<SkString> runsStr(new SkString);
- fInfo.push(SkObjectParser::ScalarToString(x, "XPOS: "));
- fInfo.push(SkObjectParser::ScalarToString(y, "YPOS: "));
- fInfo.push(SkObjectParser::RectToString(fBlob->bounds(), "Bounds: "));
- fInfo.push(runsStr.get());
- fInfo.push(SkObjectParser::PaintToString(paint));
-
- unsigned runs = 0;
- SkPaint runPaint(paint);
- SkTextBlobRunIterator iter(fBlob.get());
- while (!iter.done()) {
- std::unique_ptr<SkString> tmpStr(new SkString);
- tmpStr->printf("==== Run [%d] ====", runs++);
- fInfo.push(tmpStr.release());
-
- fInfo.push(SkObjectParser::IntToString(iter.glyphCount(), "GlyphCount: "));
- tmpStr.reset(new SkString("GlyphPositioning: "));
- tmpStr->append(gPositioningLabels[iter.positioning()]);
- fInfo.push(tmpStr.release());
-
- iter.applyFontToPaint(&runPaint);
- fInfo.push(SkObjectParser::PaintToString(runPaint));
-
- iter.next();
- }
-
- runsStr->printf("Runs: %d", runs);
- // runStr is owned by fInfo at this point.
- runsStr.release();
-}
-
-void SkDrawTextBlobCommand::execute(SkCanvas* canvas) const {
- canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
-}
-
-bool SkDrawTextBlobCommand::render(SkCanvas* canvas) const {
- canvas->clear(SK_ColorWHITE);
- canvas->save();
-
- SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
- xlate_and_scale_to_bounds(canvas, bounds);
-
- canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
-
- canvas->restore();
-
- return true;
-}
-
-Json::Value SkDrawTextBlobCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value runs(Json::arrayValue);
- SkTextBlobRunIterator iter(fBlob.get());
- while (!iter.done()) {
- Json::Value run(Json::objectValue);
- Json::Value jsonPositions(Json::arrayValue);
- Json::Value jsonGlyphs(Json::arrayValue);
- const SkScalar* iterPositions = iter.pos();
- const uint16_t* iterGlyphs = iter.glyphs();
- for (uint32_t i = 0; i < iter.glyphCount(); i++) {
- switch (iter.positioning()) {
- case SkTextBlob::kFull_Positioning:
- jsonPositions.append(MakeJsonPoint(iterPositions[i * 2],
- iterPositions[i * 2 + 1]));
- break;
- case SkTextBlob::kHorizontal_Positioning:
- jsonPositions.append(Json::Value(iterPositions[i]));
- break;
- case SkTextBlob::kDefault_Positioning:
- break;
- }
- jsonGlyphs.append(Json::Value(iterGlyphs[i]));
- }
- if (iter.positioning() != SkTextBlob::kDefault_Positioning) {
- run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS] = jsonPositions;
- }
- run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS] = jsonGlyphs;
- SkPaint fontPaint;
- iter.applyFontToPaint(&fontPaint);
- run[SKDEBUGCANVAS_ATTRIBUTE_FONT] = MakeJsonPaint(fontPaint, urlDataManager);
- run[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonPoint(iter.offset());
- runs.append(run);
- iter.next();
- }
- SkRect bounds = fBlob->bounds();
- result[SKDEBUGCANVAS_ATTRIBUTE_RUNS] = runs;
- result[SKDEBUGCANVAS_ATTRIBUTE_X] = Json::Value(fXPos);
- result[SKDEBUGCANVAS_ATTRIBUTE_Y] = Json::Value(fYPos);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(bounds);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
-
- SkString desc;
- // make the bounds local by applying the x,y
- bounds.offset(fXPos, fYPos);
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, bounds)->c_str());
-
- return result;
-}
-
-SkDrawTextBlobCommand* SkDrawTextBlobCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkTextBlobBuilder builder;
- Json::Value runs = command[SKDEBUGCANVAS_ATTRIBUTE_RUNS];
- for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) {
- Json::Value run = runs[i];
- SkPaint font;
- font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- extract_json_paint(run[SKDEBUGCANVAS_ATTRIBUTE_FONT], urlDataManager, &font);
- Json::Value glyphs = run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS];
- int count = glyphs.size();
- Json::Value coords = run[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
- SkScalar x = coords[0].asFloat();
- SkScalar y = coords[1].asFloat();
- SkRect bounds;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &bounds);
-
- if (run.isMember(SKDEBUGCANVAS_ATTRIBUTE_POSITIONS)) {
- Json::Value positions = run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS];
- if (positions.size() > 0 && positions[0].isNumeric()) {
- SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y, &bounds);
- for (int j = 0; j < count; j++) {
- buffer.glyphs[j] = glyphs[j].asUInt();
- buffer.pos[j] = positions[j].asFloat();
- }
- }
- else {
- SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count, &bounds);
- for (int j = 0; j < count; j++) {
- buffer.glyphs[j] = glyphs[j].asUInt();
- buffer.pos[j * 2] = positions[j][0].asFloat();
- buffer.pos[j * 2 + 1] = positions[j][1].asFloat();
- }
- }
- }
- else {
- SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y, &bounds);
- for (int j = 0; j < count; j++) {
- buffer.glyphs[j] = glyphs[j].asUInt();
- }
- }
- }
- SkScalar x = command[SKDEBUGCANVAS_ATTRIBUTE_X].asFloat();
- SkScalar y = command[SKDEBUGCANVAS_ATTRIBUTE_Y].asFloat();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawTextBlobCommand(builder.make(), x, y, paint);
-}
-
-SkDrawPatchCommand::SkDrawPatchCommand(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkBlendMode bmode,
- const SkPaint& paint)
- : INHERITED(kDrawPatch_OpType)
- , fBlendMode(bmode)
-{
- memcpy(fCubics, cubics, sizeof(fCubics));
- if (colors != nullptr) {
- memcpy(fColors, colors, sizeof(fColors));
- fColorsPtr = fColors;
- } else {
- fColorsPtr = nullptr;
- }
- if (texCoords != nullptr) {
- memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
- fTexCoordsPtr = fTexCoords;
- } else {
- fTexCoordsPtr = nullptr;
- }
- fPaint = paint;
-
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawPatchCommand::execute(SkCanvas* canvas) const {
- canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
-}
-
-Json::Value SkDrawPatchCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- Json::Value cubics = Json::Value(Json::arrayValue);
- for (int i = 0; i < 12; i++) {
- cubics.append(MakeJsonPoint(fCubics[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_CUBICS] = cubics;
- if (fColorsPtr != nullptr) {
- Json::Value colors = Json::Value(Json::arrayValue);
- for (int i = 0; i < 4; i++) {
- colors.append(MakeJsonColor(fColorsPtr[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_COLORS] = colors;
- }
- if (fTexCoordsPtr != nullptr) {
- Json::Value texCoords = Json::Value(Json::arrayValue);
- for (int i = 0; i < 4; i++) {
- texCoords.append(MakeJsonPoint(fTexCoords[i]));
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS] = texCoords;
- }
- // fBlendMode
- return result;
-}
-
-SkDrawPatchCommand* SkDrawPatchCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- Json::Value jsonCubics = command[SKDEBUGCANVAS_ATTRIBUTE_CUBICS];
- SkPoint cubics[12];
- for (int i = 0; i < 12; i++) {
- cubics[i] = get_json_point(jsonCubics[i]);
- }
- SkColor* colorsPtr;
- SkColor colors[4];
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORS)) {
- Json::Value jsonColors = command[SKDEBUGCANVAS_ATTRIBUTE_COLORS];
- for (int i = 0; i < 4; i++) {
- colors[i] = get_json_color(jsonColors[i]);
- }
- colorsPtr = colors;
- }
- else {
- colorsPtr = nullptr;
- }
- SkPoint* texCoordsPtr;
- SkPoint texCoords[4];
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS)) {
- Json::Value jsonTexCoords = command[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS];
- for (int i = 0; i < 4; i++) {
- texCoords[i] = get_json_point(jsonTexCoords[i]);
- }
- texCoordsPtr = texCoords;
- }
- else {
- texCoordsPtr = nullptr;
- }
-
- SkBlendMode bmode = SkBlendMode::kSrcOver; // TODO: extract from json
-
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawPatchCommand(cubics, colorsPtr, texCoordsPtr, bmode, paint);
-}
-
-SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
- : INHERITED(kDrawRect_OpType) {
- fRect = rect;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::RectToString(rect));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawRectCommand::execute(SkCanvas* canvas) const {
- canvas->drawRect(fRect, fPaint);
-}
-
-Json::Value SkDrawRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonRect(fRect);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
-
- SkString desc;
- result[SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC] = Json::Value(str_append(&desc, fRect)->c_str());
-
- return result;
-}
-
-SkDrawRectCommand* SkDrawRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRect coords;
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawRectCommand(coords, paint);
-}
-
-SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
- : INHERITED(kDrawRRect_OpType) {
- fRRect = rrect;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::RRectToString(rrect));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawRRectCommand::execute(SkCanvas* canvas) const {
- canvas->drawRRect(fRRect, fPaint);
-}
-
-bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
- render_rrect(canvas, fRRect);
- return true;
-}
-
-Json::Value SkDrawRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawRRectCommand* SkDrawRRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRRect coords;
- extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawRRectCommand(coords, paint);
-}
-
-SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
- const SkRRect& inner,
- const SkPaint& paint)
- : INHERITED(kDrawDRRect_OpType) {
- fOuter = outer;
- fInner = inner;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::RRectToString(outer));
- fInfo.push(SkObjectParser::RRectToString(inner));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawDRRectCommand::execute(SkCanvas* canvas) const {
- canvas->drawDRRect(fOuter, fInner, fPaint);
-}
-
-bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
- render_drrect(canvas, fOuter, fInner);
- return true;
-}
-
-Json::Value SkDrawDRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_OUTER] = make_json_rrect(fOuter);
- result[SKDEBUGCANVAS_ATTRIBUTE_INNER] = make_json_rrect(fInner);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawDRRectCommand* SkDrawDRRectCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkRRect outer;
- extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &outer);
- SkRRect inner;
- extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &inner);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- return new SkDrawDRRectCommand(outer, inner, paint);
-}
-
-SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint)
- : INHERITED(kDrawText_OpType) {
- fText = new char[byteLength];
- memcpy(fText, text, byteLength);
- fByteLength = byteLength;
- fX = x;
- fY = y;
- fPaint = paint;
-
- fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
- fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
- fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawTextCommand::execute(SkCanvas* canvas) const {
- canvas->drawText(fText, fByteLength, fX, fY, fPaint);
-}
-
-Json::Value SkDrawTextCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
- ((const char*) fText) + fByteLength);
- Json::Value coords(Json::arrayValue);
- result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = MakeJsonPoint(fX, fY);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawTextCommand* SkDrawTextCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
- return new SkDrawTextCommand(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(),
- paint);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint)
- : INHERITED(kDrawTextOnPath_OpType) {
- fText = new char[byteLength];
- memcpy(fText, text, byteLength);
- fByteLength = byteLength;
- fPath = path;
- if (matrix) {
- fMatrix = *matrix;
- } else {
- fMatrix.setIdentity();
- }
- fPaint = paint;
-
- fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
- fInfo.push(SkObjectParser::PathToString(path));
- if (matrix) {
- fInfo.push(SkObjectParser::MatrixToString(*matrix));
- }
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawTextOnPathCommand::execute(SkCanvas* canvas) const {
- canvas->drawTextOnPath(fText, fByteLength, fPath,
- fMatrix.isIdentity() ? nullptr : &fMatrix,
- fPaint);
-}
-
-Json::Value SkDrawTextOnPathCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
- ((const char*) fText) + fByteLength);
- Json::Value coords(Json::arrayValue);
- result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = MakeJsonPath(fPath);
- if (!fMatrix.isIdentity()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = MakeJsonMatrix(fMatrix);
- }
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawTextOnPathCommand* SkDrawTextOnPathCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- SkPath path;
- extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
- SkMatrix* matrixPtr;
- SkMatrix matrix;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_MATRIX)) {
- extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
- matrixPtr = &matrix;
- }
- else {
- matrixPtr = nullptr;
- }
- return new SkDrawTextOnPathCommand(text, strlen(text), path, matrixPtr, paint);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-SkDrawTextRSXformCommand::SkDrawTextRSXformCommand(const void* text, size_t byteLength,
- const SkRSXform xform[], const SkRect* cull,
- const SkPaint& paint)
- : INHERITED(kDrawTextRSXform_OpType)
-{
- fText = new char[byteLength];
- memcpy(fText, text, byteLength);
- fByteLength = byteLength;
- int count = paint.countText(text, byteLength);
- fXform = new SkRSXform[count];
- memcpy(fXform, xform, count * sizeof(SkRSXform));
- if (cull) {
- fCullStorage = *cull;
- fCull = &fCullStorage;
- } else {
- fCull = nullptr;
- }
- fPaint = paint;
-
- fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawTextRSXformCommand::execute(SkCanvas* canvas) const {
- canvas->drawTextRSXform(fText, fByteLength, fXform, fCull, fPaint);
-}
-
-Json::Value SkDrawTextRSXformCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
- ((const char*) fText) + fByteLength);
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
- return result;
-}
-
-SkDrawTextRSXformCommand* SkDrawTextRSXformCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
- size_t byteLength = strlen(text);
- SkPaint paint;
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
-
- // TODO: handle xform and cull
- int count = paint.countText(text, byteLength);
- SkAutoTArray<SkRSXform> xform(count);
- for (int i = 0; i < count; ++i) {
- xform[i].fSCos = 1;
- xform[i].fSSin = xform[i].fTx = xform[i].fTy = 0;
- }
- return new SkDrawTextRSXformCommand(text, byteLength, &xform[0], nullptr, paint);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-SkDrawVerticesCommand::SkDrawVerticesCommand(sk_sp<SkVertices> vertices, SkBlendMode bmode,
- const SkPaint& paint)
- : INHERITED(kDrawVertices_OpType)
- , fVertices(std::move(vertices))
- , fBlendMode(bmode)
- , fPaint(paint)
-{
- // TODO(chudy)
- fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
- fInfo.push(SkObjectParser::PaintToString(paint));
-}
-
-void SkDrawVerticesCommand::execute(SkCanvas* canvas) const {
- canvas->drawVertices(fVertices, fBlendMode, fPaint);
-}
-
-SkRestoreCommand::SkRestoreCommand()
- : INHERITED(kRestore_OpType) {
- fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
-}
-
-void SkRestoreCommand::execute(SkCanvas* canvas) const {
- canvas->restore();
-}
-
-SkRestoreCommand* SkRestoreCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
- return new SkRestoreCommand();
-}
-
-SkSaveCommand::SkSaveCommand()
- : INHERITED(kSave_OpType) {
-}
-
-void SkSaveCommand::execute(SkCanvas* canvas) const {
- canvas->save();
-}
-
-SkSaveCommand* SkSaveCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
- return new SkSaveCommand();
-}
-
-SkSaveLayerCommand::SkSaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
- : INHERITED(kSaveLayer_OpType) {
- if (rec.fBounds) {
- fBounds = *rec.fBounds;
- } else {
- fBounds.setEmpty();
- }
-
- if (rec.fPaint) {
- fPaint = *rec.fPaint;
- fPaintPtr = &fPaint;
- } else {
- fPaintPtr = nullptr;
- }
- fSaveLayerFlags = rec.fSaveLayerFlags;
-
- if (rec.fBackdrop) {
- fBackdrop = rec.fBackdrop;
- fBackdrop->ref();
- } else {
- fBackdrop = nullptr;
- }
-
- if (rec.fBounds) {
- fInfo.push(SkObjectParser::RectToString(*rec.fBounds, "Bounds: "));
- }
- if (rec.fPaint) {
- fInfo.push(SkObjectParser::PaintToString(*rec.fPaint));
- }
- fInfo.push(SkObjectParser::SaveLayerFlagsToString(fSaveLayerFlags));
-}
-
-SkSaveLayerCommand::~SkSaveLayerCommand() {
- if (fBackdrop != nullptr) {
- fBackdrop->unref();
- }
-}
-
-void SkSaveLayerCommand::execute(SkCanvas* canvas) const {
- canvas->saveLayer(SkCanvas::SaveLayerRec(fBounds.isEmpty() ? nullptr : &fBounds,
- fPaintPtr,
- fSaveLayerFlags));
-}
-
-void SkSaveLayerCommand::vizExecute(SkCanvas* canvas) const {
- canvas->save();
-}
-
-Json::Value SkSaveLayerCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- if (!fBounds.isEmpty()) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS] = MakeJsonRect(fBounds);
- }
- if (fPaintPtr != nullptr) {
- result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaintPtr,
- urlDataManager);
- }
- if (fBackdrop != nullptr) {
- Json::Value jsonBackdrop;
- flatten(fBackdrop, &jsonBackdrop, urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP] = jsonBackdrop;
- }
- if (fSaveLayerFlags != 0) {
- SkDebugf("unsupported: saveLayer flags\n");
- SkASSERT(false);
- }
- return result;
-}
-
-SkSaveLayerCommand* SkSaveLayerCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkCanvas::SaveLayerRec rec;
- SkRect bounds;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BOUNDS)) {
- extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS], &bounds);
- rec.fBounds = &bounds;
- }
- SkPaint paint;
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
- extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
- rec.fPaint = &paint;
- }
- if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BACKDROP)) {
- Json::Value backdrop = command[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP];
- rec.fBackdrop = (SkImageFilter*) load_flattenable(backdrop, urlDataManager);
- }
- SkSaveLayerCommand* result = new SkSaveLayerCommand(rec);
- if (rec.fBackdrop != nullptr) {
- rec.fBackdrop->unref();
- }
- return result;
-}
-
-SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
- : INHERITED(kSetMatrix_OpType) {
- fUserMatrix.reset();
- fMatrix = matrix;
- fInfo.push(SkObjectParser::MatrixToString(matrix));
-}
-
-void SkSetMatrixCommand::setUserMatrix(const SkMatrix& userMatrix) {
- fUserMatrix = userMatrix;
-}
-
-void SkSetMatrixCommand::execute(SkCanvas* canvas) const {
- SkMatrix temp = SkMatrix::Concat(fUserMatrix, fMatrix);
- canvas->setMatrix(temp);
-}
-
-Json::Value SkSetMatrixCommand::toJSON(UrlDataManager& urlDataManager) const {
- Json::Value result = INHERITED::toJSON(urlDataManager);
- result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = MakeJsonMatrix(fMatrix);
- return result;
-}
-
-SkSetMatrixCommand* SkSetMatrixCommand::fromJSON(Json::Value& command,
- UrlDataManager& urlDataManager) {
- SkMatrix matrix;
- extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
- return new SkSetMatrixCommand(matrix);
-}
diff --git a/src/third_party/skia/tools/debugger/SkDrawCommand.h b/src/third_party/skia/tools/debugger/SkDrawCommand.h
deleted file mode 100644
index 654cbdd..0000000
--- a/src/third_party/skia/tools/debugger/SkDrawCommand.h
+++ /dev/null
@@ -1,766 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKDRAWCOMMAND_H_
-#define SKDRAWCOMMAND_H_
-
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkFlattenable.h"
-#include "SkTLazy.h"
-#include "SkPath.h"
-#include "SkRegion.h"
-#include "SkRRect.h"
-#include "SkRSXform.h"
-#include "SkString.h"
-#include "SkTDArray.h"
-#include "SkVertices.h"
-#include "SkJSONCPP.h"
-#include "UrlDataManager.h"
-
-class SkDrawCommand {
-public:
- enum OpType {
- kBeginDrawPicture_OpType,
- kClipPath_OpType,
- kClipRegion_OpType,
- kClipRect_OpType,
- kClipRRect_OpType,
- kConcat_OpType,
- kDrawAnnotation_OpType,
- kDrawBitmap_OpType,
- kDrawBitmapNine_OpType,
- kDrawBitmapRect_OpType,
- kDrawClear_OpType,
- kDrawDRRect_OpType,
- kDrawImage_OpType,
- kDrawImageLattice_OpType,
- kDrawImageRect_OpType,
- kDrawOval_OpType,
- kDrawPaint_OpType,
- kDrawPatch_OpType,
- kDrawPath_OpType,
- kDrawPoints_OpType,
- kDrawPosText_OpType,
- kDrawPosTextH_OpType,
- kDrawRect_OpType,
- kDrawRRect_OpType,
- kDrawText_OpType,
- kDrawTextBlob_OpType,
- kDrawTextOnPath_OpType,
- kDrawTextRSXform_OpType,
- kDrawVertices_OpType,
- kEndDrawPicture_OpType,
- kRestore_OpType,
- kSave_OpType,
- kSaveLayer_OpType,
- kSetMatrix_OpType,
-
- kLast_OpType = kSetMatrix_OpType
- };
-
- static const int kOpTypeCount = kLast_OpType + 1;
-
- static void WritePNG(const uint8_t* rgba, unsigned width, unsigned height,
- SkWStream& out, bool isOpaque);
-
- SkDrawCommand(OpType opType);
-
- virtual ~SkDrawCommand();
-
- virtual SkString toString() const;
-
- virtual const char* toCString() const {
- return GetCommandString(fOpType);
- }
-
- bool isVisible() const {
- return fVisible;
- }
-
- void setVisible(bool toggle) {
- fVisible = toggle;
- }
-
- const SkTDArray<SkString*>* Info() const { return &fInfo; }
- virtual void execute(SkCanvas*) const = 0;
- virtual void vizExecute(SkCanvas*) const {}
-
- virtual void setUserMatrix(const SkMatrix&) {}
-
- // The next "active" system is only used by save, saveLayer, and restore.
- // It is used to determine which saveLayers are currently active (at a
- // given point in the rendering).
- // saves just return a kPushLayer action but don't track active state
- // restores just return a kPopLayer action
- // saveLayers return kPushLayer but also track the active state
- enum Action {
- kNone_Action,
- kPopLayer_Action,
- kPushLayer_Action,
- };
- virtual Action action() const { return kNone_Action; }
- virtual void setActive(bool active) {}
- virtual bool active() const { return false; }
-
- OpType getType() const { return fOpType; }
-
- virtual bool render(SkCanvas* canvas) const { return false; }
-
- virtual Json::Value toJSON(UrlDataManager& urlDataManager) const;
-
- /* Converts a JSON representation of a command into a newly-allocated SkDrawCommand object. It
- * is the caller's responsibility to delete this object. This method may return null if an error
- * occurs.
- */
- static SkDrawCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
- static const char* GetCommandString(OpType type);
-
- // Helper methods for converting things to JSON
- static Json::Value MakeJsonColor(const SkColor color);
- static Json::Value MakeJsonColor4f(const SkColor4f& color);
- static Json::Value MakeJsonPoint(const SkPoint& point);
- static Json::Value MakeJsonPoint(SkScalar x, SkScalar y);
- static Json::Value MakeJsonRect(const SkRect& rect);
- static Json::Value MakeJsonIRect(const SkIRect&);
- static Json::Value MakeJsonMatrix(const SkMatrix&);
- static Json::Value MakeJsonScalar(SkScalar);
- static Json::Value MakeJsonPath(const SkPath& path);
- static Json::Value MakeJsonRegion(const SkRegion& region);
- static Json::Value MakeJsonPaint(const SkPaint& paint, UrlDataManager& urlDataManager);
- static Json::Value MakeJsonLattice(const SkCanvas::Lattice& lattice);
-
- static void flatten(const SkFlattenable* flattenable, Json::Value* target,
- UrlDataManager& urlDataManager);
- static bool flatten(const SkImage& image, Json::Value* target,
- UrlDataManager& urlDataManager);
- static bool flatten(const SkBitmap& bitmap, Json::Value* target,
- UrlDataManager& urlDataManager);
-
-protected:
- SkTDArray<SkString*> fInfo;
-
-private:
- OpType fOpType;
- bool fVisible;
-};
-
-class SkRestoreCommand : public SkDrawCommand {
-public:
- SkRestoreCommand();
- void execute(SkCanvas* canvas) const override;
- Action action() const override { return kPopLayer_Action; }
- static SkRestoreCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- typedef SkDrawCommand INHERITED;
-};
-
-class SkClearCommand : public SkDrawCommand {
-public:
- SkClearCommand(SkColor color);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkClearCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkColor fColor;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkClipPathCommand : public SkDrawCommand {
-public:
- SkClipPathCommand(const SkPath& path, SkClipOp op, bool doAA);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkClipPathCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkPath fPath;
- SkClipOp fOp;
- bool fDoAA;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkClipRegionCommand : public SkDrawCommand {
-public:
- SkClipRegionCommand(const SkRegion& region, SkClipOp op);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkClipRegionCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRegion fRegion;
- SkClipOp fOp;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkClipRectCommand : public SkDrawCommand {
-public:
- SkClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkClipRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
- const SkRect& rect() const { return fRect; }
- SkClipOp op() const { return fOp; }
- bool doAA() const { return fDoAA; }
-
-private:
- SkRect fRect;
- SkClipOp fOp;
- bool fDoAA;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkClipRRectCommand : public SkDrawCommand {
-public:
- SkClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkClipRRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
- const SkRRect& rrect() const { return fRRect; }
- SkClipOp op() const { return fOp; }
- bool doAA() const { return fDoAA; }
-
-private:
- SkRRect fRRect;
- SkClipOp fOp;
- bool fDoAA;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkConcatCommand : public SkDrawCommand {
-public:
- SkConcatCommand(const SkMatrix& matrix);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkConcatCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkMatrix fMatrix;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawAnnotationCommand : public SkDrawCommand {
-public:
- SkDrawAnnotationCommand(const SkRect&, const char key[], sk_sp<SkData> value);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawAnnotationCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRect fRect;
- SkString fKey;
- sk_sp<SkData> fValue;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawBitmapCommand : public SkDrawCommand {
-public:
- SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawBitmapCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkBitmap fBitmap;
- SkScalar fLeft;
- SkScalar fTop;
- SkPaint fPaint;
- SkPaint* fPaintPtr;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawBitmapNineCommand : public SkDrawCommand {
-public:
- SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawBitmapNineCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkBitmap fBitmap;
- SkIRect fCenter;
- SkRect fDst;
- SkPaint fPaint;
- SkPaint* fPaintPtr;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawBitmapRectCommand : public SkDrawCommand {
-public:
- SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
- const SkRect& dst, const SkPaint* paint,
- SkCanvas::SrcRectConstraint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawBitmapRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
- const SkBitmap& bitmap() const { return fBitmap; }
-
- // The non-const 'paint' method allows modification of this object's
- // SkPaint. For this reason the ctor and setPaint method make a local copy.
- // The 'fPaintPtr' member acts a signal that the local SkPaint is valid
- // (since only an SkPaint* is passed into the ctor).
- const SkPaint* paint() const { return fPaintPtr; }
- SkPaint* paint() { return fPaintPtr; }
-
- void setPaint(const SkPaint& paint) { fPaint = paint; fPaintPtr = &fPaint; }
-
- const SkRect* srcRect() const { return fSrc.isEmpty() ? nullptr : &fSrc; }
- void setSrcRect(const SkRect& src) { fSrc = src; }
-
- const SkRect& dstRect() const { return fDst; }
- void setDstRect(const SkRect& dst) { fDst = dst; }
-
- SkCanvas::SrcRectConstraint constraint() const { return fConstraint; }
- void setConstraint(SkCanvas::SrcRectConstraint constraint) { fConstraint = constraint; }
-
-private:
- SkBitmap fBitmap;
- SkRect fSrc;
- SkRect fDst;
- SkPaint fPaint;
- SkPaint* fPaintPtr;
- SkCanvas::SrcRectConstraint fConstraint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawImageCommand : public SkDrawCommand {
-public:
- SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawImageCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- sk_sp<const SkImage> fImage;
- SkScalar fLeft;
- SkScalar fTop;
- SkTLazy<SkPaint> fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawImageLatticeCommand : public SkDrawCommand {
-public:
- SkDrawImageLatticeCommand(const SkImage* image, const SkCanvas::Lattice& lattice,
- const SkRect& dst, const SkPaint* paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
-
-private:
- sk_sp<const SkImage> fImage;
- SkCanvas::Lattice fLattice;
- SkRect fDst;
- SkTLazy<SkPaint> fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawImageRectCommand : public SkDrawCommand {
-public:
- SkDrawImageRectCommand(const SkImage* image, const SkRect* src, const SkRect& dst,
- const SkPaint* paint, SkCanvas::SrcRectConstraint constraint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawImageRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- sk_sp<const SkImage> fImage;
- SkTLazy<SkRect> fSrc;
- SkRect fDst;
- SkTLazy<SkPaint> fPaint;
- SkCanvas::SrcRectConstraint fConstraint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawOvalCommand : public SkDrawCommand {
-public:
- SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawOvalCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRect fOval;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawArcCommand : public SkDrawCommand {
-public:
- SkDrawArcCommand(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
- const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawArcCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRect fOval;
- SkScalar fStartAngle;
- SkScalar fSweepAngle;
- bool fUseCenter;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPaintCommand : public SkDrawCommand {
-public:
- SkDrawPaintCommand(const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPaintCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPathCommand : public SkDrawCommand {
-public:
- SkDrawPathCommand(const SkPath& path, const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPathCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkPath fPath;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkBeginDrawPictureCommand : public SkDrawCommand {
-public:
- SkBeginDrawPictureCommand(const SkPicture* picture,
- const SkMatrix* matrix,
- const SkPaint* paint);
-
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
-
-private:
- sk_sp<const SkPicture> fPicture;
- SkTLazy<SkMatrix> fMatrix;
- SkTLazy<SkPaint> fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkEndDrawPictureCommand : public SkDrawCommand {
-public:
- SkEndDrawPictureCommand(bool restore);
-
- void execute(SkCanvas* canvas) const override;
-
-private:
- bool fRestore;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPointsCommand : public SkDrawCommand {
-public:
- SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
- const SkPaint& paint);
- ~SkDrawPointsCommand() override { delete [] fPts; }
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPointsCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkCanvas::PointMode fMode;
- size_t fCount;
- SkPoint* fPts;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawTextCommand : public SkDrawCommand {
-public:
- SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint);
- ~SkDrawTextCommand() override { delete [] fText; }
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawTextCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- char* fText;
- size_t fByteLength;
- SkScalar fX;
- SkScalar fY;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPosTextCommand : public SkDrawCommand {
-public:
- SkDrawPosTextCommand(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint& paint);
- ~SkDrawPosTextCommand() override { delete [] fPos; delete [] fText; }
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPosTextCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- char* fText;
- size_t fByteLength;
- SkPoint* fPos;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawTextOnPathCommand : public SkDrawCommand {
-public:
- SkDrawTextOnPathCommand(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint& paint);
- ~SkDrawTextOnPathCommand() override { delete [] fText; }
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawTextOnPathCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- char* fText;
- size_t fByteLength;
- SkPath fPath;
- SkMatrix fMatrix;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawTextRSXformCommand : public SkDrawCommand {
-public:
- SkDrawTextRSXformCommand(const void* text, size_t byteLength, const SkRSXform[],
- const SkRect*, const SkPaint& paint);
- ~SkDrawTextRSXformCommand() override { delete[] fText; delete[] fXform; }
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawTextRSXformCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- char* fText;
- size_t fByteLength;
- SkRSXform* fXform;
- SkRect* fCull;
- SkRect fCullStorage;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPosTextHCommand : public SkDrawCommand {
-public:
- SkDrawPosTextHCommand(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint& paint);
- ~SkDrawPosTextHCommand() override { delete [] fXpos; delete [] fText; }
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPosTextHCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkScalar* fXpos;
- char* fText;
- size_t fByteLength;
- SkScalar fConstY;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawTextBlobCommand : public SkDrawCommand {
-public:
- SkDrawTextBlobCommand(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, const SkPaint& paint);
-
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawTextBlobCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- sk_sp<SkTextBlob> fBlob;
- SkScalar fXPos;
- SkScalar fYPos;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawPatchCommand : public SkDrawCommand {
-public:
- SkDrawPatchCommand(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkBlendMode bmode,
- const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawPatchCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkPoint fCubics[12];
- SkColor* fColorsPtr;
- SkColor fColors[4];
- SkPoint* fTexCoordsPtr;
- SkPoint fTexCoords[4];
- SkBlendMode fBlendMode;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-
-class SkDrawRectCommand : public SkDrawCommand {
-public:
- SkDrawRectCommand(const SkRect& rect, const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
- const SkRect& rect() const { return fRect; }
- const SkPaint& paint() const { return fPaint; }
-private:
- SkRect fRect;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawRRectCommand : public SkDrawCommand {
-public:
- SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawRRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRRect fRRect;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawDRRectCommand : public SkDrawCommand {
-public:
- SkDrawDRRectCommand(const SkRRect& outer, const SkRRect& inner,
- const SkPaint& paint);
- void execute(SkCanvas* canvas) const override;
- bool render(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkDrawDRRectCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkRRect fOuter;
- SkRRect fInner;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkDrawVerticesCommand : public SkDrawCommand {
-public:
- SkDrawVerticesCommand(sk_sp<SkVertices>, SkBlendMode, const SkPaint&);
-
- void execute(SkCanvas* canvas) const override;
-
-private:
- sk_sp<SkVertices> fVertices;
- SkBlendMode fBlendMode;
- SkPaint fPaint;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkSaveCommand : public SkDrawCommand {
-public:
- SkSaveCommand();
- void execute(SkCanvas* canvas) const override;
- Action action() const override { return kPushLayer_Action; }
- static SkSaveCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- typedef SkDrawCommand INHERITED;
-};
-
-class SkSaveLayerCommand : public SkDrawCommand {
-public:
- SkSaveLayerCommand(const SkCanvas::SaveLayerRec&);
- ~SkSaveLayerCommand() override;
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkSaveLayerCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
- void vizExecute(SkCanvas* canvas) const override;
- Action action() const override{ return kPushLayer_Action; }
- void setActive(bool active) override { fActive = active; }
- bool active() const override { return fActive; }
-
- const SkPaint* paint() const { return fPaintPtr; }
-
-private:
- SkRect fBounds;
- SkPaint fPaint;
- SkPaint* fPaintPtr;
- const SkImageFilter* fBackdrop;
- uint32_t fSaveLayerFlags;
-
- bool fActive;
-
- typedef SkDrawCommand INHERITED;
-};
-
-class SkSetMatrixCommand : public SkDrawCommand {
-public:
- SkSetMatrixCommand(const SkMatrix& matrix);
- void setUserMatrix(const SkMatrix&) override;
- void execute(SkCanvas* canvas) const override;
- Json::Value toJSON(UrlDataManager& urlDataManager) const override;
- static SkSetMatrixCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
-
-private:
- SkMatrix fUserMatrix;
- SkMatrix fMatrix;
-
- typedef SkDrawCommand INHERITED;
-};
-#endif
-
diff --git a/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp b/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp
deleted file mode 100644
index 4b075dd..0000000
--- a/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkJsonWriteBuffer.h"
-
-#include "SkDrawCommand.h"
-#include "SkObjectParser.h"
-
-void SkJsonWriteBuffer::append(const char* type, const Json::Value& value) {
- SkString fullName = SkStringPrintf("%02d_%s", fJson.size(), type);
- fJson[fullName.c_str()] = value;
-}
-
-void SkJsonWriteBuffer::writeByteArray(const void* data, size_t size) {
- Json::Value jsonArray(Json::arrayValue);
- const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
- for (size_t i = 0; i < size; ++i) {
- SkString hexByte = SkStringPrintf("%02x", bytes[i]);
- jsonArray.append(hexByte.c_str());
- }
- this->append("byteArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writeBool(bool value) {
- this->append("bool", value);
-}
-
-void SkJsonWriteBuffer::writeScalar(SkScalar value) {
- this->append("scalar", value);
-}
-
-void SkJsonWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
- Json::Value jsonArray(Json::arrayValue);
- for (uint32_t i = 0; i < count; ++i) {
- jsonArray.append(value[i]);
- }
- this->append("scalarArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writeInt(int32_t value) {
- this->append("int", value);
-}
-
-void SkJsonWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
- Json::Value jsonArray(Json::arrayValue);
- for (uint32_t i = 0; i < count; ++i) {
- jsonArray.append(value[i]);
- }
- this->append("intArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writeUInt(uint32_t value) {
- this->append("uint", value);
-}
-
-void SkJsonWriteBuffer::writeString(const char* value) {
- this->append("string", value);
-}
-
-void SkJsonWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
- if (flattenable) {
- SkJsonWriteBuffer flattenableBuffer(fUrlDataManager);
- flattenable->flatten(flattenableBuffer);
- this->append(flattenable->getTypeName(), flattenableBuffer.getValue());
- } else {
- this->append("flattenable", Json::Value());
- }
-}
-
-void SkJsonWriteBuffer::writeColor(SkColor color) {
- this->append("color", SkDrawCommand::MakeJsonColor(color));
-}
-
-void SkJsonWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
- Json::Value jsonArray(Json::arrayValue);
- for (uint32_t i = 0; i < count; ++i) {
- jsonArray.append(SkDrawCommand::MakeJsonColor(color[i]));
- }
- this->append("colorArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writeColor4f(const SkColor4f& color) {
- this->append("color", SkDrawCommand::MakeJsonColor4f(color));
-}
-
-void SkJsonWriteBuffer::writeColor4fArray(const SkColor4f* color, uint32_t count) {
- Json::Value jsonArray(Json::arrayValue);
- for (uint32_t i = 0; i < count; ++i) {
- jsonArray.append(SkDrawCommand::MakeJsonColor4f(color[i]));
- }
- this->append("colorArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writePoint(const SkPoint& point) {
- this->append("point", SkDrawCommand::MakeJsonPoint(point));
-}
-
-void SkJsonWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
- Json::Value jsonArray(Json::arrayValue);
- for (uint32_t i = 0; i < count; ++i) {
- jsonArray.append(SkDrawCommand::MakeJsonPoint(point[i]));
- }
- this->append("pointArray", jsonArray);
-}
-
-void SkJsonWriteBuffer::writeMatrix(const SkMatrix& matrix) {
- this->append("matrix", SkDrawCommand::MakeJsonMatrix(matrix));
-}
-
-void SkJsonWriteBuffer::writeIRect(const SkIRect& rect) {
- this->append("irect", SkDrawCommand::MakeJsonIRect(rect));
-}
-
-void SkJsonWriteBuffer::writeRect(const SkRect& rect) {
- this->append("rect", SkDrawCommand::MakeJsonRect(rect));
-}
-
-void SkJsonWriteBuffer::writeRegion(const SkRegion& region) {
- this->append("region", SkDrawCommand::MakeJsonRegion(region));
-}
-
-void SkJsonWriteBuffer::writePath(const SkPath& path) {
- this->append("path", SkDrawCommand::MakeJsonPath(path));
-}
-
-size_t SkJsonWriteBuffer::writeStream(SkStream* stream, size_t length) {
- // Contents not supported
- SkASSERT(length < Json::Value::maxUInt);
- this->append("stream", static_cast<Json::UInt>(length));
- return 0;
-}
-
-void SkJsonWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
- Json::Value jsonBitmap;
- SkDrawCommand::flatten(bitmap, &jsonBitmap, *fUrlDataManager);
- this->append("bitmap", jsonBitmap);
-}
-
-void SkJsonWriteBuffer::writeImage(const SkImage* image) {
- Json::Value jsonImage;
- SkDrawCommand::flatten(*image, &jsonImage, *fUrlDataManager);
- this->append("image", jsonImage);
-}
-
-void SkJsonWriteBuffer::writeTypeface(SkTypeface* typeface) {
- // Unsupported
- this->append("typeface", Json::Value());
-}
-
-void SkJsonWriteBuffer::writePaint(const SkPaint& paint) {
- this->append("paint", SkDrawCommand::MakeJsonPaint(paint, *fUrlDataManager));
-}
diff --git a/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.h b/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.h
deleted file mode 100644
index a0cf4e7..0000000
--- a/src/third_party/skia/tools/debugger/SkJsonWriteBuffer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkJsonWriteBuffer_DEFINED
-#define SkJsonWriteBuffer_DEFINED
-
-#include "SkWriteBuffer.h"
-
-#include "SkJSONCPP.h"
-
-class SkPath;
-class UrlDataManager;
-
-class SkJsonWriteBuffer final : public SkWriteBuffer {
-public:
- SkJsonWriteBuffer(UrlDataManager* urlDataManager)
- : fUrlDataManager(urlDataManager)
- , fJson(Json::objectValue) {}
-
- bool isCrossProcess() const override { return false; }
-
- void writeByteArray(const void* data, size_t size) override;
- void writeBool(bool value) override;
- void writeScalar(SkScalar value) override;
- void writeScalarArray(const SkScalar* value, uint32_t count) override;
- void writeInt(int32_t value) override;
- void writeIntArray(const int32_t* value, uint32_t count) override;
- void writeUInt(uint32_t value) override;
- void writeString(const char* value) override;
-
- void writeFlattenable(const SkFlattenable* flattenable) override;
- void writeColor(SkColor color) override;
- void writeColorArray(const SkColor* color, uint32_t count) override;
- void writeColor4f(const SkColor4f& color) override;
- void writeColor4fArray(const SkColor4f* color, uint32_t count) override;
- void writePoint(const SkPoint& point) override;
- void writePointArray(const SkPoint* point, uint32_t count) override;
- void writeMatrix(const SkMatrix& matrix) override;
- void writeIRect(const SkIRect& rect) override;
- void writeRect(const SkRect& rect) override;
- void writeRegion(const SkRegion& region) override;
- void writePath(const SkPath& path) override;
- size_t writeStream(SkStream* stream, size_t length) override;
- void writeBitmap(const SkBitmap& bitmap) override;
- void writeImage(const SkImage*) override;
- void writeTypeface(SkTypeface* typeface) override;
- void writePaint(const SkPaint& paint) override;
-
- const Json::Value& getValue() const { return fJson; }
-
-private:
- void append(const char* type, const Json::Value& value);
-
- UrlDataManager* fUrlDataManager;
- Json::Value fJson;
-};
-
-#endif
diff --git a/src/third_party/skia/tools/debugger/SkObjectParser.cpp b/src/third_party/skia/tools/debugger/SkObjectParser.cpp
deleted file mode 100644
index 1f48319..0000000
--- a/src/third_party/skia/tools/debugger/SkObjectParser.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkObjectParser.h"
-#include "SkData.h"
-#include "SkFontDescriptor.h"
-#include "SkImage.h"
-#include "SkPath.h"
-#include "SkRRect.h"
-#include "SkShader.h"
-#include "SkStream.h"
-#include "SkStringUtils.h"
-#include "SkTypeface.h"
-#include "SkUtils.h"
-#include "SkClipOpPriv.h"
-
-/* TODO(chudy): Replace all std::strings with char */
-
-SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) {
- SkString* mBitmap = new SkString("SkBitmap: ");
- mBitmap->append("W: ");
- mBitmap->appendS32(bitmap.width());
- mBitmap->append(" H: ");
- mBitmap->appendS32(bitmap.height());
-
- const char* gColorTypeStrings[] = {
- "None", "A8", "565", "4444", "RGBA", "BGRA",
- "G8", "RGBAf16"
- };
- static_assert(kLastEnum_SkColorType + 1 == SK_ARRAY_COUNT(gColorTypeStrings),
- "colortype names do not match colortype enum");
-
- mBitmap->append(" ColorType: ");
- mBitmap->append(gColorTypeStrings[bitmap.colorType()]);
-
- if (bitmap.isOpaque()) {
- mBitmap->append(" opaque");
- } else {
- mBitmap->append(" not-opaque");
- }
-
- if (bitmap.isImmutable()) {
- mBitmap->append(" immutable");
- } else {
- mBitmap->append(" not-immutable");
- }
-
- if (bitmap.isVolatile()) {
- mBitmap->append(" volatile");
- } else {
- mBitmap->append(" not-volatile");
- }
-
- mBitmap->append(" genID: ");
- mBitmap->appendS32(bitmap.getGenerationID());
-
- return mBitmap;
-}
-
-SkString* SkObjectParser::ImageToString(const SkImage* image) {
- SkString* str = new SkString("SkImage: ");
- if (!image) {
- return str;
- }
-
- str->append("W: ");
- str->appendS32(image->width());
- str->append(" H: ");
- str->appendS32(image->height());
-
- if (image->isOpaque()) {
- str->append(" opaque");
- } else {
- str->append(" not-opaque");
- }
-
- str->append(" uniqueID: ");
- str->appendS32(image->uniqueID());
-
- return str;
-}
-
-SkString* SkObjectParser::BoolToString(bool doAA) {
- SkString* mBool = new SkString("Bool doAA: ");
- if (doAA) {
- mBool->append("True");
- } else {
- mBool->append("False");
- }
- return mBool;
-}
-
-SkString* SkObjectParser::CustomTextToString(const char* text) {
- SkString* mText = new SkString(text);
- return mText;
-}
-
-SkString* SkObjectParser::IntToString(int x, const char* text) {
- SkString* mInt = new SkString(text);
- mInt->append(" ");
- mInt->appendScalar(SkIntToScalar(x));
- return mInt;
-}
-
-SkString* SkObjectParser::IRectToString(const SkIRect& rect) {
- SkString* mRect = new SkString("SkIRect: ");
- mRect->append("L: ");
- mRect->appendS32(rect.left());
- mRect->append(", T: ");
- mRect->appendS32(rect.top());
- mRect->append(", R: ");
- mRect->appendS32(rect.right());
- mRect->append(", B: ");
- mRect->appendS32(rect.bottom());
- return mRect;
-}
-
-SkString* SkObjectParser::MatrixToString(const SkMatrix& matrix) {
- SkString* str = new SkString("SkMatrix: ");
-#ifndef SK_IGNORE_TO_STRING
- matrix.toString(str);
-#endif
- return str;
-}
-
-SkString* SkObjectParser::PaintToString(const SkPaint& paint) {
- SkString* str = new SkString;
-#ifndef SK_IGNORE_TO_STRING
- paint.toString(str);
-#endif
- return str;
-}
-
-SkString* SkObjectParser::PathToString(const SkPath& path) {
- SkString* mPath = new SkString;
-
- mPath->appendf("Path (%d) (", path.getGenerationID());
-
- static const char* gFillStrings[] = {
- "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd"
- };
-
- mPath->append(gFillStrings[path.getFillType()]);
- mPath->append(", ");
-
- static const char* gConvexityStrings[] = {
- "Unknown", "Convex", "Concave"
- };
- SkASSERT(SkPath::kConcave_Convexity == 2);
-
- mPath->append(gConvexityStrings[path.getConvexity()]);
- mPath->append(", ");
-
- if (path.isRect(nullptr)) {
- mPath->append("isRect, ");
- } else {
- mPath->append("isNotRect, ");
- }
-
- if (path.isOval(nullptr)) {
- mPath->append("isOval, ");
- } else {
- mPath->append("isNotOval, ");
- }
-
- SkRRect rrect;
- if (path.isRRect(&rrect)) {
- mPath->append("isRRect, ");
- } else {
- mPath->append("isNotRRect, ");
- }
-
- mPath->appendS32(path.countVerbs());
- mPath->append("V, ");
- mPath->appendS32(path.countPoints());
- mPath->append("P): ");
-
- static const char* gVerbStrings[] = {
- "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done"
- };
- static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 };
- static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 };
- SkASSERT(SkPath::kDone_Verb == 6);
-
- SkPath::Iter iter(const_cast<SkPath&>(path), false);
- SkPath::Verb verb;
- SkPoint points[4];
-
- for(verb = iter.next(points, false);
- verb != SkPath::kDone_Verb;
- verb = iter.next(points, false)) {
-
- mPath->append(gVerbStrings[verb]);
- mPath->append(" ");
-
- for (int i = 0; i < gPtsPerVerb[verb]; ++i) {
- mPath->append("(");
- mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fX);
- mPath->append(", ");
- mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fY);
- mPath->append(")");
- }
-
- if (SkPath::kConic_Verb == verb) {
- mPath->append("(");
- mPath->appendScalar(iter.conicWeight());
- mPath->append(")");
- }
-
- mPath->append(" ");
- }
-
- SkString* boundStr = SkObjectParser::RectToString(path.getBounds(), " Bound: ");
-
- if (boundStr) {
- mPath->append(*boundStr);
- delete boundStr;
- }
-
- return mPath;
-}
-
-SkString* SkObjectParser::PointsToString(const SkPoint pts[], size_t count) {
- SkString* mPoints = new SkString("SkPoints pts[]: ");
- for (unsigned int i = 0; i < count; i++) {
- mPoints->append("(");
- mPoints->appendScalar(pts[i].fX);
- mPoints->append(",");
- mPoints->appendScalar(pts[i].fY);
- mPoints->append(")");
- }
- return mPoints;
-}
-
-SkString* SkObjectParser::PointModeToString(SkCanvas::PointMode mode) {
- SkString* mMode = new SkString("SkCanvas::PointMode: ");
- if (mode == SkCanvas::kPoints_PointMode) {
- mMode->append("kPoints_PointMode");
- } else if (mode == SkCanvas::kLines_PointMode) {
- mMode->append("kLines_Mode");
- } else if (mode == SkCanvas::kPolygon_PointMode) {
- mMode->append("kPolygon_PointMode");
- }
- return mMode;
-}
-
-SkString* SkObjectParser::RectToString(const SkRect& rect, const char* title) {
-
- SkString* mRect = new SkString;
-
- if (nullptr == title) {
- mRect->append("SkRect: ");
- } else {
- mRect->append(title);
- }
- mRect->append("(");
- mRect->appendScalar(rect.left());
- mRect->append(", ");
- mRect->appendScalar(rect.top());
- mRect->append(", ");
- mRect->appendScalar(rect.right());
- mRect->append(", ");
- mRect->appendScalar(rect.bottom());
- mRect->append(")");
- return mRect;
-}
-
-SkString* SkObjectParser::RRectToString(const SkRRect& rrect, const char* title) {
-
- SkString* mRRect = new SkString;
-
- if (nullptr == title) {
- mRRect->append("SkRRect (");
- if (rrect.isEmpty()) {
- mRRect->append("empty");
- } else if (rrect.isRect()) {
- mRRect->append("rect");
- } else if (rrect.isOval()) {
- mRRect->append("oval");
- } else if (rrect.isSimple()) {
- mRRect->append("simple");
- } else if (rrect.isNinePatch()) {
- mRRect->append("nine-patch");
- } else {
- SkASSERT(rrect.isComplex());
- mRRect->append("complex");
- }
- mRRect->append("): ");
- } else {
- mRRect->append(title);
- }
- mRRect->append("(");
- mRRect->appendScalar(rrect.rect().left());
- mRRect->append(", ");
- mRRect->appendScalar(rrect.rect().top());
- mRRect->append(", ");
- mRRect->appendScalar(rrect.rect().right());
- mRRect->append(", ");
- mRRect->appendScalar(rrect.rect().bottom());
- mRRect->append(") radii: (");
- for (int i = 0; i < 4; ++i) {
- const SkVector& radii = rrect.radii((SkRRect::Corner) i);
- mRRect->appendScalar(radii.fX);
- mRRect->append(", ");
- mRRect->appendScalar(radii.fY);
- if (i < 3) {
- mRRect->append(", ");
- }
- }
- mRRect->append(")");
- return mRRect;
-}
-
-SkString* SkObjectParser::ClipOpToString(SkClipOp op) {
- SkString* mOp = new SkString("SkRegion::Op: ");
- if (op == kDifference_SkClipOp) {
- mOp->append("kDifference_Op");
- } else if (op == kIntersect_SkClipOp) {
- mOp->append("kIntersect_Op");
- } else if (op == kUnion_SkClipOp) {
- mOp->append("kUnion_Op");
- } else if (op == kXOR_SkClipOp) {
- mOp->append("kXOR_Op");
- } else if (op == kReverseDifference_SkClipOp) {
- mOp->append("kReverseDifference_Op");
- } else if (op == kReplace_SkClipOp) {
- mOp->append("kReplace_Op");
- } else {
- mOp->append("Unknown Type");
- }
- return mOp;
-}
-
-SkString* SkObjectParser::RegionToString(const SkRegion& region) {
- SkString* mRegion = new SkString("SkRegion: Data unavailable.");
- return mRegion;
-}
-
-SkString* SkObjectParser::SaveLayerFlagsToString(SkCanvas::SaveLayerFlags saveLayerFlags) {
- SkString* mFlags = new SkString("SkCanvas::SaveFlags: ");
- if (saveLayerFlags & SkCanvas::kIsOpaque_SaveLayerFlag) {
- mFlags->append("kIsOpaque_SaveLayerFlag ");
- }
- if (saveLayerFlags & SkCanvas::kPreserveLCDText_SaveLayerFlag) {
- mFlags->append("kPreserveLCDText_SaveLayerFlag ");
- }
- return mFlags;
-}
-
-SkString* SkObjectParser::ScalarToString(SkScalar x, const char* text) {
- SkString* mScalar = new SkString(text);
- mScalar->append(" ");
- mScalar->appendScalar(x);
- return mScalar;
-}
-
-SkString* SkObjectParser::TextToString(const void* text, size_t byteLength,
- SkPaint::TextEncoding encoding) {
-
- SkString* decodedText = new SkString();
- switch (encoding) {
- case SkPaint::kUTF8_TextEncoding: {
- decodedText->append("UTF-8: ");
- decodedText->append((const char*)text, byteLength);
- break;
- }
- case SkPaint::kUTF16_TextEncoding: {
- decodedText->append("UTF-16: ");
- size_t sizeNeeded = SkUTF16_ToUTF8((uint16_t*)text,
- SkToS32(byteLength / 2),
- nullptr);
- SkAutoSTMalloc<0x100, char> utf8(sizeNeeded);
- SkUTF16_ToUTF8((uint16_t*)text, SkToS32(byteLength / 2), utf8);
- decodedText->append(utf8, sizeNeeded);
- break;
- }
- case SkPaint::kUTF32_TextEncoding: {
- decodedText->append("UTF-32: ");
- const SkUnichar* begin = (const SkUnichar*)text;
- const SkUnichar* end = (const SkUnichar*)((const char*)text + byteLength);
- for (const SkUnichar* unichar = begin; unichar < end; ++unichar) {
- decodedText->appendUnichar(*unichar);
- }
- break;
- }
- case SkPaint::kGlyphID_TextEncoding: {
- decodedText->append("GlyphID: ");
- const uint16_t* begin = (const uint16_t*)text;
- const uint16_t* end = (const uint16_t*)((const char*)text + byteLength);
- for (const uint16_t* glyph = begin; glyph < end; ++glyph) {
- decodedText->append("0x");
- decodedText->appendHex(*glyph);
- decodedText->append(" ");
- }
- break;
- }
- default:
- decodedText->append("Unknown text encoding.");
- break;
- }
-
- return decodedText;
-}
-
-SkString* SkObjectParser::LatticeToString(const SkCanvas::Lattice& lattice) {
- SkString* mLattice = new SkString;
- mLattice->append("Lattice: ");
- mLattice->append("(X: ");
- mLattice->appendS32(lattice.fXCount);
- mLattice->append(", Y:");
- mLattice->appendS32(lattice.fYCount);
- mLattice->append(", Bounds:");
- if (nullptr != lattice.fBounds) {
- mLattice->append(*IRectToString(*lattice.fBounds));
- } else {
- mLattice->append("null");
- }
- mLattice->append(")");
- return mLattice;
-}
diff --git a/src/third_party/skia/tools/debugger/SkObjectParser.h b/src/third_party/skia/tools/debugger/SkObjectParser.h
deleted file mode 100644
index 2532c5c..0000000
--- a/src/third_party/skia/tools/debugger/SkObjectParser.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKOBJECTPARSER_H_
-#define SKOBJECTPARSER_H_
-
-#include "SkCanvas.h"
-#include "SkString.h"
-
-/** \class SkObjectParser
-
- The ObjectParser is used to return string information about parameters
- in each draw command.
- */
-class SkObjectParser {
-public:
-
- /**
- Returns a string about a bitmap's bounds and colortype.
- @param bitmap SkBitmap
- */
- static SkString* BitmapToString(const SkBitmap& bitmap);
-
- /**
- Returns a string about a image
- @param image SkImage
- */
- static SkString* ImageToString(const SkImage* image);
-
- /**
- Returns a string representation of a boolean.
- @param doAA boolean
- */
- static SkString* BoolToString(bool doAA);
-
- /**
- Returns a string representation of the text pointer passed in.
- */
- static SkString* CustomTextToString(const char* text);
-
- /**
- Returns a string representation of an integer with the text parameter
- at the front of the string.
- @param x integer
- @param text
- */
- static SkString* IntToString(int x, const char* text);
- /**
- Returns a string representation of the SkIRects coordinates.
- @param rect SkIRect
- */
- static SkString* IRectToString(const SkIRect& rect);
-
- /**
- Returns a string representation of an SkMatrix's contents
- @param matrix SkMatrix
- */
- static SkString* MatrixToString(const SkMatrix& matrix);
-
- /**
- Returns a string representation of an SkPaint's color
- @param paint SkPaint
- */
- static SkString* PaintToString(const SkPaint& paint);
-
- /**
- Returns a string representation of a SkPath's points.
- @param path SkPath
- */
- static SkString* PathToString(const SkPath& path);
-
- /**
- Returns a string representation of the points in the point array.
- @param pts[] Array of SkPoints
- @param count
- */
- static SkString* PointsToString(const SkPoint pts[], size_t count);
-
- /**
- Returns a string representation of the SkCanvas PointMode enum.
- */
- static SkString* PointModeToString(SkCanvas::PointMode mode);
-
- /**
- Returns a string representation of the SkRects coordinates.
- @param rect SkRect
- */
- static SkString* RectToString(const SkRect& rect, const char* title = nullptr);
-
- /**
- Returns a string representation of an SkRRect.
- @param rrect SkRRect
- */
- static SkString* RRectToString(const SkRRect& rrect, const char* title = nullptr);
-
- /**
- Returns a string representation of the SkRegion enum.
- @param op SkRegion::op enum
- */
- static SkString* ClipOpToString(SkClipOp op);
-
- /**
- Returns a string representation of the SkRegion.
- @param region SkRegion
- */
- static SkString* RegionToString(const SkRegion& region);
-
- /**
- Returns a string representation of the SkCanvas::SaveLayerFlags enum.
- @param flags SkCanvas::SaveLayerFlags enum
- */
- static SkString* SaveLayerFlagsToString(uint32_t saveLayerFlags);
-
- /**
- Returns a string representation of an SkScalar with the text parameter
- at the front of the string.
- @param x SkScalar
- @param text
- */
- static SkString* ScalarToString(SkScalar x, const char* text);
-
- /**
- Returns a string representation of the char pointer passed in.
- @param text const void* that will be cast to a char*
- */
- static SkString* TextToString(const void* text, size_t byteLength,
- SkPaint::TextEncoding encoding);
-
- /**
- Returns a string representation of the SkCanvas::Lattice.
- @param lattice SkCanvas::Lattice
- */
- static SkString* LatticeToString(const SkCanvas::Lattice& lattice);
-};
-
-#endif
diff --git a/src/third_party/skia/tools/doxygen/Doxyfile b/src/third_party/skia/tools/doxygen/Doxyfile
new file mode 100644
index 0000000..ada9cf1
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/Doxyfile
@@ -0,0 +1,2504 @@
+# Doxyfile 1.8.13
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "Skia"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "2D Graphics Library"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO = logo.png
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = /tmp/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES = "copy{1}=\htmlonly <script>document.write('<div style=\'display:none;visibility:hidden;\'>');</script> \endhtmlonly \image html \1 \n \htmlonly <script>document.write('</div>');</script> \endhtmlonly"
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 2
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 8
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ../../include/core \
+ ../../include/effects \
+ ../../include/gpu \
+ ../../include/pathops \
+ ../../third_party/skcms \
+ ../../modules/particles/include \
+ ../../modules/skottie/include \
+ ../../modules/sksg/include \
+ ../../modules/skshaper/include \
+ ./mainpage
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH = ./mainpage/markdeep
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse-libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER = ./footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = ./customdoxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED = SkDEBUGCODE
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
+
diff --git a/src/third_party/skia/tools/doxygen/ProdDoxyfile b/src/third_party/skia/tools/doxygen/ProdDoxyfile
new file mode 100644
index 0000000..afcacff
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/ProdDoxyfile
@@ -0,0 +1,5 @@
+# This config is used to generate the docs under continuous integration.
+
+@INCLUDE = Doxyfile
+
+OUTPUT_DIRECTORY = /workspace/__doxygen_staging
diff --git a/src/third_party/skia/tools/doxygen/README.md b/src/third_party/skia/tools/doxygen/README.md
new file mode 100644
index 0000000..d01cecb
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/README.md
@@ -0,0 +1,31 @@
+Doxygen
+=======
+
+To generate all the documentation run the following
+from this directory:
+
+ doxygen Doxyfile
+
+The resulting output goes to
+
+ /tmp/doxygen
+
+To view those file locally in your browser run:
+
+ cd /tmp/doxygen/html; python -m SimpleHTTPServer 8000
+
+and visit
+
+ http://localhost:8000
+
+If you want to have the documentation regenerated on every save then
+you can install `entr` and run the following from this directory:
+
+ find ../../include/ ../../src/ . | entr doxygen ./Doxyfile
+
+Install
+-------
+
+For a linux desktop you can install the doxygen tool via:
+
+ sudo apt install doxygen
diff --git a/src/third_party/skia/tools/doxygen/customdoxygen.css b/src/third_party/skia/tools/doxygen/customdoxygen.css
new file mode 100644
index 0000000..749cfb1
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/customdoxygen.css
@@ -0,0 +1,182 @@
+/* Skia overrides for doxygen CSS. */
+
+html {
+ --blue: rgb(0,114,178);
+ --green: rgb(0,158,115);
+ --red: rgb(213,94,0);
+ --orange: rgb(230,159,0);
+ --purple: rgb(204,121,167);
+ --brown: rgb(177,89,40);
+ --gray: rgb(79,79,79);
+ --light-blue: rgb(128,185,217);
+ --light-green: rgb(128,207,185);
+ --light-red: rgb(234,175,128);
+ --light-orange: rgb(243,207,128);
+ --light-purple: rgb(230,188,211);
+ --light-brown: rgb(216,172,148);
+ --light-gray: rgb(168,168,168);
+
+ --dark-blue: rgb(0,65,101);
+ --dark-red: rgb(156,44,8);
+
+ --white: rgb(254,254,254);
+ --dark-white: rgb(240,240,240);
+ --black: rgb(10,10,10);
+}
+
+#titlearea {
+ /* background matches Skia logo. */
+ background: rgb(248,248,248);
+ color: var(--blue);
+}
+
+#main-nav .sm {
+ background-image: none;
+}
+
+h2.groupheader {
+ border-bottom: var(--gray);
+ color: var(--dark-blue);
+}
+
+div.qindex, div.navtab{
+ background-color: var(--light-gray);
+ border: 1px solid var(--light-blue);
+}
+
+a {
+ color: var(--blue);
+}
+
+.contents a:visited {
+ color: var(--blue);
+}
+
+a.qindexHL {
+ background-color: var(--light-gray);
+ color: var(--white);
+ border: 1px double var(--gray);
+}
+
+.contents a.qindexHL:visited {
+ color: var(--white);
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: var(--blue);
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: var(--blue);
+}
+
+pre.fragment {
+ border: 1px solid var(--orange);
+ background-color: var(--dark-white);
+}
+
+div.fragment {
+ background-color: var(--dark-white);
+ border: 1px solid var(--orange);
+}
+
+span.lineno {
+ border-right: 2px solid var(--green);
+ background-color: var(-light-gray);
+}
+span.lineno a {
+ background-color: var(--light-gray);
+}
+
+span.lineno a:hover {
+ background-color: var(--light-gray);
+ color: var(--blue);
+}
+
+div.ah, span.ah {
+ background-color: var(--black);
+ color: var(--white);
+ border: solid thin var(--gray);
+ box-shadow: 2px 2px 3px var(light-gray);
+ background-image: none;
+}
+
+td.indexkey {
+ background-color: var(--light-gray);
+ border: 1px solid var(--orange);
+}
+
+td.indexvalue {
+ background-color: var(--light-gray);
+ border: 1px solid var(--orange);
+}
+
+tr.memlist {
+ background-color: var(--light-gray);
+}
+
+span.keyword {
+ color: var(--green);
+}
+
+span.keywordtype {
+ color: var(--brown);
+}
+
+span.keywordflow {
+ color: var(--brown);
+}
+
+span.comment {
+ color: var(--brown);
+}
+
+span.charliteral {
+ color: var(--green);
+}
+
+span.vhdldigit {
+ color: var(--purple);
+}
+
+span.vhdlchar {
+ color: var(--black);
+}
+
+blockquote {
+ background-color: var(--light-gray);
+ border-left: 2px solid var(--gray);
+}
+
+.memtitle {
+ background-image: none;
+}
+
+.memdoc, dl.reflist dd {
+ background-image: none;
+}
+
+.paramname {
+ color: var(--dark-red);
+}
+
+.tabsearch {
+ background-image: none;
+}
+
+.navpath ul {
+ background-image: none;
+}
+
+.navpath li {
+ background-image: none;
+}
+
+.navpath li.navelem a:hover {
+ color: var(--blue)
+}
+
+.navpath li.footer {
+ background-image:none;
+}
+
diff --git a/src/third_party/skia/tools/doxygen/footer.html b/src/third_party/skia/tools/doxygen/footer.html
new file mode 100644
index 0000000..4997206
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/footer.html
@@ -0,0 +1,24 @@
+<!-- HTML footer for doxygen 1.8.13-->
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ $navpath
+ <li class="footer">$generatedby
+ <a href="http://www.doxygen.org/index.html">
+ Doxygen</a> $doxygenversion on $date</li>
+ </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small>
+$generatedby  <a href="http://www.doxygen.org/index.html">
+ Doxygen
+</a> $doxygenversion on $date
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+
+<script>window.markdeepOptions = {mode: 'doxygen'};</script>
+<script src="https://casual-effects.com/markdeep/latest/markdeep.min.js"></script><script src="markdeep.min.js"></script>
+</body>
+</html>
diff --git a/src/third_party/skia/tools/doxygen/logo.png b/src/third_party/skia/tools/doxygen/logo.png
new file mode 100644
index 0000000..b250f7d
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/logo.png
Binary files differ
diff --git a/src/third_party/skia/tools/doxygen/mainpage/mainpage.dox b/src/third_party/skia/tools/doxygen/mainpage/mainpage.dox
new file mode 100644
index 0000000..4748d8c
--- /dev/null
+++ b/src/third_party/skia/tools/doxygen/mainpage/mainpage.dox
@@ -0,0 +1,24 @@
+/** \mainpage
+
+Skia is an open source 2D graphics library which provides common APIs that work
+across a variety of hardware and software platforms. It serves as the graphics
+engine for Google Chrome and Chrome OS, Android, Mozilla Firefox and Firefox
+OS, and many other products.
+
+Skia is sponsored and managed by Google, but is available for use by anyone
+under the BSD Free Software License. While engineering of the core components
+is done by the Skia development team, we consider contributions from any
+source.
+
+The site you are at is the API documentation for the Skia library. Other
+resources are:
+
+ - Canonical source tree:
+ [skia.googlesource.com/skia](https://skia.googlesource.com/skia).
+ - Issue tracker:
+ [bug.skia.org](https://bug.skia.org/).
+ - Discussion forum:
+ [skia-discuss@googlegroups.com](https://groups.google.com/forum/#!forum/skia-discuss).
+ - Skia Fiddle: [fiddle.skia.org](https://fiddle.skia.org/c/@skcanvas_paint).
+
+*/
diff --git a/src/third_party/skia/tools/dump_record.cpp b/src/third_party/skia/tools/dump_record.cpp
index 24017bd..abfb12f 100644
--- a/src/third_party/skia/tools/dump_record.cpp
+++ b/src/third_party/skia/tools/dump_record.cpp
@@ -5,26 +5,26 @@
* found in the LICENSE file.
*/
-#include "DumpRecord.h"
-#include "SkBitmap.h"
-#include "SkCommandLineFlags.h"
-#include "SkDeferredCanvas.h"
-#include "SkPicture.h"
-#include "SkPictureRecorder.h"
-#include "SkRecordDraw.h"
-#include "SkRecordOpts.h"
-#include "SkRecorder.h"
-#include "SkStream.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkPictureRecorder.h"
+#include "include/core/SkStream.h"
+#include "src/core/SkRecordDraw.h"
+#include "src/core/SkRecordOpts.h"
+#include "src/core/SkRecorder.h"
+#include "tools/DumpRecord.h"
+#include "tools/flags/CommandLineFlags.h"
+
#include <stdio.h>
-DEFINE_string2(skps, r, "", ".SKPs to dump.");
-DEFINE_string(match, "", "The usual filters on file names to dump.");
-DEFINE_bool2(optimize, O, false, "Run SkRecordOptimize before dumping.");
-DEFINE_bool(optimize2, false, "Run SkRecordOptimize2 before dumping.");
-DEFINE_int32(tile, 1000000000, "Simulated tile size.");
-DEFINE_bool(timeWithCommand, false, "If true, print time next to command, else in first column.");
-DEFINE_string2(write, w, "", "Write the (optimized) picture to the named file.");
-DEFINE_bool(defer, false, "Defer clips and translates");
+static DEFINE_string2(skps, r, "", ".SKPs to dump.");
+static DEFINE_string(match, "", "The usual filters on file names to dump.");
+static DEFINE_bool2(optimize, O, false, "Run SkRecordOptimize before dumping.");
+static DEFINE_bool(optimize2, false, "Run SkRecordOptimize2 before dumping.");
+static DEFINE_int(tile, 1000000000, "Simulated tile size.");
+static DEFINE_bool(timeWithCommand, false,
+ "If true, print time next to command, else in first column.");
+static DEFINE_string2(write, w, "", "Write the (optimized) picture to the named file.");
static void dump(const char* name, int w, int h, const SkRecord& record) {
SkBitmap bitmap;
@@ -39,10 +39,10 @@
}
int main(int argc, char** argv) {
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::Parse(argc, argv);
for (int i = 0; i < FLAGS_skps.count(); i++) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
+ if (CommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
continue;
}
@@ -56,13 +56,6 @@
SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
return 1;
}
- if (FLAGS_defer) {
- SkPictureRecorder recorder;
- SkDeferredCanvas deferred(recorder.beginRecording(src->cullRect()),
- SkDeferredCanvas::kEager);
- src->playback(&deferred);
- src = recorder.finishRecordingAsPicture();
- }
const int w = SkScalarCeilToInt(src->cullRect().width());
const int h = SkScalarCeilToInt(src->cullRect().height());
diff --git a/src/third_party/skia/tools/embed_resources.py b/src/third_party/skia/tools/embed_resources.py
index 56d5982..675a9fe 100644
--- a/src/third_party/skia/tools/embed_resources.py
+++ b/src/third_party/skia/tools/embed_resources.py
@@ -39,12 +39,13 @@
args = parser.parse_args()
out = args.output.write;
- out('#include "SkTypes.h"\n')
+ out('#include <stddef.h>\n')
+ out('#include <stdint.h>\n')
# Write the resources.
index = 0
for f in args.input:
- out('static const uint8_t resource{0:d}[] SK_STRUCT_ALIGN({1:d}) = {{\n'
+ out('alignas({1:d}) static const uint8_t resource{0:d}[] = {{\n'
.format(index, args.align))
bytes_written = 0
bytes_on_line = 0
diff --git a/src/third_party/skia/tools/fiddle/all_examples.cpp b/src/third_party/skia/tools/fiddle/all_examples.cpp
new file mode 100644
index 0000000..c3148d3
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/all_examples.cpp
@@ -0,0 +1,1074 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#include "../../docs/examples/Alpha_Constants_a.cpp"
+#include "../../docs/examples/Alpha_Constants_b.cpp"
+#include "../../docs/examples/Alpha_Type_Opaque.cpp"
+#include "../../docs/examples/Alpha_Type_Premul.cpp"
+#include "../../docs/examples/Alpha_Type_Unpremul.cpp"
+#include "../../docs/examples/Anti_Alias.cpp"
+#include "../../docs/examples/Arc.cpp"
+#include "../../docs/examples/AutoCanvasRestore_SkCanvas_star.cpp"
+#include "../../docs/examples/AutoCanvasRestore_restore.cpp"
+#include "../../docs/examples/Bitmap_012.cpp"
+#include "../../docs/examples/Bitmap_ComputeIsOpaque.cpp"
+#include "../../docs/examples/Bitmap_HeapAllocator_allocPixelRef.cpp"
+#include "../../docs/examples/Bitmap_allocN32Pixels.cpp"
+#include "../../docs/examples/Bitmap_allocPixels.cpp"
+#include "../../docs/examples/Bitmap_allocPixelsFlags.cpp"
+#include "../../docs/examples/Bitmap_allocPixels_2.cpp"
+#include "../../docs/examples/Bitmap_allocPixels_3.cpp"
+#include "../../docs/examples/Bitmap_allocPixels_4.cpp"
+#include "../../docs/examples/Bitmap_bounds.cpp"
+#include "../../docs/examples/Bitmap_bytesPerPixel.cpp"
+#include "../../docs/examples/Bitmap_colorSpace.cpp"
+#include "../../docs/examples/Bitmap_colorType.cpp"
+#include "../../docs/examples/Bitmap_computeByteSize.cpp"
+#include "../../docs/examples/Bitmap_copy_const_SkBitmap.cpp"
+#include "../../docs/examples/Bitmap_copy_operator.cpp"
+#include "../../docs/examples/Bitmap_dimensions.cpp"
+#include "../../docs/examples/Bitmap_drawsNothing.cpp"
+#include "../../docs/examples/Bitmap_empty.cpp"
+#include "../../docs/examples/Bitmap_empty_constructor.cpp"
+#include "../../docs/examples/Bitmap_erase.cpp"
+#include "../../docs/examples/Bitmap_eraseARGB.cpp"
+#include "../../docs/examples/Bitmap_eraseColor.cpp"
+#include "../../docs/examples/Bitmap_extractAlpha.cpp"
+#include "../../docs/examples/Bitmap_extractAlpha_2.cpp"
+#include "../../docs/examples/Bitmap_extractAlpha_3.cpp"
+#include "../../docs/examples/Bitmap_extractSubset.cpp"
+#include "../../docs/examples/Bitmap_getAddr.cpp"
+#include "../../docs/examples/Bitmap_getAddr16.cpp"
+#include "../../docs/examples/Bitmap_getAddr32.cpp"
+#include "../../docs/examples/Bitmap_getAddr8.cpp"
+#include "../../docs/examples/Bitmap_getBounds.cpp"
+#include "../../docs/examples/Bitmap_getBounds_2.cpp"
+#include "../../docs/examples/Bitmap_getColor.cpp"
+#include "../../docs/examples/Bitmap_getGenerationID.cpp"
+#include "../../docs/examples/Bitmap_getPixels.cpp"
+#include "../../docs/examples/Bitmap_getSubset.cpp"
+#include "../../docs/examples/Bitmap_height.cpp"
+#include "../../docs/examples/Bitmap_info.cpp"
+#include "../../docs/examples/Bitmap_installPixels.cpp"
+#include "../../docs/examples/Bitmap_installPixels_2.cpp"
+#include "../../docs/examples/Bitmap_installPixels_3.cpp"
+#include "../../docs/examples/Bitmap_isImmutable.cpp"
+#include "../../docs/examples/Bitmap_isNull.cpp"
+#include "../../docs/examples/Bitmap_isOpaque.cpp"
+#include "../../docs/examples/Bitmap_isVolatile.cpp"
+#include "../../docs/examples/Bitmap_move_SkBitmap.cpp"
+#include "../../docs/examples/Bitmap_move_operator.cpp"
+#include "../../docs/examples/Bitmap_notifyPixelsChanged.cpp"
+#include "../../docs/examples/Bitmap_peekPixels.cpp"
+#include "../../docs/examples/Bitmap_pixelRef.cpp"
+#include "../../docs/examples/Bitmap_pixelRefOrigin.cpp"
+#include "../../docs/examples/Bitmap_pixmap.cpp"
+#include "../../docs/examples/Bitmap_readPixels.cpp"
+#include "../../docs/examples/Bitmap_readPixels_2.cpp"
+#include "../../docs/examples/Bitmap_readPixels_3.cpp"
+#include "../../docs/examples/Bitmap_readyToDraw.cpp"
+#include "../../docs/examples/Bitmap_refColorSpace.cpp"
+#include "../../docs/examples/Bitmap_reset.cpp"
+#include "../../docs/examples/Bitmap_rowBytes.cpp"
+#include "../../docs/examples/Bitmap_rowBytesAsPixels.cpp"
+#include "../../docs/examples/Bitmap_setAlphaType.cpp"
+#include "../../docs/examples/Bitmap_setImmutable.cpp"
+#include "../../docs/examples/Bitmap_setInfo.cpp"
+#include "../../docs/examples/Bitmap_setIsVolatile.cpp"
+#include "../../docs/examples/Bitmap_setPixelRef.cpp"
+#include "../../docs/examples/Bitmap_setPixels.cpp"
+#include "../../docs/examples/Bitmap_shiftPerPixel.cpp"
+#include "../../docs/examples/Bitmap_swap.cpp"
+#include "../../docs/examples/Bitmap_tryAllocN32Pixels.cpp"
+#include "../../docs/examples/Bitmap_tryAllocPixels.cpp"
+#include "../../docs/examples/Bitmap_tryAllocPixelsFlags.cpp"
+#include "../../docs/examples/Bitmap_tryAllocPixels_2.cpp"
+#include "../../docs/examples/Bitmap_tryAllocPixels_3.cpp"
+#include "../../docs/examples/Bitmap_tryAllocPixels_4.cpp"
+#include "../../docs/examples/Bitmap_width.cpp"
+#include "../../docs/examples/Bitmap_writePixels.cpp"
+#include "../../docs/examples/Bitmap_writePixels_2.cpp"
+#include "../../docs/examples/BlendMode_Name.cpp"
+#include "../../docs/examples/Blend_Mode_Methods.cpp"
+#include "../../docs/examples/Canvas_129.cpp"
+#include "../../docs/examples/Canvas_MakeRasterDirect.cpp"
+#include "../../docs/examples/Canvas_MakeRasterDirectN32.cpp"
+#include "../../docs/examples/Canvas_PointMode.cpp"
+#include "../../docs/examples/Canvas_SaveLayerRec.cpp"
+#include "../../docs/examples/Canvas_SaveLayerRec_SaveLayerRec.cpp"
+#include "../../docs/examples/Canvas_SaveLayerRec_const_SkRect_star_const_SkPaint_star.cpp"
+#include "../../docs/examples/Canvas_SaveLayerRec_const_SkRect_star_const_SkPaint_star_const_SkImageFilter_star.cpp"
+#include "../../docs/examples/Canvas_SrcRectConstraint.cpp"
+#include "../../docs/examples/Canvas_accessTopLayerPixels_a.cpp"
+#include "../../docs/examples/Canvas_accessTopLayerPixels_b.cpp"
+#include "../../docs/examples/Canvas_accessTopRasterHandle.cpp"
+#include "../../docs/examples/Canvas_clear.cpp"
+#include "../../docs/examples/Canvas_clipPath.cpp"
+#include "../../docs/examples/Canvas_clipPath_2.cpp"
+#include "../../docs/examples/Canvas_clipPath_3.cpp"
+#include "../../docs/examples/Canvas_clipRRect.cpp"
+#include "../../docs/examples/Canvas_clipRRect_2.cpp"
+#include "../../docs/examples/Canvas_clipRRect_3.cpp"
+#include "../../docs/examples/Canvas_clipRect.cpp"
+#include "../../docs/examples/Canvas_clipRect_2.cpp"
+#include "../../docs/examples/Canvas_clipRect_3.cpp"
+#include "../../docs/examples/Canvas_clipRegion.cpp"
+#include "../../docs/examples/Canvas_concat.cpp"
+#include "../../docs/examples/Canvas_const_SkBitmap_const_SkSurfaceProps.cpp"
+#include "../../docs/examples/Canvas_copy_const_SkBitmap.cpp"
+#include "../../docs/examples/Canvas_destructor.cpp"
+#include "../../docs/examples/Canvas_drawAnnotation_2.cpp"
+#include "../../docs/examples/Canvas_drawArc_a.cpp"
+#include "../../docs/examples/Canvas_drawArc_b.cpp"
+#include "../../docs/examples/Canvas_drawAtlas.cpp"
+#include "../../docs/examples/Canvas_drawAtlas_2.cpp"
+#include "../../docs/examples/Canvas_drawAtlas_3.cpp"
+#include "../../docs/examples/Canvas_drawAtlas_4.cpp"
+#include "../../docs/examples/Canvas_drawBitmap.cpp"
+#include "../../docs/examples/Canvas_drawBitmapLattice.cpp"
+#include "../../docs/examples/Canvas_drawBitmapNine.cpp"
+#include "../../docs/examples/Canvas_drawBitmapRect.cpp"
+#include "../../docs/examples/Canvas_drawBitmapRect_2.cpp"
+#include "../../docs/examples/Canvas_drawBitmapRect_3.cpp"
+#include "../../docs/examples/Canvas_drawCircle.cpp"
+#include "../../docs/examples/Canvas_drawCircle_2.cpp"
+#include "../../docs/examples/Canvas_drawColor.cpp"
+#include "../../docs/examples/Canvas_drawDRRect_a.cpp"
+#include "../../docs/examples/Canvas_drawDRRect_b.cpp"
+#include "../../docs/examples/Canvas_drawDrawable.cpp"
+#include "../../docs/examples/Canvas_drawDrawable_2.cpp"
+#include "../../docs/examples/Canvas_drawIRect.cpp"
+#include "../../docs/examples/Canvas_drawImage.cpp"
+#include "../../docs/examples/Canvas_drawImageNine.cpp"
+#include "../../docs/examples/Canvas_drawImageNine_2.cpp"
+#include "../../docs/examples/Canvas_drawImageRect.cpp"
+#include "../../docs/examples/Canvas_drawImageRect_2.cpp"
+#include "../../docs/examples/Canvas_drawImageRect_3.cpp"
+#include "../../docs/examples/Canvas_drawImageRect_4.cpp"
+#include "../../docs/examples/Canvas_drawImageRect_5.cpp"
+#include "../../docs/examples/Canvas_drawImageRect_6.cpp"
+#include "../../docs/examples/Canvas_drawImage_2.cpp"
+#include "../../docs/examples/Canvas_drawLine.cpp"
+#include "../../docs/examples/Canvas_drawLine_2.cpp"
+#include "../../docs/examples/Canvas_drawOval.cpp"
+#include "../../docs/examples/Canvas_drawPaint.cpp"
+#include "../../docs/examples/Canvas_drawPatch.cpp"
+#include "../../docs/examples/Canvas_drawPatch_2_a.cpp"
+#include "../../docs/examples/Canvas_drawPatch_2_b.cpp"
+#include "../../docs/examples/Canvas_drawPath.cpp"
+#include "../../docs/examples/Canvas_drawPicture_2.cpp"
+#include "../../docs/examples/Canvas_drawPicture_3.cpp"
+#include "../../docs/examples/Canvas_drawPicture_4.cpp"
+#include "../../docs/examples/Canvas_drawPoint.cpp"
+#include "../../docs/examples/Canvas_drawPoint_2.cpp"
+#include "../../docs/examples/Canvas_drawPoints.cpp"
+#include "../../docs/examples/Canvas_drawPosText.cpp"
+#include "../../docs/examples/Canvas_drawPosTextH.cpp"
+#include "../../docs/examples/Canvas_drawRRect.cpp"
+#include "../../docs/examples/Canvas_drawRect.cpp"
+#include "../../docs/examples/Canvas_drawRegion.cpp"
+#include "../../docs/examples/Canvas_drawRoundRect.cpp"
+#include "../../docs/examples/Canvas_drawString.cpp"
+#include "../../docs/examples/Canvas_drawString_2.cpp"
+#include "../../docs/examples/Canvas_drawText.cpp"
+#include "../../docs/examples/Canvas_drawTextBlob.cpp"
+#include "../../docs/examples/Canvas_drawTextBlob_2.cpp"
+#include "../../docs/examples/Canvas_drawTextRSXform.cpp"
+#include "../../docs/examples/Canvas_drawVertices.cpp"
+#include "../../docs/examples/Canvas_drawVertices_2.cpp"
+#include "../../docs/examples/Canvas_empty_constructor.cpp"
+#include "../../docs/examples/Canvas_getBaseLayerSize.cpp"
+#include "../../docs/examples/Canvas_getDeviceClipBounds.cpp"
+#include "../../docs/examples/Canvas_getDeviceClipBounds_2.cpp"
+#include "../../docs/examples/Canvas_getGrContext.cpp"
+#include "../../docs/examples/Canvas_getLocalClipBounds.cpp"
+#include "../../docs/examples/Canvas_getLocalClipBounds_2.cpp"
+#include "../../docs/examples/Canvas_getProps.cpp"
+#include "../../docs/examples/Canvas_getSaveCount.cpp"
+#include "../../docs/examples/Canvas_getTotalMatrix.cpp"
+#include "../../docs/examples/Canvas_imageInfo.cpp"
+#include "../../docs/examples/Canvas_int_int_const_SkSurfaceProps_star.cpp"
+#include "../../docs/examples/Canvas_isClipEmpty.cpp"
+#include "../../docs/examples/Canvas_isClipRect.cpp"
+#include "../../docs/examples/Canvas_kInitWithPrevious_SaveLayerFlag.cpp"
+#include "../../docs/examples/Canvas_makeSurface.cpp"
+#include "../../docs/examples/Canvas_peekPixels.cpp"
+#include "../../docs/examples/Canvas_quickReject.cpp"
+#include "../../docs/examples/Canvas_quickReject_2.cpp"
+#include "../../docs/examples/Canvas_readPixels_2.cpp"
+#include "../../docs/examples/Canvas_readPixels_3.cpp"
+#include "../../docs/examples/Canvas_readPixels_a.cpp"
+#include "../../docs/examples/Canvas_readPixels_b.cpp"
+#include "../../docs/examples/Canvas_resetMatrix.cpp"
+#include "../../docs/examples/Canvas_restore.cpp"
+#include "../../docs/examples/Canvas_restoreToCount.cpp"
+#include "../../docs/examples/Canvas_rotate.cpp"
+#include "../../docs/examples/Canvas_rotate_2.cpp"
+#include "../../docs/examples/Canvas_save.cpp"
+#include "../../docs/examples/Canvas_saveLayer.cpp"
+#include "../../docs/examples/Canvas_saveLayerAlpha.cpp"
+#include "../../docs/examples/Canvas_saveLayerPreserveLCDTextRequests.cpp"
+#include "../../docs/examples/Canvas_saveLayer_2.cpp"
+#include "../../docs/examples/Canvas_saveLayer_3.cpp"
+#include "../../docs/examples/Canvas_scale.cpp"
+#include "../../docs/examples/Canvas_setMatrix.cpp"
+#include "../../docs/examples/Canvas_skew.cpp"
+#include "../../docs/examples/Canvas_translate.cpp"
+#include "../../docs/examples/Canvas_writePixels.cpp"
+#include "../../docs/examples/Canvas_writePixels_2.cpp"
+#include "../../docs/examples/Clear.cpp"
+#include "../../docs/examples/Clip.cpp"
+#include "../../docs/examples/Color.cpp"
+#include "../../docs/examples/ColorGetA.cpp"
+#include "../../docs/examples/ColorGetB.cpp"
+#include "../../docs/examples/ColorGetG.cpp"
+#include "../../docs/examples/ColorGetR.cpp"
+#include "../../docs/examples/ColorSetA.cpp"
+#include "../../docs/examples/ColorSetARGB.cpp"
+#include "../../docs/examples/ColorSetRGB.cpp"
+#include "../../docs/examples/ColorToHSV.cpp"
+#include "../../docs/examples/ColorTypeBytesPerPixel.cpp"
+#include "../../docs/examples/ColorTypeIsAlwaysOpaque.cpp"
+#include "../../docs/examples/ColorTypeValidateAlphaType.cpp"
+#include "../../docs/examples/Color_Burn.cpp"
+#include "../../docs/examples/Color_Constants_a.cpp"
+#include "../../docs/examples/Color_Constants_b.cpp"
+#include "../../docs/examples/Color_Constants_c.cpp"
+#include "../../docs/examples/Color_Constants_d.cpp"
+#include "../../docs/examples/Color_Dodge.cpp"
+#include "../../docs/examples/Color_Filter_Methods.cpp"
+#include "../../docs/examples/Color_Methods.cpp"
+#include "../../docs/examples/Color_Type_ARGB_4444.cpp"
+#include "../../docs/examples/Color_Type_Alpha_8.cpp"
+#include "../../docs/examples/Color_Type_BGRA_8888.cpp"
+#include "../../docs/examples/Color_Type_Gray_8.cpp"
+#include "../../docs/examples/Color_Type_RGBA_1010102.cpp"
+#include "../../docs/examples/Color_Type_RGBA_8888.cpp"
+#include "../../docs/examples/Color_Type_RGBA_F16.cpp"
+#include "../../docs/examples/Color_Type_RGB_101010.cpp"
+#include "../../docs/examples/Color_Type_RGB_565.cpp"
+#include "../../docs/examples/Color_Type_RGB_888.cpp"
+#include "../../docs/examples/Colors.cpp"
+#include "../../docs/examples/Conic_Weight_a.cpp"
+#include "../../docs/examples/Conic_Weight_b.cpp"
+#include "../../docs/examples/Conic_Weight_c.cpp"
+#include "../../docs/examples/Cubic.cpp"
+#include "../../docs/examples/Darken.cpp"
+#include "../../docs/examples/Device_Text.cpp"
+#include "../../docs/examples/Difference.cpp"
+#include "../../docs/examples/Dither_a.cpp"
+#include "../../docs/examples/Dither_b.cpp"
+#include "../../docs/examples/Draw_Looper_Methods.cpp"
+#include "../../docs/examples/Dst.cpp"
+#include "../../docs/examples/Dst_Atop.cpp"
+#include "../../docs/examples/Dst_In.cpp"
+#include "../../docs/examples/Dst_Out.cpp"
+#include "../../docs/examples/Dst_Over.cpp"
+#include "../../docs/examples/Exclusion.cpp"
+#include "../../docs/examples/Fake_Bold.cpp"
+#include "../../docs/examples/Filter_Quality_Methods.cpp"
+#include "../../docs/examples/Font_breakText.cpp"
+#include "../../docs/examples/HSVToColor.cpp"
+#include "../../docs/examples/HSVToColor_2.cpp"
+#include "../../docs/examples/Hard_Light.cpp"
+#include "../../docs/examples/Hue.cpp"
+#include "../../docs/examples/IPoint_Make.cpp"
+#include "../../docs/examples/IPoint_add_operator.cpp"
+#include "../../docs/examples/IPoint_addto_operator.cpp"
+#include "../../docs/examples/IPoint_equal_operator.cpp"
+#include "../../docs/examples/IPoint_equals.cpp"
+#include "../../docs/examples/IPoint_isZero.cpp"
+#include "../../docs/examples/IPoint_minus_operator.cpp"
+#include "../../docs/examples/IPoint_notequal_operator.cpp"
+#include "../../docs/examples/IPoint_set.cpp"
+#include "../../docs/examples/IPoint_subtract_operator.cpp"
+#include "../../docs/examples/IPoint_subtractfrom_operator.cpp"
+#include "../../docs/examples/IPoint_x.cpp"
+#include "../../docs/examples/IPoint_y.cpp"
+#include "../../docs/examples/IRect_EmptyIRect.cpp"
+#include "../../docs/examples/IRect_Intersects.cpp"
+#include "../../docs/examples/IRect_MakeEmpty.cpp"
+#include "../../docs/examples/IRect_MakeLTRB.cpp"
+#include "../../docs/examples/IRect_MakeSize.cpp"
+#include "../../docs/examples/IRect_MakeWH.cpp"
+#include "../../docs/examples/IRect_MakeXYWH.cpp"
+#include "../../docs/examples/IRect_adjust.cpp"
+#include "../../docs/examples/IRect_bottom.cpp"
+#include "../../docs/examples/IRect_contains.cpp"
+#include "../../docs/examples/IRect_containsNoEmptyCheck.cpp"
+#include "../../docs/examples/IRect_containsNoEmptyCheck_2.cpp"
+#include "../../docs/examples/IRect_contains_3.cpp"
+#include "../../docs/examples/IRect_contains_4.cpp"
+#include "../../docs/examples/IRect_equal_operator.cpp"
+#include "../../docs/examples/IRect_height.cpp"
+#include "../../docs/examples/IRect_height64.cpp"
+#include "../../docs/examples/IRect_inset.cpp"
+#include "../../docs/examples/IRect_intersect.cpp"
+#include "../../docs/examples/IRect_intersect_2.cpp"
+#include "../../docs/examples/IRect_isEmpty.cpp"
+#include "../../docs/examples/IRect_isEmpty64.cpp"
+#include "../../docs/examples/IRect_join_2.cpp"
+#include "../../docs/examples/IRect_left.cpp"
+#include "../../docs/examples/IRect_makeInset.cpp"
+#include "../../docs/examples/IRect_makeOffset.cpp"
+#include "../../docs/examples/IRect_makeOutset.cpp"
+#include "../../docs/examples/IRect_makeSorted.cpp"
+#include "../../docs/examples/IRect_notequal_operator.cpp"
+#include "../../docs/examples/IRect_offset.cpp"
+#include "../../docs/examples/IRect_offsetTo.cpp"
+#include "../../docs/examples/IRect_offset_2.cpp"
+#include "../../docs/examples/IRect_outset.cpp"
+#include "../../docs/examples/IRect_right.cpp"
+#include "../../docs/examples/IRect_setEmpty.cpp"
+#include "../../docs/examples/IRect_setLTRB.cpp"
+#include "../../docs/examples/IRect_setXYWH.cpp"
+#include "../../docs/examples/IRect_size.cpp"
+#include "../../docs/examples/IRect_sort.cpp"
+#include "../../docs/examples/IRect_top.cpp"
+#include "../../docs/examples/IRect_width.cpp"
+#include "../../docs/examples/IRect_width64.cpp"
+#include "../../docs/examples/IRect_x.cpp"
+#include "../../docs/examples/IRect_y.cpp"
+#include "../../docs/examples/ImageInfo_ByteSizeOverflowed.cpp"
+#include "../../docs/examples/ImageInfo_Make.cpp"
+#include "../../docs/examples/ImageInfo_MakeA8.cpp"
+#include "../../docs/examples/ImageInfo_MakeN32.cpp"
+#include "../../docs/examples/ImageInfo_MakeN32Premul.cpp"
+#include "../../docs/examples/ImageInfo_MakeN32Premul_2.cpp"
+#include "../../docs/examples/ImageInfo_MakeS32.cpp"
+#include "../../docs/examples/ImageInfo_MakeUnknown.cpp"
+#include "../../docs/examples/ImageInfo_MakeUnknown_2.cpp"
+#include "../../docs/examples/ImageInfo_alphaType.cpp"
+#include "../../docs/examples/ImageInfo_bounds.cpp"
+#include "../../docs/examples/ImageInfo_bytesPerPixel.cpp"
+#include "../../docs/examples/ImageInfo_colorSpace.cpp"
+#include "../../docs/examples/ImageInfo_colorType.cpp"
+#include "../../docs/examples/ImageInfo_computeByteSize.cpp"
+#include "../../docs/examples/ImageInfo_computeMinByteSize.cpp"
+#include "../../docs/examples/ImageInfo_computeOffset.cpp"
+#include "../../docs/examples/ImageInfo_dimensions.cpp"
+#include "../../docs/examples/ImageInfo_empty_constructor.cpp"
+#include "../../docs/examples/ImageInfo_equal1_operator.cpp"
+#include "../../docs/examples/ImageInfo_gammaCloseToSRGB.cpp"
+#include "../../docs/examples/ImageInfo_height.cpp"
+#include "../../docs/examples/ImageInfo_isEmpty.cpp"
+#include "../../docs/examples/ImageInfo_isOpaque.cpp"
+#include "../../docs/examples/ImageInfo_makeAlphaType.cpp"
+#include "../../docs/examples/ImageInfo_makeColorSpace.cpp"
+#include "../../docs/examples/ImageInfo_makeColorType.cpp"
+#include "../../docs/examples/ImageInfo_makeWH.cpp"
+#include "../../docs/examples/ImageInfo_minRowBytes.cpp"
+#include "../../docs/examples/ImageInfo_minRowBytes64.cpp"
+#include "../../docs/examples/ImageInfo_notequal1_operator.cpp"
+#include "../../docs/examples/ImageInfo_refColorSpace.cpp"
+#include "../../docs/examples/ImageInfo_reset.cpp"
+#include "../../docs/examples/ImageInfo_shiftPerPixel.cpp"
+#include "../../docs/examples/ImageInfo_validRowBytes.cpp"
+#include "../../docs/examples/ImageInfo_width.cpp"
+#include "../../docs/examples/Image_Filter_Methods.cpp"
+#include "../../docs/examples/Image_MakeBackendTextureFromSkImage.cpp"
+#include "../../docs/examples/Image_MakeCrossContextFromPixmap.cpp"
+#include "../../docs/examples/Image_MakeFromAdoptedTexture.cpp"
+#include "../../docs/examples/Image_MakeFromBitmap.cpp"
+#include "../../docs/examples/Image_MakeFromEncoded.cpp"
+#include "../../docs/examples/Image_MakeFromGenerator.cpp"
+#include "../../docs/examples/Image_MakeFromPicture.cpp"
+#include "../../docs/examples/Image_MakeFromRaster.cpp"
+#include "../../docs/examples/Image_MakeFromTexture.cpp"
+#include "../../docs/examples/Image_MakeFromTexture_2.cpp"
+#include "../../docs/examples/Image_MakeRasterCopy.cpp"
+#include "../../docs/examples/Image_MakeRasterData.cpp"
+#include "../../docs/examples/Image_alphaType.cpp"
+#include "../../docs/examples/Image_bounds.cpp"
+#include "../../docs/examples/Image_colorSpace.cpp"
+#include "../../docs/examples/Image_colorType.cpp"
+#include "../../docs/examples/Image_dimensions.cpp"
+#include "../../docs/examples/Image_encodeToData.cpp"
+#include "../../docs/examples/Image_encodeToData_2.cpp"
+#include "../../docs/examples/Image_getBackendTexture.cpp"
+#include "../../docs/examples/Image_height.cpp"
+#include "../../docs/examples/Image_isAlphaOnly.cpp"
+#include "../../docs/examples/Image_isLazyGenerated_a.cpp"
+#include "../../docs/examples/Image_isLazyGenerated_b.cpp"
+#include "../../docs/examples/Image_isOpaque.cpp"
+#include "../../docs/examples/Image_isTextureBacked.cpp"
+#include "../../docs/examples/Image_isValid.cpp"
+#include "../../docs/examples/Image_makeColorSpace.cpp"
+#include "../../docs/examples/Image_makeNonTextureImage.cpp"
+#include "../../docs/examples/Image_makeRasterImage.cpp"
+#include "../../docs/examples/Image_makeShader.cpp"
+#include "../../docs/examples/Image_makeShader_2.cpp"
+#include "../../docs/examples/Image_makeSubset.cpp"
+#include "../../docs/examples/Image_makeTextureImage.cpp"
+#include "../../docs/examples/Image_makeWithFilter.cpp"
+#include "../../docs/examples/Image_peekPixels.cpp"
+#include "../../docs/examples/Image_readPixels.cpp"
+#include "../../docs/examples/Image_readPixels_2.cpp"
+#include "../../docs/examples/Image_refColorSpace.cpp"
+#include "../../docs/examples/Image_refEncodedData.cpp"
+#include "../../docs/examples/Image_scalePixels.cpp"
+#include "../../docs/examples/Image_uniqueID.cpp"
+#include "../../docs/examples/Image_width.cpp"
+#include "../../docs/examples/Lighten.cpp"
+#include "../../docs/examples/Luminosity.cpp"
+#include "../../docs/examples/Mask_Filter_Methods.cpp"
+#include "../../docs/examples/Matrix_063.cpp"
+#include "../../docs/examples/Matrix_Concat.cpp"
+#include "../../docs/examples/Matrix_I.cpp"
+#include "../../docs/examples/Matrix_InvalidMatrix.cpp"
+#include "../../docs/examples/Matrix_MakeAll.cpp"
+#include "../../docs/examples/Matrix_MakeRectToRect.cpp"
+#include "../../docs/examples/Matrix_MakeScale.cpp"
+#include "../../docs/examples/Matrix_MakeScale_2.cpp"
+#include "../../docs/examples/Matrix_MakeTrans.cpp"
+#include "../../docs/examples/Matrix_ScaleToFit.cpp"
+#include "../../docs/examples/Matrix_SetAffineIdentity.cpp"
+#include "../../docs/examples/Matrix_TypeMask.cpp"
+#include "../../docs/examples/Matrix_array_operator.cpp"
+#include "../../docs/examples/Matrix_asAffine.cpp"
+#include "../../docs/examples/Matrix_cheapEqualTo.cpp"
+#include "../../docs/examples/Matrix_decomposeScale.cpp"
+#include "../../docs/examples/Matrix_dirtyMatrixTypeCache.cpp"
+#include "../../docs/examples/Matrix_dump.cpp"
+#include "../../docs/examples/Matrix_equal_operator.cpp"
+#include "../../docs/examples/Matrix_fixedStepInX.cpp"
+#include "../../docs/examples/Matrix_get.cpp"
+#include "../../docs/examples/Matrix_get9.cpp"
+#include "../../docs/examples/Matrix_getMaxScale.cpp"
+#include "../../docs/examples/Matrix_getMinMaxScales.cpp"
+#include "../../docs/examples/Matrix_getMinScale.cpp"
+#include "../../docs/examples/Matrix_getPerspX.cpp"
+#include "../../docs/examples/Matrix_getPerspY.cpp"
+#include "../../docs/examples/Matrix_getScaleX.cpp"
+#include "../../docs/examples/Matrix_getScaleY.cpp"
+#include "../../docs/examples/Matrix_getSkewX.cpp"
+#include "../../docs/examples/Matrix_getSkewY.cpp"
+#include "../../docs/examples/Matrix_getTranslateX.cpp"
+#include "../../docs/examples/Matrix_getTranslateY.cpp"
+#include "../../docs/examples/Matrix_getType.cpp"
+#include "../../docs/examples/Matrix_hasPerspective.cpp"
+#include "../../docs/examples/Matrix_invert.cpp"
+#include "../../docs/examples/Matrix_isFinite.cpp"
+#include "../../docs/examples/Matrix_isFixedStepInX.cpp"
+#include "../../docs/examples/Matrix_isIdentity.cpp"
+#include "../../docs/examples/Matrix_isScaleTranslate.cpp"
+#include "../../docs/examples/Matrix_isSimilarity.cpp"
+#include "../../docs/examples/Matrix_isTranslate.cpp"
+#include "../../docs/examples/Matrix_mapHomogeneousPoints.cpp"
+#include "../../docs/examples/Matrix_mapPoints.cpp"
+#include "../../docs/examples/Matrix_mapPoints_2.cpp"
+#include "../../docs/examples/Matrix_mapRadius.cpp"
+#include "../../docs/examples/Matrix_mapRect.cpp"
+#include "../../docs/examples/Matrix_mapRectScaleTranslate.cpp"
+#include "../../docs/examples/Matrix_mapRectToQuad.cpp"
+#include "../../docs/examples/Matrix_mapRect_2.cpp"
+#include "../../docs/examples/Matrix_mapRect_3.cpp"
+#include "../../docs/examples/Matrix_mapVector.cpp"
+#include "../../docs/examples/Matrix_mapVector_2.cpp"
+#include "../../docs/examples/Matrix_mapVectors.cpp"
+#include "../../docs/examples/Matrix_mapVectors_2.cpp"
+#include "../../docs/examples/Matrix_mapXY.cpp"
+#include "../../docs/examples/Matrix_mapXY_2.cpp"
+#include "../../docs/examples/Matrix_notequal_operator.cpp"
+#include "../../docs/examples/Matrix_postConcat.cpp"
+#include "../../docs/examples/Matrix_postRotate.cpp"
+#include "../../docs/examples/Matrix_postRotate_2.cpp"
+#include "../../docs/examples/Matrix_postScale.cpp"
+#include "../../docs/examples/Matrix_postScale_2.cpp"
+#include "../../docs/examples/Matrix_postSkew.cpp"
+#include "../../docs/examples/Matrix_postSkew_2.cpp"
+#include "../../docs/examples/Matrix_postTranslate.cpp"
+#include "../../docs/examples/Matrix_preConcat.cpp"
+#include "../../docs/examples/Matrix_preRotate.cpp"
+#include "../../docs/examples/Matrix_preRotate_2.cpp"
+#include "../../docs/examples/Matrix_preScale.cpp"
+#include "../../docs/examples/Matrix_preScale_2.cpp"
+#include "../../docs/examples/Matrix_preSkew.cpp"
+#include "../../docs/examples/Matrix_preSkew_2.cpp"
+#include "../../docs/examples/Matrix_preTranslate.cpp"
+#include "../../docs/examples/Matrix_preservesAxisAlignment.cpp"
+#include "../../docs/examples/Matrix_preservesRightAngles.cpp"
+#include "../../docs/examples/Matrix_rectStaysRect.cpp"
+#include "../../docs/examples/Matrix_reset.cpp"
+#include "../../docs/examples/Matrix_set.cpp"
+#include "../../docs/examples/Matrix_set9.cpp"
+#include "../../docs/examples/Matrix_setAffine.cpp"
+#include "../../docs/examples/Matrix_setAll.cpp"
+#include "../../docs/examples/Matrix_setConcat.cpp"
+#include "../../docs/examples/Matrix_setIdentity.cpp"
+#include "../../docs/examples/Matrix_setPerspX.cpp"
+#include "../../docs/examples/Matrix_setPerspY.cpp"
+#include "../../docs/examples/Matrix_setPolyToPoly.cpp"
+#include "../../docs/examples/Matrix_setRSXform.cpp"
+#include "../../docs/examples/Matrix_setRectToRect.cpp"
+#include "../../docs/examples/Matrix_setRotate.cpp"
+#include "../../docs/examples/Matrix_setRotate_2.cpp"
+#include "../../docs/examples/Matrix_setScale.cpp"
+#include "../../docs/examples/Matrix_setScaleTranslate.cpp"
+#include "../../docs/examples/Matrix_setScaleX.cpp"
+#include "../../docs/examples/Matrix_setScaleY.cpp"
+#include "../../docs/examples/Matrix_setScale_2.cpp"
+#include "../../docs/examples/Matrix_setSinCos.cpp"
+#include "../../docs/examples/Matrix_setSinCos_2.cpp"
+#include "../../docs/examples/Matrix_setSkew.cpp"
+#include "../../docs/examples/Matrix_setSkewX.cpp"
+#include "../../docs/examples/Matrix_setSkewY.cpp"
+#include "../../docs/examples/Matrix_setSkew_2.cpp"
+#include "../../docs/examples/Matrix_setTranslate.cpp"
+#include "../../docs/examples/Matrix_setTranslateX.cpp"
+#include "../../docs/examples/Matrix_setTranslateY.cpp"
+#include "../../docs/examples/Matrix_setTranslate_2.cpp"
+#include "../../docs/examples/MemberIndex.cpp"
+#include "../../docs/examples/Miter_Limit.cpp"
+#include "../../docs/examples/Modulate.cpp"
+#include "../../docs/examples/Multiply.cpp"
+#include "../../docs/examples/Overlay.cpp"
+#include "../../docs/examples/PDF.cpp"
+#include "../../docs/examples/Paint_053.cpp"
+#include "../../docs/examples/Paint_057.cpp"
+#include "../../docs/examples/Paint_containsText.cpp"
+#include "../../docs/examples/Paint_copy_const_SkPaint.cpp"
+#include "../../docs/examples/Paint_copy_operator.cpp"
+#include "../../docs/examples/Paint_countText.cpp"
+#include "../../docs/examples/Paint_empty_constructor.cpp"
+#include "../../docs/examples/Paint_equal_operator.cpp"
+#include "../../docs/examples/Paint_getAlpha.cpp"
+#include "../../docs/examples/Paint_getBlendMode.cpp"
+#include "../../docs/examples/Paint_getColor.cpp"
+#include "../../docs/examples/Paint_getColor4f.cpp"
+#include "../../docs/examples/Paint_getColorFilter.cpp"
+#include "../../docs/examples/Paint_getDrawLooper.cpp"
+#include "../../docs/examples/Paint_getFillPath.cpp"
+#include "../../docs/examples/Paint_getFillPath_2.cpp"
+#include "../../docs/examples/Paint_getFilterQuality.cpp"
+#include "../../docs/examples/Paint_getFlags.cpp"
+#include "../../docs/examples/Paint_getFontMetrics.cpp"
+#include "../../docs/examples/Paint_getFontSpacing.cpp"
+#include "../../docs/examples/Paint_getHash.cpp"
+#include "../../docs/examples/Paint_getHinting.cpp"
+#include "../../docs/examples/Paint_getImageFilter.cpp"
+#include "../../docs/examples/Paint_getMaskFilter.cpp"
+#include "../../docs/examples/Paint_getPathEffect.cpp"
+#include "../../docs/examples/Paint_getPosTextPath.cpp"
+#include "../../docs/examples/Paint_getShader.cpp"
+#include "../../docs/examples/Paint_getStrokeCap.cpp"
+#include "../../docs/examples/Paint_getStrokeJoin.cpp"
+#include "../../docs/examples/Paint_getStrokeMiter.cpp"
+#include "../../docs/examples/Paint_getStrokeWidth.cpp"
+#include "../../docs/examples/Paint_getStyle.cpp"
+#include "../../docs/examples/Paint_getTextEncoding.cpp"
+#include "../../docs/examples/Paint_getTextPath.cpp"
+#include "../../docs/examples/Paint_getTextScaleX.cpp"
+#include "../../docs/examples/Paint_getTextSize.cpp"
+#include "../../docs/examples/Paint_getTextSkewX.cpp"
+#include "../../docs/examples/Paint_getTextWidths.cpp"
+#include "../../docs/examples/Paint_getTypeface.cpp"
+#include "../../docs/examples/Paint_isAntiAlias.cpp"
+#include "../../docs/examples/Paint_isAutohinted.cpp"
+#include "../../docs/examples/Paint_isDither.cpp"
+#include "../../docs/examples/Paint_isEmbeddedBitmapText.cpp"
+#include "../../docs/examples/Paint_isFakeBoldText.cpp"
+#include "../../docs/examples/Paint_isLCDRenderText.cpp"
+#include "../../docs/examples/Paint_isLinearText.cpp"
+#include "../../docs/examples/Paint_isSubpixelText.cpp"
+#include "../../docs/examples/Paint_measureText.cpp"
+#include "../../docs/examples/Paint_measureText_2.cpp"
+#include "../../docs/examples/Paint_move_SkPaint.cpp"
+#include "../../docs/examples/Paint_move_operator.cpp"
+#include "../../docs/examples/Paint_notequal_operator.cpp"
+#include "../../docs/examples/Paint_nothingToDraw.cpp"
+#include "../../docs/examples/Paint_refColorFilter.cpp"
+#include "../../docs/examples/Paint_refDrawLooper.cpp"
+#include "../../docs/examples/Paint_refImageFilter.cpp"
+#include "../../docs/examples/Paint_refMaskFilter.cpp"
+#include "../../docs/examples/Paint_refPathEffect.cpp"
+#include "../../docs/examples/Paint_refShader.cpp"
+#include "../../docs/examples/Paint_refTypeface.cpp"
+#include "../../docs/examples/Paint_reset.cpp"
+#include "../../docs/examples/Paint_setARGB.cpp"
+#include "../../docs/examples/Paint_setAlpha.cpp"
+#include "../../docs/examples/Paint_setAntiAlias.cpp"
+#include "../../docs/examples/Paint_setAutohinted.cpp"
+#include "../../docs/examples/Paint_setBlendMode.cpp"
+#include "../../docs/examples/Paint_setColor.cpp"
+#include "../../docs/examples/Paint_setColor4f.cpp"
+#include "../../docs/examples/Paint_setColorFilter.cpp"
+#include "../../docs/examples/Paint_setDither.cpp"
+#include "../../docs/examples/Paint_setDrawLooper.cpp"
+#include "../../docs/examples/Paint_setEmbeddedBitmapText.cpp"
+#include "../../docs/examples/Paint_setFakeBoldText.cpp"
+#include "../../docs/examples/Paint_setFilterQuality.cpp"
+#include "../../docs/examples/Paint_setFlags.cpp"
+#include "../../docs/examples/Paint_setHinting.cpp"
+#include "../../docs/examples/Paint_setImageFilter.cpp"
+#include "../../docs/examples/Paint_setLCDRenderText.cpp"
+#include "../../docs/examples/Paint_setLinearText.cpp"
+#include "../../docs/examples/Paint_setMaskFilter.cpp"
+#include "../../docs/examples/Paint_setPathEffect.cpp"
+#include "../../docs/examples/Paint_setShader.cpp"
+#include "../../docs/examples/Paint_setStrokeCap_a.cpp"
+#include "../../docs/examples/Paint_setStrokeCap_b.cpp"
+#include "../../docs/examples/Paint_setStrokeJoin.cpp"
+#include "../../docs/examples/Paint_setStrokeMiter.cpp"
+#include "../../docs/examples/Paint_setStrokeWidth.cpp"
+#include "../../docs/examples/Paint_setStyle.cpp"
+#include "../../docs/examples/Paint_setSubpixelText.cpp"
+#include "../../docs/examples/Paint_setTextEncoding.cpp"
+#include "../../docs/examples/Paint_setTextScaleX.cpp"
+#include "../../docs/examples/Paint_setTextSize.cpp"
+#include "../../docs/examples/Paint_setTextSkewX.cpp"
+#include "../../docs/examples/Paint_setTypeface.cpp"
+#include "../../docs/examples/Paint_textToGlyphs.cpp"
+#include "../../docs/examples/Path_AddPathMode.cpp"
+#include "../../docs/examples/Path_ArcSize.cpp"
+#include "../../docs/examples/Path_ConvertConicToQuads.cpp"
+#include "../../docs/examples/Path_ConvertToNonInverseFillType.cpp"
+#include "../../docs/examples/Path_Convexity.cpp"
+#include "../../docs/examples/Path_Direction.cpp"
+#include "../../docs/examples/Path_Effect_Methods.cpp"
+#include "../../docs/examples/Path_FillType_a.cpp"
+#include "../../docs/examples/Path_FillType_b.cpp"
+#include "../../docs/examples/Path_IsCubicDegenerate.cpp"
+#include "../../docs/examples/Path_IsInverseFillType.cpp"
+#include "../../docs/examples/Path_IsLineDegenerate.cpp"
+#include "../../docs/examples/Path_IsQuadDegenerate.cpp"
+#include "../../docs/examples/Path_Iter.cpp"
+#include "../../docs/examples/Path_Iter_Iter.cpp"
+#include "../../docs/examples/Path_Iter_conicWeight.cpp"
+#include "../../docs/examples/Path_Iter_const_SkPath.cpp"
+#include "../../docs/examples/Path_Iter_isCloseLine.cpp"
+#include "../../docs/examples/Path_Iter_isClosedContour.cpp"
+#include "../../docs/examples/Path_Iter_next.cpp"
+#include "../../docs/examples/Path_Iter_setPath.cpp"
+#include "../../docs/examples/Path_RawIter_conicWeight.cpp"
+#include "../../docs/examples/Path_RawIter_next.cpp"
+#include "../../docs/examples/Path_RawIter_peek.cpp"
+#include "../../docs/examples/Path_SegmentMask.cpp"
+#include "../../docs/examples/Path_Verb.cpp"
+#include "../../docs/examples/Path_addArc.cpp"
+#include "../../docs/examples/Path_addCircle.cpp"
+#include "../../docs/examples/Path_addOval.cpp"
+#include "../../docs/examples/Path_addOval_2.cpp"
+#include "../../docs/examples/Path_addPath.cpp"
+#include "../../docs/examples/Path_addPath_2.cpp"
+#include "../../docs/examples/Path_addPath_3.cpp"
+#include "../../docs/examples/Path_addPoly.cpp"
+#include "../../docs/examples/Path_addPoly_2.cpp"
+#include "../../docs/examples/Path_addRRect.cpp"
+#include "../../docs/examples/Path_addRRect_2.cpp"
+#include "../../docs/examples/Path_addRect.cpp"
+#include "../../docs/examples/Path_addRect_2.cpp"
+#include "../../docs/examples/Path_addRect_3.cpp"
+#include "../../docs/examples/Path_addRoundRect.cpp"
+#include "../../docs/examples/Path_addRoundRect_2.cpp"
+#include "../../docs/examples/Path_arcTo.cpp"
+#include "../../docs/examples/Path_arcTo_2_a.cpp"
+#include "../../docs/examples/Path_arcTo_2_b.cpp"
+#include "../../docs/examples/Path_arcTo_2_c.cpp"
+#include "../../docs/examples/Path_arcTo_3.cpp"
+#include "../../docs/examples/Path_arcTo_4.cpp"
+#include "../../docs/examples/Path_close.cpp"
+#include "../../docs/examples/Path_computeTightBounds.cpp"
+#include "../../docs/examples/Path_conicTo.cpp"
+#include "../../docs/examples/Path_conicTo_2.cpp"
+#include "../../docs/examples/Path_conservativelyContainsRect.cpp"
+#include "../../docs/examples/Path_contains.cpp"
+#include "../../docs/examples/Path_copy_const_SkPath.cpp"
+#include "../../docs/examples/Path_copy_operator.cpp"
+#include "../../docs/examples/Path_countPoints.cpp"
+#include "../../docs/examples/Path_countVerbs.cpp"
+#include "../../docs/examples/Path_cubicTo.cpp"
+#include "../../docs/examples/Path_cubicTo_2.cpp"
+#include "../../docs/examples/Path_destructor.cpp"
+#include "../../docs/examples/Path_dump.cpp"
+#include "../../docs/examples/Path_dumpHex.cpp"
+#include "../../docs/examples/Path_dump_2.cpp"
+#include "../../docs/examples/Path_empty_constructor.cpp"
+#include "../../docs/examples/Path_equal_operator.cpp"
+#include "../../docs/examples/Path_getBounds.cpp"
+#include "../../docs/examples/Path_getConvexity.cpp"
+#include "../../docs/examples/Path_getConvexityOrUnknown.cpp"
+#include "../../docs/examples/Path_getFillType.cpp"
+#include "../../docs/examples/Path_getGenerationID.cpp"
+#include "../../docs/examples/Path_getLastPt.cpp"
+#include "../../docs/examples/Path_getPoint.cpp"
+#include "../../docs/examples/Path_getPoints.cpp"
+#include "../../docs/examples/Path_getSegmentMasks.cpp"
+#include "../../docs/examples/Path_getVerbs.cpp"
+#include "../../docs/examples/Path_incReserve.cpp"
+#include "../../docs/examples/Path_interpolate.cpp"
+#include "../../docs/examples/Path_isConvex.cpp"
+#include "../../docs/examples/Path_isEmpty.cpp"
+#include "../../docs/examples/Path_isFinite.cpp"
+#include "../../docs/examples/Path_isInterpolatable.cpp"
+#include "../../docs/examples/Path_isInverseFillType_2.cpp"
+#include "../../docs/examples/Path_isLastContourClosed.cpp"
+#include "../../docs/examples/Path_isLine.cpp"
+#include "../../docs/examples/Path_isOval.cpp"
+#include "../../docs/examples/Path_isRRect.cpp"
+#include "../../docs/examples/Path_isRect.cpp"
+#include "../../docs/examples/Path_isVolatile.cpp"
+#include "../../docs/examples/Path_lineTo.cpp"
+#include "../../docs/examples/Path_lineTo_2.cpp"
+#include "../../docs/examples/Path_moveTo.cpp"
+#include "../../docs/examples/Path_moveTo_2.cpp"
+#include "../../docs/examples/Path_notequal_operator.cpp"
+#include "../../docs/examples/Path_offset.cpp"
+#include "../../docs/examples/Path_offset_2.cpp"
+#include "../../docs/examples/Path_quadTo.cpp"
+#include "../../docs/examples/Path_quadTo_2.cpp"
+#include "../../docs/examples/Path_rArcTo.cpp"
+#include "../../docs/examples/Path_rConicTo.cpp"
+#include "../../docs/examples/Path_rCubicTo.cpp"
+#include "../../docs/examples/Path_rLineTo.cpp"
+#include "../../docs/examples/Path_rMoveTo.cpp"
+#include "../../docs/examples/Path_rQuadTo.cpp"
+#include "../../docs/examples/Path_readFromMemory.cpp"
+#include "../../docs/examples/Path_reset.cpp"
+#include "../../docs/examples/Path_reverseAddPath.cpp"
+#include "../../docs/examples/Path_rewind.cpp"
+#include "../../docs/examples/Path_serialize.cpp"
+#include "../../docs/examples/Path_setConvexity.cpp"
+#include "../../docs/examples/Path_setFillType.cpp"
+#include "../../docs/examples/Path_setIsVolatile.cpp"
+#include "../../docs/examples/Path_setLastPt.cpp"
+#include "../../docs/examples/Path_setLastPt_2.cpp"
+#include "../../docs/examples/Path_swap.cpp"
+#include "../../docs/examples/Path_toggleInverseFillType.cpp"
+#include "../../docs/examples/Path_transform.cpp"
+#include "../../docs/examples/Path_transform_2.cpp"
+#include "../../docs/examples/Path_updateBoundsCache.cpp"
+#include "../../docs/examples/Path_writeToMemory.cpp"
+#include "../../docs/examples/Picture_008.cpp"
+#include "../../docs/examples/Picture_AbortCallback_abort.cpp"
+#include "../../docs/examples/Picture_MakeFromData.cpp"
+#include "../../docs/examples/Picture_MakeFromStream.cpp"
+#include "../../docs/examples/Picture_MakePlaceholder.cpp"
+#include "../../docs/examples/Picture_approximateBytesUsed.cpp"
+#include "../../docs/examples/Picture_approximateOpCount.cpp"
+#include "../../docs/examples/Picture_cullRect.cpp"
+#include "../../docs/examples/Picture_playback.cpp"
+#include "../../docs/examples/Picture_serialize.cpp"
+#include "../../docs/examples/Picture_serialize_2.cpp"
+#include "../../docs/examples/Picture_uniqueID.cpp"
+#include "../../docs/examples/Pixmap_addr.cpp"
+#include "../../docs/examples/Pixmap_addr16.cpp"
+#include "../../docs/examples/Pixmap_addr16_2.cpp"
+#include "../../docs/examples/Pixmap_addr32.cpp"
+#include "../../docs/examples/Pixmap_addr32_2.cpp"
+#include "../../docs/examples/Pixmap_addr64.cpp"
+#include "../../docs/examples/Pixmap_addr64_2.cpp"
+#include "../../docs/examples/Pixmap_addr8.cpp"
+#include "../../docs/examples/Pixmap_addr8_2.cpp"
+#include "../../docs/examples/Pixmap_addrF16.cpp"
+#include "../../docs/examples/Pixmap_addrF16_2.cpp"
+#include "../../docs/examples/Pixmap_addr_2.cpp"
+#include "../../docs/examples/Pixmap_alphaType.cpp"
+#include "../../docs/examples/Pixmap_bounds.cpp"
+#include "../../docs/examples/Pixmap_colorSpace.cpp"
+#include "../../docs/examples/Pixmap_colorType.cpp"
+#include "../../docs/examples/Pixmap_computeByteSize.cpp"
+#include "../../docs/examples/Pixmap_computeIsOpaque.cpp"
+#include "../../docs/examples/Pixmap_const_SkImageInfo_const_star.cpp"
+#include "../../docs/examples/Pixmap_empty_constructor.cpp"
+#include "../../docs/examples/Pixmap_erase.cpp"
+#include "../../docs/examples/Pixmap_erase_2.cpp"
+#include "../../docs/examples/Pixmap_erase_3.cpp"
+#include "../../docs/examples/Pixmap_extractSubset.cpp"
+#include "../../docs/examples/Pixmap_getColor.cpp"
+#include "../../docs/examples/Pixmap_height.cpp"
+#include "../../docs/examples/Pixmap_info.cpp"
+#include "../../docs/examples/Pixmap_isOpaque.cpp"
+#include "../../docs/examples/Pixmap_readPixels.cpp"
+#include "../../docs/examples/Pixmap_readPixels_2.cpp"
+#include "../../docs/examples/Pixmap_readPixels_3.cpp"
+#include "../../docs/examples/Pixmap_readPixels_4.cpp"
+#include "../../docs/examples/Pixmap_reset.cpp"
+#include "../../docs/examples/Pixmap_reset_2.cpp"
+#include "../../docs/examples/Pixmap_rowBytes.cpp"
+#include "../../docs/examples/Pixmap_rowBytesAsPixels.cpp"
+#include "../../docs/examples/Pixmap_scalePixels.cpp"
+#include "../../docs/examples/Pixmap_setColorSpace.cpp"
+#include "../../docs/examples/Pixmap_shiftPerPixel.cpp"
+#include "../../docs/examples/Pixmap_width.cpp"
+#include "../../docs/examples/Pixmap_writable_addr.cpp"
+#include "../../docs/examples/Pixmap_writable_addr16.cpp"
+#include "../../docs/examples/Pixmap_writable_addr32.cpp"
+#include "../../docs/examples/Pixmap_writable_addr64.cpp"
+#include "../../docs/examples/Pixmap_writable_addr8.cpp"
+#include "../../docs/examples/Pixmap_writable_addrF16.cpp"
+#include "../../docs/examples/Pixmap_writable_addr_2.cpp"
+#include "../../docs/examples/Plus.cpp"
+#include "../../docs/examples/Point_CrossProduct.cpp"
+#include "../../docs/examples/Point_Distance.cpp"
+#include "../../docs/examples/Point_DotProduct.cpp"
+#include "../../docs/examples/Point_Length.cpp"
+#include "../../docs/examples/Point_Make.cpp"
+#include "../../docs/examples/Point_Normalize.cpp"
+#include "../../docs/examples/Point_Offset.cpp"
+#include "../../docs/examples/Point_Offset_2.cpp"
+#include "../../docs/examples/Point_add_operator.cpp"
+#include "../../docs/examples/Point_addto_operator.cpp"
+#include "../../docs/examples/Point_cross.cpp"
+#include "../../docs/examples/Point_distanceToOrigin.cpp"
+#include "../../docs/examples/Point_dot.cpp"
+#include "../../docs/examples/Point_equal_operator.cpp"
+#include "../../docs/examples/Point_equals.cpp"
+#include "../../docs/examples/Point_isFinite.cpp"
+#include "../../docs/examples/Point_isZero.cpp"
+#include "../../docs/examples/Point_iset.cpp"
+#include "../../docs/examples/Point_iset_2.cpp"
+#include "../../docs/examples/Point_length_2.cpp"
+#include "../../docs/examples/Point_minus_operator.cpp"
+#include "../../docs/examples/Point_multiply_operator.cpp"
+#include "../../docs/examples/Point_multiplyby_operator.cpp"
+#include "../../docs/examples/Point_negate.cpp"
+#include "../../docs/examples/Point_normalize_2.cpp"
+#include "../../docs/examples/Point_notequal_operator.cpp"
+#include "../../docs/examples/Point_offset_3.cpp"
+#include "../../docs/examples/Point_scale.cpp"
+#include "../../docs/examples/Point_scale_2.cpp"
+#include "../../docs/examples/Point_set.cpp"
+#include "../../docs/examples/Point_setAbs.cpp"
+#include "../../docs/examples/Point_setLength.cpp"
+#include "../../docs/examples/Point_setLength_2.cpp"
+#include "../../docs/examples/Point_setNormalize.cpp"
+#include "../../docs/examples/Point_subtract_operator.cpp"
+#include "../../docs/examples/Point_subtractfrom_operator.cpp"
+#include "../../docs/examples/Point_x.cpp"
+#include "../../docs/examples/Point_y.cpp"
+#include "../../docs/examples/PreMultiplyARGB.cpp"
+#include "../../docs/examples/PreMultiplyColor.cpp"
+#include "../../docs/examples/Quad_a.cpp"
+#include "../../docs/examples/Quad_b.cpp"
+#include "../../docs/examples/RGBA4f_FromColor.cpp"
+#include "../../docs/examples/RGBA4f_equal1_operator.cpp"
+#include "../../docs/examples/RGBA4f_notequal1_operator.cpp"
+#include "../../docs/examples/RGBA4f_toSkColor.cpp"
+#include "../../docs/examples/RGBA4f_vec.cpp"
+#include "../../docs/examples/RGBA4f_vec_2.cpp"
+#include "../../docs/examples/RGBToHSV.cpp"
+#include "../../docs/examples/RRect_Corner.cpp"
+#include "../../docs/examples/RRect_MakeEmpty.cpp"
+#include "../../docs/examples/RRect_MakeOval.cpp"
+#include "../../docs/examples/RRect_MakeRect.cpp"
+#include "../../docs/examples/RRect_MakeRectXY.cpp"
+#include "../../docs/examples/RRect_Type.cpp"
+#include "../../docs/examples/RRect_contains.cpp"
+#include "../../docs/examples/RRect_copy_const_SkRRect.cpp"
+#include "../../docs/examples/RRect_copy_operator.cpp"
+#include "../../docs/examples/RRect_dump.cpp"
+#include "../../docs/examples/RRect_dumpHex.cpp"
+#include "../../docs/examples/RRect_dump_2.cpp"
+#include "../../docs/examples/RRect_empty_constructor.cpp"
+#include "../../docs/examples/RRect_equal_operator.cpp"
+#include "../../docs/examples/RRect_getBounds.cpp"
+#include "../../docs/examples/RRect_getSimpleRadii.cpp"
+#include "../../docs/examples/RRect_getType.cpp"
+#include "../../docs/examples/RRect_height.cpp"
+#include "../../docs/examples/RRect_inset.cpp"
+#include "../../docs/examples/RRect_inset_2.cpp"
+#include "../../docs/examples/RRect_isComplex.cpp"
+#include "../../docs/examples/RRect_isEmpty.cpp"
+#include "../../docs/examples/RRect_isNinePatch.cpp"
+#include "../../docs/examples/RRect_isOval.cpp"
+#include "../../docs/examples/RRect_isRect.cpp"
+#include "../../docs/examples/RRect_isSimple.cpp"
+#include "../../docs/examples/RRect_isValid.cpp"
+#include "../../docs/examples/RRect_makeOffset.cpp"
+#include "../../docs/examples/RRect_notequal_operator.cpp"
+#include "../../docs/examples/RRect_offset.cpp"
+#include "../../docs/examples/RRect_outset.cpp"
+#include "../../docs/examples/RRect_outset_2.cpp"
+#include "../../docs/examples/RRect_radii.cpp"
+#include "../../docs/examples/RRect_readFromMemory.cpp"
+#include "../../docs/examples/RRect_rect.cpp"
+#include "../../docs/examples/RRect_setEmpty.cpp"
+#include "../../docs/examples/RRect_setNinePatch.cpp"
+#include "../../docs/examples/RRect_setOval.cpp"
+#include "../../docs/examples/RRect_setRect.cpp"
+#include "../../docs/examples/RRect_setRectRadii.cpp"
+#include "../../docs/examples/RRect_setRectXY.cpp"
+#include "../../docs/examples/RRect_transform.cpp"
+#include "../../docs/examples/RRect_type_2.cpp"
+#include "../../docs/examples/RRect_width.cpp"
+#include "../../docs/examples/RRect_writeToMemory.cpp"
+#include "../../docs/examples/Rect_Intersects.cpp"
+#include "../../docs/examples/Rect_Make.cpp"
+#include "../../docs/examples/Rect_MakeEmpty.cpp"
+#include "../../docs/examples/Rect_MakeIWH.cpp"
+#include "../../docs/examples/Rect_MakeLTRB.cpp"
+#include "../../docs/examples/Rect_MakeSize.cpp"
+#include "../../docs/examples/Rect_MakeWH.cpp"
+#include "../../docs/examples/Rect_MakeXYWH.cpp"
+#include "../../docs/examples/Rect_Make_2.cpp"
+#include "../../docs/examples/Rect_asScalars.cpp"
+#include "../../docs/examples/Rect_bottom.cpp"
+#include "../../docs/examples/Rect_centerX.cpp"
+#include "../../docs/examples/Rect_centerY.cpp"
+#include "../../docs/examples/Rect_contains.cpp"
+#include "../../docs/examples/Rect_contains_2.cpp"
+#include "../../docs/examples/Rect_contains_3.cpp"
+#include "../../docs/examples/Rect_dump.cpp"
+#include "../../docs/examples/Rect_dumpHex.cpp"
+#include "../../docs/examples/Rect_dump_2.cpp"
+#include "../../docs/examples/Rect_equal_operator.cpp"
+#include "../../docs/examples/Rect_height.cpp"
+#include "../../docs/examples/Rect_inset.cpp"
+#include "../../docs/examples/Rect_intersect.cpp"
+#include "../../docs/examples/Rect_intersect_2.cpp"
+#include "../../docs/examples/Rect_intersect_3.cpp"
+#include "../../docs/examples/Rect_intersects_2.cpp"
+#include "../../docs/examples/Rect_intersects_3.cpp"
+#include "../../docs/examples/Rect_isEmpty.cpp"
+#include "../../docs/examples/Rect_isFinite.cpp"
+#include "../../docs/examples/Rect_isSorted.cpp"
+#include "../../docs/examples/Rect_join.cpp"
+#include "../../docs/examples/Rect_joinNonEmptyArg.cpp"
+#include "../../docs/examples/Rect_joinPossiblyEmptyRect.cpp"
+#include "../../docs/examples/Rect_join_2.cpp"
+#include "../../docs/examples/Rect_left.cpp"
+#include "../../docs/examples/Rect_makeInset.cpp"
+#include "../../docs/examples/Rect_makeOffset.cpp"
+#include "../../docs/examples/Rect_makeOutset.cpp"
+#include "../../docs/examples/Rect_makeSorted.cpp"
+#include "../../docs/examples/Rect_notequal_operator.cpp"
+#include "../../docs/examples/Rect_offset.cpp"
+#include "../../docs/examples/Rect_offsetTo.cpp"
+#include "../../docs/examples/Rect_offset_2.cpp"
+#include "../../docs/examples/Rect_outset.cpp"
+#include "../../docs/examples/Rect_right.cpp"
+#include "../../docs/examples/Rect_round.cpp"
+#include "../../docs/examples/Rect_roundIn.cpp"
+#include "../../docs/examples/Rect_roundOut.cpp"
+#include "../../docs/examples/Rect_roundOut_2.cpp"
+#include "../../docs/examples/Rect_roundOut_3.cpp"
+#include "../../docs/examples/Rect_round_2.cpp"
+#include "../../docs/examples/Rect_set.cpp"
+#include "../../docs/examples/Rect_setBounds.cpp"
+#include "../../docs/examples/Rect_setBoundsCheck.cpp"
+#include "../../docs/examples/Rect_setBoundsNoCheck.cpp"
+#include "../../docs/examples/Rect_setEmpty.cpp"
+#include "../../docs/examples/Rect_setLTRB.cpp"
+#include "../../docs/examples/Rect_setWH.cpp"
+#include "../../docs/examples/Rect_setXYWH.cpp"
+#include "../../docs/examples/Rect_set_4.cpp"
+#include "../../docs/examples/Rect_sort.cpp"
+#include "../../docs/examples/Rect_toQuad.cpp"
+#include "../../docs/examples/Rect_top.cpp"
+#include "../../docs/examples/Rect_width.cpp"
+#include "../../docs/examples/Rect_x.cpp"
+#include "../../docs/examples/Rect_y.cpp"
+#include "../../docs/examples/Region_Cliperator_const_SkRegion_const_SkIRect.cpp"
+#include "../../docs/examples/Region_Cliperator_done.cpp"
+#include "../../docs/examples/Region_Cliperator_next.cpp"
+#include "../../docs/examples/Region_Cliperator_rect.cpp"
+#include "../../docs/examples/Region_Iterator_Iterator.cpp"
+#include "../../docs/examples/Region_Iterator_copy_const_SkRegion.cpp"
+#include "../../docs/examples/Region_Iterator_done.cpp"
+#include "../../docs/examples/Region_Iterator_next.cpp"
+#include "../../docs/examples/Region_Iterator_rect.cpp"
+#include "../../docs/examples/Region_Iterator_reset.cpp"
+#include "../../docs/examples/Region_Iterator_rewind.cpp"
+#include "../../docs/examples/Region_Iterator_rgn.cpp"
+#include "../../docs/examples/Region_Op.cpp"
+#include "../../docs/examples/Region_Spanerator_const_SkRegion_int_int_int.cpp"
+#include "../../docs/examples/Region_Spanerator_next.cpp"
+#include "../../docs/examples/Region_computeRegionComplexity.cpp"
+#include "../../docs/examples/Region_contains.cpp"
+#include "../../docs/examples/Region_contains_2.cpp"
+#include "../../docs/examples/Region_contains_3.cpp"
+#include "../../docs/examples/Region_copy_const_SkIRect.cpp"
+#include "../../docs/examples/Region_copy_const_SkRegion.cpp"
+#include "../../docs/examples/Region_copy_operator.cpp"
+#include "../../docs/examples/Region_destructor.cpp"
+#include "../../docs/examples/Region_empty_constructor.cpp"
+#include "../../docs/examples/Region_equal1_operator.cpp"
+#include "../../docs/examples/Region_getBoundaryPath.cpp"
+#include "../../docs/examples/Region_getBounds.cpp"
+#include "../../docs/examples/Region_intersects.cpp"
+#include "../../docs/examples/Region_intersects_2.cpp"
+#include "../../docs/examples/Region_isComplex.cpp"
+#include "../../docs/examples/Region_isEmpty.cpp"
+#include "../../docs/examples/Region_isRect.cpp"
+#include "../../docs/examples/Region_notequal1_operator.cpp"
+#include "../../docs/examples/Region_op_1.cpp"
+#include "../../docs/examples/Region_op_2.cpp"
+#include "../../docs/examples/Region_op_3.cpp"
+#include "../../docs/examples/Region_op_4.cpp"
+#include "../../docs/examples/Region_op_5.cpp"
+#include "../../docs/examples/Region_op_6.cpp"
+#include "../../docs/examples/Region_quickContains.cpp"
+#include "../../docs/examples/Region_quickReject.cpp"
+#include "../../docs/examples/Region_quickReject_2.cpp"
+#include "../../docs/examples/Region_readFromMemory.cpp"
+#include "../../docs/examples/Region_set.cpp"
+#include "../../docs/examples/Region_setEmpty.cpp"
+#include "../../docs/examples/Region_setPath.cpp"
+#include "../../docs/examples/Region_setRect.cpp"
+#include "../../docs/examples/Region_setRects.cpp"
+#include "../../docs/examples/Region_setRegion.cpp"
+#include "../../docs/examples/Region_swap.cpp"
+#include "../../docs/examples/Region_translate.cpp"
+#include "../../docs/examples/Region_translate_2.cpp"
+#include "../../docs/examples/Region_writeToMemory.cpp"
+#include "../../docs/examples/Saturation.cpp"
+#include "../../docs/examples/Screen.cpp"
+#include "../../docs/examples/Shader_Methods_a.cpp"
+#include "../../docs/examples/Shader_Methods_b.cpp"
+#include "../../docs/examples/Soft_Light.cpp"
+#include "../../docs/examples/Src.cpp"
+#include "../../docs/examples/Src_Atop.cpp"
+#include "../../docs/examples/Src_In.cpp"
+#include "../../docs/examples/Src_Out.cpp"
+#include "../../docs/examples/Src_Over.cpp"
+#include "../../docs/examples/State_Stack_a.cpp"
+#include "../../docs/examples/State_Stack_b.cpp"
+#include "../../docs/examples/Stroke_Width.cpp"
+#include "../../docs/examples/Surface_MakeFromBackendTexture.cpp"
+#include "../../docs/examples/Surface_MakeFromBackendTextureAsRenderTarget.cpp"
+#include "../../docs/examples/Surface_MakeNull.cpp"
+#include "../../docs/examples/Surface_MakeRaster.cpp"
+#include "../../docs/examples/Surface_MakeRasterDirect.cpp"
+#include "../../docs/examples/Surface_MakeRasterDirectReleaseProc.cpp"
+#include "../../docs/examples/Surface_MakeRasterN32Premul.cpp"
+#include "../../docs/examples/Surface_MakeRaster_2.cpp"
+#include "../../docs/examples/Surface_MakeRenderTarget.cpp"
+#include "../../docs/examples/Surface_MakeRenderTarget_2.cpp"
+#include "../../docs/examples/Surface_MakeRenderTarget_3.cpp"
+#include "../../docs/examples/Surface_characterize.cpp"
+#include "../../docs/examples/Surface_draw.cpp"
+#include "../../docs/examples/Surface_draw_2.cpp"
+#include "../../docs/examples/Surface_getCanvas.cpp"
+#include "../../docs/examples/Surface_height.cpp"
+#include "../../docs/examples/Surface_makeImageSnapshot.cpp"
+#include "../../docs/examples/Surface_makeImageSnapshot_2.cpp"
+#include "../../docs/examples/Surface_makeSurface.cpp"
+#include "../../docs/examples/Surface_notifyContentWillChange.cpp"
+#include "../../docs/examples/Surface_peekPixels.cpp"
+#include "../../docs/examples/Surface_props.cpp"
+#include "../../docs/examples/Surface_readPixels.cpp"
+#include "../../docs/examples/Surface_readPixels_2.cpp"
+#include "../../docs/examples/Surface_readPixels_3.cpp"
+#include "../../docs/examples/Surface_width.cpp"
+#include "../../docs/examples/Surface_writePixels.cpp"
+#include "../../docs/examples/Surface_writePixels_2.cpp"
+#include "../../docs/examples/TextBlobBuilder_allocRun.cpp"
+#include "../../docs/examples/TextBlobBuilder_allocRunPos.cpp"
+#include "../../docs/examples/TextBlobBuilder_allocRunPosH.cpp"
+#include "../../docs/examples/TextBlobBuilder_empty_constructor.cpp"
+#include "../../docs/examples/TextBlobBuilder_make.cpp"
+#include "../../docs/examples/TextBlob_Deserialize.cpp"
+#include "../../docs/examples/TextBlob_MakeFromString.cpp"
+#include "../../docs/examples/TextBlob_MakeFromText.cpp"
+#include "../../docs/examples/TextBlob_bounds.cpp"
+#include "../../docs/examples/TextBlob_getIntercepts.cpp"
+#include "../../docs/examples/TextBlob_serialize.cpp"
+#include "../../docs/examples/TextBlob_serialize_2.cpp"
+#include "../../docs/examples/TextBlob_uniqueID.cpp"
+#include "../../docs/examples/Text_Encoding.cpp"
+#include "../../docs/examples/Text_Scale_X.cpp"
+#include "../../docs/examples/Text_Size.cpp"
+#include "../../docs/examples/Text_Skew_X.cpp"
+#include "../../docs/examples/Typeface_Methods.cpp"
+#include "../../docs/examples/Xor.cpp"
+#include "../../docs/examples/incomplete.cpp"
diff --git a/src/third_party/skia/tools/fiddle/disabled_examples.txt b/src/third_party/skia/tools/fiddle/disabled_examples.txt
new file mode 100644
index 0000000..3970425
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/disabled_examples.txt
@@ -0,0 +1,202 @@
+docs/examples/Alpha_Type_Opaque.cpp
+docs/examples/Alpha_Type_Premul.cpp
+docs/examples/Alpha_Type_Unpremul.cpp
+docs/examples/Arc.cpp
+docs/examples/Canvas_129.cpp
+docs/examples/Canvas_SaveLayerRec_SaveLayerRec.cpp
+docs/examples/Canvas_drawAnnotation_2.cpp
+docs/examples/Canvas_drawPatch_2_a.cpp
+docs/examples/Canvas_drawPosText.cpp
+docs/examples/Canvas_drawPosTextH.cpp
+docs/examples/Canvas_drawTextBlob.cpp
+docs/examples/Canvas_saveLayerPreserveLCDTextRequests.cpp
+docs/examples/ColorGetB.cpp
+docs/examples/ColorGetG.cpp
+docs/examples/ColorGetR.cpp
+docs/examples/Color_Constants_a.cpp
+docs/examples/Device_Text.cpp
+docs/examples/Fake_Bold.cpp
+docs/examples/Font_breakText.cpp
+docs/examples/ImageInfo_MakeN32.cpp
+docs/examples/ImageInfo_MakeN32Premul.cpp
+docs/examples/ImageInfo_MakeN32Premul_2.cpp
+docs/examples/ImageInfo_MakeUnknown.cpp
+docs/examples/ImageInfo_MakeUnknown_2.cpp
+docs/examples/ImageInfo_empty_constructor.cpp
+docs/examples/ImageInfo_gammaCloseToSRGB.cpp
+docs/examples/ImageInfo_height.cpp
+docs/examples/ImageInfo_makeColorSpace.cpp
+docs/examples/ImageInfo_width.cpp
+docs/examples/Image_alphaType.cpp
+docs/examples/Image_colorSpace.cpp
+docs/examples/Image_getBackendTexture.cpp
+docs/examples/Image_height.cpp
+docs/examples/Image_isLazyGenerated_a.cpp
+docs/examples/Image_isLazyGenerated_b.cpp
+docs/examples/Image_isTextureBacked.cpp
+docs/examples/Image_isValid.cpp
+docs/examples/Image_makeColorSpace.cpp
+docs/examples/Image_makeNonTextureImage.cpp
+docs/examples/Image_makeRasterImage.cpp
+docs/examples/Image_makeTextureImage.cpp
+docs/examples/Image_peekPixels.cpp
+docs/examples/Image_refColorSpace.cpp
+docs/examples/Image_refEncodedData.cpp
+docs/examples/Image_uniqueID.cpp
+docs/examples/Image_width.cpp
+docs/examples/Matrix_MakeAll.cpp
+docs/examples/Matrix_ScaleToFit.cpp
+docs/examples/Matrix_getPerspX.cpp
+docs/examples/Matrix_getPerspY.cpp
+docs/examples/Matrix_hasPerspective.cpp
+docs/examples/Matrix_isSimilarity.cpp
+docs/examples/Matrix_mapRadius.cpp
+docs/examples/Matrix_mapVector.cpp
+docs/examples/Matrix_mapVector_2.cpp
+docs/examples/Matrix_preservesRightAngles.cpp
+docs/examples/Matrix_setAll.cpp
+docs/examples/Matrix_setPolyToPoly.cpp
+docs/examples/Matrix_setScale.cpp
+docs/examples/Matrix_setScaleX.cpp
+docs/examples/Matrix_setScaleY.cpp
+docs/examples/Matrix_setScale_2.cpp
+docs/examples/Matrix_setSkew.cpp
+docs/examples/Matrix_setSkewX.cpp
+docs/examples/Matrix_setSkewY.cpp
+docs/examples/Matrix_setSkew_2.cpp
+docs/examples/Matrix_setTranslate.cpp
+docs/examples/Matrix_setTranslateX.cpp
+docs/examples/Matrix_setTranslateY.cpp
+docs/examples/Matrix_setTranslate_2.cpp
+docs/examples/MemberIndex.cpp
+docs/examples/Paint_containsText.cpp
+docs/examples/Paint_countText.cpp
+docs/examples/Paint_getFlags.cpp
+docs/examples/Paint_getFontMetrics.cpp
+docs/examples/Paint_getFontSpacing.cpp
+docs/examples/Paint_getHinting.cpp
+docs/examples/Paint_getPosTextPath.cpp
+docs/examples/Paint_getTextEncoding.cpp
+docs/examples/Paint_getTextPath.cpp
+docs/examples/Paint_getTextScaleX.cpp
+docs/examples/Paint_getTextSize.cpp
+docs/examples/Paint_getTextSkewX.cpp
+docs/examples/Paint_getTextWidths.cpp
+docs/examples/Paint_getTypeface.cpp
+docs/examples/Paint_isAntiAlias.cpp
+docs/examples/Paint_isAutohinted.cpp
+docs/examples/Paint_isDither.cpp
+docs/examples/Paint_isEmbeddedBitmapText.cpp
+docs/examples/Paint_isFakeBoldText.cpp
+docs/examples/Paint_isLCDRenderText.cpp
+docs/examples/Paint_isLinearText.cpp
+docs/examples/Paint_isSubpixelText.cpp
+docs/examples/Paint_measureText.cpp
+docs/examples/Paint_measureText_2.cpp
+docs/examples/Paint_refTypeface.cpp
+docs/examples/Paint_setAntiAlias.cpp
+docs/examples/Paint_setAutohinted.cpp
+docs/examples/Paint_setDither.cpp
+docs/examples/Paint_setEmbeddedBitmapText.cpp
+docs/examples/Paint_setFakeBoldText.cpp
+docs/examples/Paint_setFlags.cpp
+docs/examples/Paint_setHinting.cpp
+docs/examples/Paint_setImageFilter.cpp
+docs/examples/Paint_setLCDRenderText.cpp
+docs/examples/Paint_setLinearText.cpp
+docs/examples/Paint_setSubpixelText.cpp
+docs/examples/Paint_setTextEncoding.cpp
+docs/examples/Paint_setTextScaleX.cpp
+docs/examples/Paint_setTextSize.cpp
+docs/examples/Paint_setTextSkewX.cpp
+docs/examples/Paint_setTypeface.cpp
+docs/examples/Paint_textToGlyphs.cpp
+docs/examples/Path_Convexity.cpp
+docs/examples/Path_Direction.cpp
+docs/examples/Path_FillType_b.cpp
+docs/examples/Path_Iter.cpp
+docs/examples/Path_addOval_2.cpp
+docs/examples/Path_addPath.cpp
+docs/examples/Path_arcTo_2_a.cpp
+docs/examples/Path_arcTo_2_b.cpp
+docs/examples/Path_contains.cpp
+docs/examples/Path_isConvex.cpp
+docs/examples/Path_lineTo.cpp
+docs/examples/Path_rMoveTo.cpp
+docs/examples/Path_setLastPt.cpp
+docs/examples/Path_setLastPt_2.cpp
+docs/examples/Path_toggleInverseFillType.cpp
+docs/examples/Picture_approximateBytesUsed.cpp
+docs/examples/Picture_approximateOpCount.cpp
+docs/examples/Pixmap_setColorSpace.cpp
+docs/examples/Point_CrossProduct.cpp
+docs/examples/Point_Distance.cpp
+docs/examples/Point_DotProduct.cpp
+docs/examples/Point_Length.cpp
+docs/examples/Point_Normalize.cpp
+docs/examples/Point_cross.cpp
+docs/examples/Point_distanceToOrigin.cpp
+docs/examples/Point_dot.cpp
+docs/examples/Point_length_2.cpp
+docs/examples/PreMultiplyARGB.cpp
+docs/examples/PreMultiplyColor.cpp
+docs/examples/RGBToHSV.cpp
+docs/examples/RRect_MakeEmpty.cpp
+docs/examples/RRect_Type.cpp
+docs/examples/RRect_contains.cpp
+docs/examples/RRect_equal_operator.cpp
+docs/examples/RRect_getSimpleRadii.cpp
+docs/examples/RRect_getType.cpp
+docs/examples/RRect_isComplex.cpp
+docs/examples/RRect_isEmpty.cpp
+docs/examples/RRect_isNinePatch.cpp
+docs/examples/RRect_isOval.cpp
+docs/examples/RRect_isRect.cpp
+docs/examples/RRect_isSimple.cpp
+docs/examples/RRect_isValid.cpp
+docs/examples/RRect_notequal_operator.cpp
+docs/examples/RRect_readFromMemory.cpp
+docs/examples/RRect_transform.cpp
+docs/examples/RRect_type_2.cpp
+docs/examples/RRect_writeToMemory.cpp
+docs/examples/Region_Op.cpp
+docs/examples/Region_contains.cpp
+docs/examples/Region_contains_2.cpp
+docs/examples/Region_contains_3.cpp
+docs/examples/Region_intersects.cpp
+docs/examples/Region_intersects_2.cpp
+docs/examples/Region_op_1.cpp
+docs/examples/Region_op_2.cpp
+docs/examples/Region_op_3.cpp
+docs/examples/Region_op_4.cpp
+docs/examples/Region_op_5.cpp
+docs/examples/Region_op_6.cpp
+docs/examples/Region_setPath.cpp
+docs/examples/Region_writeToMemory.cpp
+docs/examples/Surface_MakeFromBackendTexture.cpp
+docs/examples/Surface_MakeFromBackendTextureAsRenderTarget.cpp
+docs/examples/Surface_MakeRenderTarget.cpp
+docs/examples/Surface_MakeRenderTarget_2.cpp
+docs/examples/Surface_MakeRenderTarget_3.cpp
+docs/examples/Surface_characterize.cpp
+docs/examples/Surface_draw_2.cpp
+docs/examples/Surface_getCanvas.cpp
+docs/examples/Surface_peekPixels.cpp
+docs/examples/Surface_readPixels.cpp
+docs/examples/Surface_writePixels.cpp
+docs/examples/TextBlobBuilder_allocRun.cpp
+docs/examples/TextBlobBuilder_allocRunPos.cpp
+docs/examples/TextBlobBuilder_allocRunPosH.cpp
+docs/examples/TextBlobBuilder_make.cpp
+docs/examples/TextBlob_Deserialize.cpp
+docs/examples/TextBlob_MakeFromString.cpp
+docs/examples/TextBlob_MakeFromText.cpp
+docs/examples/TextBlob_bounds.cpp
+docs/examples/TextBlob_getIntercepts.cpp
+docs/examples/TextBlob_serialize.cpp
+docs/examples/TextBlob_uniqueID.cpp
+docs/examples/Text_Encoding.cpp
+docs/examples/Text_Scale_X.cpp
+docs/examples/Text_Size.cpp
+docs/examples/Text_Skew_X.cpp
+docs/examples/Typeface_Methods.cpp
diff --git a/src/third_party/skia/tools/fiddle/documumentation_examples_map.txt b/src/third_party/skia/tools/fiddle/documumentation_examples_map.txt
new file mode 100644
index 0000000..a1acd1c
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/documumentation_examples_map.txt
@@ -0,0 +1,4103 @@
+
+This file contains a mapping from where these documumentation examples
+should be inserted into the headers.
+
+###########################################################################
+
+[AutoCanvasRestore_SkCanvas_star]
+SkAutoCanvasRestore
+SkAutoCanvasRestore(SkCanvas* canvas, bool doSave);
+
+[AutoCanvasRestore_restore]
+SkAutoCanvasRestore
+void restore();
+
+[Bitmap_ComputeIsOpaque]
+SkBitmap
+static bool ComputeIsOpaque(const SkBitmap& bm);
+
+[Bitmap_empty_constructor]
+SkBitmap
+SkBitmap();
+
+[Bitmap_move_SkBitmap]
+SkBitmap
+SkBitmap(SkBitmap&& src);
+
+[Bitmap_copy_const_SkBitmap]
+SkBitmap
+SkBitmap(const SkBitmap& src);
+
+[Bitmap_allocN32Pixels]
+SkBitmap
+void allocN32Pixels(int width, int height, bool isOpaque = false);
+
+[Bitmap_HeapAllocator_allocPixelRef]
+SkBitmap
+bool allocPixelRef(SkBitmap* bitmap) override;
+
+[Bitmap_allocPixels_3]
+SkBitmap
+void allocPixels();
+
+[Bitmap_allocPixels_4]
+SkBitmap
+void allocPixels(Allocator* allocator);
+
+[Bitmap_allocPixels_2]
+SkBitmap
+void allocPixels(const SkImageInfo& info);
+
+[Bitmap_allocPixels]
+SkBitmap
+void allocPixels(const SkImageInfo& info, size_t rowBytes);
+
+[Bitmap_allocPixelsFlags]
+SkBitmap
+void allocPixelsFlags(const SkImageInfo& info, uint32_t flags);
+
+[Pixmap_alphaType]
+SkBitmap
+SkAlphaType alphaType() const;
+
+[Bitmap_bounds]
+SkBitmap
+SkIRect bounds() const;
+
+[Bitmap_bytesPerPixel]
+SkBitmap
+int bytesPerPixel() const;
+
+[Bitmap_colorSpace]
+SkBitmap
+SkColorSpace* colorSpace() const;
+
+[Bitmap_colorType]
+SkBitmap
+SkColorType colorType() const;
+
+[Bitmap_computeByteSize]
+SkBitmap
+size_t computeByteSize() const;
+
+[Bitmap_dimensions]
+SkBitmap
+SkISize dimensions() const;
+
+[Bitmap_drawsNothing]
+SkBitmap
+bool drawsNothing() const;
+
+[Bitmap_empty]
+SkBitmap
+bool empty() const;
+
+[Bitmap_erase]
+SkBitmap
+void erase(SkColor c, const SkIRect& area) const;
+
+[Bitmap_eraseARGB]
+SkBitmap
+void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
+
+[Bitmap_eraseColor]
+SkBitmap
+void eraseColor(SkColor c) const;
+
+[Bitmap_extractAlpha]
+SkBitmap
+bool extractAlpha(SkBitmap* dst) const;
+
+[Bitmap_extractAlpha_3]
+SkBitmap
+bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator, SkIPoint* offset) const;
+
+[Bitmap_extractAlpha_2]
+SkBitmap
+bool extractAlpha(SkBitmap* dst, const SkPaint* paint, SkIPoint* offset) const;
+
+[Bitmap_extractSubset]
+SkBitmap
+bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
+
+[Bitmap_getAddr]
+SkBitmap
+void* getAddr(int x, int y) const;
+
+[Bitmap_getAddr16]
+SkBitmap
+uint16_t* getAddr16(int x, int y) const;
+
+[Bitmap_getAddr32]
+SkBitmap
+uint32_t* getAddr32(int x, int y) const;
+
+[Bitmap_getAddr8]
+SkBitmap
+uint8_t* getAddr8(int x, int y) const;
+
+[Bitmap_getBounds_2]
+SkBitmap
+void getBounds(SkIRect* bounds) const;
+
+[Bitmap_getBounds]
+SkBitmap
+void getBounds(SkRect* bounds) const;
+
+[Bitmap_getColor]
+SkBitmap
+SkColor getColor(int x, int y) const;
+
+[Bitmap_getGenerationID]
+SkBitmap
+uint32_t getGenerationID() const;
+
+[Bitmap_getPixels]
+SkBitmap
+void* getPixels() const;
+
+[Bitmap_getSubset]
+SkBitmap
+SkIRect getSubset() const;
+
+[Bitmap_height]
+SkBitmap
+int height() const;
+
+[Bitmap_info]
+SkBitmap
+const SkImageInfo& info() const;
+
+[Bitmap_installPixels_2]
+SkBitmap
+bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
+
+[Bitmap_installPixels]
+SkBitmap
+bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, void (*releaseProc) (void* addr, void* context) , void* context);
+
+[Bitmap_installPixels_3]
+SkBitmap
+bool installPixels(const SkPixmap& pixmap);
+
+[Bitmap_isImmutable]
+SkBitmap
+bool isImmutable() const;
+
+[Bitmap_isNull]
+SkBitmap
+bool isNull() const;
+
+[Bitmap_isOpaque]
+SkBitmap
+bool isOpaque() const;
+
+[Bitmap_isVolatile]
+SkBitmap
+bool isVolatile() const;
+
+[Bitmap_notifyPixelsChanged]
+SkBitmap
+void notifyPixelsChanged() const;
+
+[Bitmap_move_operator]
+SkBitmap
+SkBitmap& operator=(SkBitmap&& src);
+
+[Bitmap_copy_operator]
+SkBitmap
+SkBitmap& operator=(const SkBitmap& src);
+
+[Bitmap_peekPixels]
+SkBitmap
+bool peekPixels(SkPixmap* pixmap) const;
+
+[Bitmap_pixelRef]
+SkBitmap
+SkPixelRef* pixelRef() const;
+
+[Bitmap_pixelRefOrigin]
+SkBitmap
+SkIPoint pixelRefOrigin() const;
+
+[Bitmap_pixmap]
+SkBitmap
+const SkPixmap& pixmap() const;
+
+[Bitmap_readPixels]
+SkBitmap
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY) const;
+
+[Bitmap_readPixels_3]
+SkBitmap
+bool readPixels(const SkPixmap& dst) const;
+
+[Bitmap_readPixels_2]
+SkBitmap
+bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
+
+[Bitmap_readyToDraw]
+SkBitmap
+bool readyToDraw() const;
+
+[Bitmap_refColorSpace]
+SkBitmap
+sk_sp<SkColorSpace> refColorSpace() const;
+
+[Bitmap_reset]
+SkBitmap
+void reset();
+
+[Bitmap_rowBytes]
+SkBitmap
+size_t rowBytes() const;
+
+[Bitmap_rowBytesAsPixels]
+SkBitmap
+int rowBytesAsPixels() const;
+
+[Bitmap_setAlphaType]
+SkBitmap
+bool setAlphaType(SkAlphaType alphaType);
+
+[Bitmap_setImmutable]
+SkBitmap
+void setImmutable();
+
+[Bitmap_setInfo]
+SkBitmap
+bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);
+
+[Bitmap_setIsVolatile]
+SkBitmap
+void setIsVolatile(bool isVolatile);
+
+[Bitmap_setPixelRef]
+SkBitmap
+void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);
+
+[Bitmap_setPixels]
+SkBitmap
+void setPixels(void* pixels);
+
+[Bitmap_shiftPerPixel]
+SkBitmap
+int shiftPerPixel() const;
+
+[Bitmap_swap]
+SkBitmap
+void swap(SkBitmap& other);
+
+[Bitmap_tryAllocN32Pixels]
+SkBitmap
+bool tryAllocN32Pixels(int width, int height, bool isOpaque = false);
+
+[Bitmap_tryAllocPixels_3]
+SkBitmap
+bool tryAllocPixels();
+
+[Bitmap_tryAllocPixels_4]
+SkBitmap
+bool tryAllocPixels(Allocator* allocator);
+
+[Bitmap_tryAllocPixels_2]
+SkBitmap
+bool tryAllocPixels(const SkImageInfo& info);
+
+[Bitmap_tryAllocPixels]
+SkBitmap
+bool tryAllocPixels(const SkImageInfo& info, size_t rowBytes);
+
+[Bitmap_tryAllocPixelsFlags]
+SkBitmap
+bool tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);
+
+[Bitmap_width]
+SkBitmap
+int width() const;
+
+[Bitmap_writePixels_2]
+SkBitmap
+bool writePixels(const SkPixmap& src);
+
+[Bitmap_writePixels]
+SkBitmap
+bool writePixels(const SkPixmap& src, int dstX, int dstY);
+
+[BlendMode_Name]
+SkBlendMode
+const char* SkBlendMode_Name(SkBlendMode blendMode);
+
+[Clear]
+[Color]
+[Color_Burn]
+[Color_Dodge]
+[Darken]
+[Difference]
+[Dst]
+[Dst_Atop]
+[Dst_In]
+[Dst_Out]
+[Dst_Over]
+[Exclusion]
+[Hard_Light]
+[Hue]
+[Lighten]
+[Luminosity]
+[Modulate]
+[Multiply]
+[Overlay]
+[Plus]
+[Saturation]
+[Screen]
+[Soft_Light]
+[Src]
+[Src_Atop]
+[Src_In]
+[Src_Out]
+[Src_Over]
+[Xor]
+SkBlendMode
+enum class SkBlendMode { kClear, kSrc, kDst, kSrcOver, kDstOver, kSrcIn, kDstIn, kSrcOut, kDstOut, kSrcATop, kDstATop, kXor, kPlus, kModulate, kScreen, kLastCoeffMode = kScreen, kOverlay, kDarken, kLighten, kColorDodge, kColorBurn, kHardLight, kSoftLight, kDifference, kExclusion, kMultiply, kLastSeparableMode = kMultiply, kHue, kSaturation, kColor, kLuminosity, kLastMode = kLuminosity, }; const char* SkBlendMode_Name(SkBlendMode blendMode);
+
+[Canvas_MakeRasterDirect]
+SkCanvas
+static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkSurfaceProps* props = nullptr);
+
+[Canvas_MakeRasterDirectN32]
+SkCanvas
+static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes);
+
+[Canvas_SaveLayerRec]
+SkCanvas
+struct SaveLayerRec { SaveLayerRec(); SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0); SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, SaveLayerFlags saveLayerFlags); const SkRect* fBounds = nullptr; const SkPaint* fPaint = nullptr; const SkImageFilter* fBackdrop = nullptr; const SkImage* fClipMask = nullptr; const SkMatrix* fClipMatrix = nullptr; SaveLayerFlags fSaveLayerFlags = 0; };
+
+[Canvas_SaveLayerRec_SaveLayerRec]
+SkCanvas
+SaveLayerRec();
+
+[Canvas_SaveLayerRec_const_SkRect_star_const_SkPaint_star]
+SkCanvas
+SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0);
+
+[Canvas_SaveLayerRec_const_SkRect_star_const_SkPaint_star_const_SkImageFilter_star]
+SkCanvas
+SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, SaveLayerFlags saveLayerFlags);
+
+[Canvas_copy_const_SkBitmap]
+SkCanvas
+explicit SkCanvas(const SkBitmap& bitmap);
+
+[Canvas_empty_constructor]
+SkCanvas
+SkCanvas();
+
+[Canvas_const_SkBitmap_const_SkSurfaceProps]
+SkCanvas
+SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
+
+[Canvas_int_int_const_SkSurfaceProps_star]
+SkCanvas
+SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
+
+[Canvas_accessTopLayerPixels_a]
+[Canvas_accessTopLayerPixels_b]
+SkCanvas
+void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);
+
+[Canvas_accessTopRasterHandle]
+SkCanvas
+SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
+
+[Canvas_clear]
+SkCanvas
+void clear(SkColor color);
+
+[Canvas_clipPath_2]
+SkCanvas
+void clipPath(const SkPath& path, SkClipOp op);
+
+[Canvas_clipPath]
+SkCanvas
+void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
+
+[Canvas_clipPath_3]
+SkCanvas
+void clipPath(const SkPath& path, bool doAntiAlias = false);
+
+[Canvas_clipRRect_2]
+SkCanvas
+void clipRRect(const SkRRect& rrect, SkClipOp op);
+
+[Canvas_clipRRect]
+SkCanvas
+void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
+
+[Canvas_clipRRect_3]
+SkCanvas
+void clipRRect(const SkRRect& rrect, bool doAntiAlias = false);
+
+[Canvas_clipRect_2]
+SkCanvas
+void clipRect(const SkRect& rect, SkClipOp op);
+
+[Canvas_clipRect]
+SkCanvas
+void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
+
+[Canvas_clipRect_3]
+SkCanvas
+void clipRect(const SkRect& rect, bool doAntiAlias = false);
+
+[Canvas_clipRegion]
+SkCanvas
+void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
+
+[Canvas_concat]
+SkCanvas
+void concat(const SkMatrix& matrix);
+
+[Canvas_drawAnnotation_2]
+SkCanvas
+void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
+
+[Canvas_drawAnnotation_2]
+SkCanvas
+void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value);
+
+[Canvas_drawArc_a]
+[Canvas_drawArc_b]
+SkCanvas
+void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
+
+[Canvas_drawAtlas]
+SkCanvas
+void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, const SkPaint* paint);
+
+[Canvas_drawAtlas_3]
+SkCanvas
+void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count, const SkRect* cullRect, const SkPaint* paint);
+
+[Canvas_drawAtlas_2]
+SkCanvas
+void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, const SkPaint* paint);
+
+[Canvas_drawAtlas_4]
+SkCanvas
+void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], int count, const SkRect* cullRect, const SkPaint* paint);
+
+[Canvas_drawBitmap]
+SkCanvas
+void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint = nullptr);
+
+[Canvas_drawBitmapLattice]
+SkCanvas
+void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, const SkPaint* paint = nullptr);
+
+[Canvas_drawBitmapNine]
+SkCanvas
+void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint = nullptr);
+
+[Canvas_drawBitmapRect_2]
+SkCanvas
+void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawBitmapRect_3]
+SkCanvas
+void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawBitmapRect]
+SkCanvas
+void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawCircle_2]
+SkCanvas
+void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint);
+
+[Canvas_drawCircle]
+SkCanvas
+void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
+
+[Canvas_drawColor]
+SkCanvas
+void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
+
+[Canvas_drawDRRect_a]
+[Canvas_drawDRRect_b]
+SkCanvas
+void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+
+[Canvas_drawDrawable_2]
+SkCanvas
+void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
+
+[Canvas_drawDrawable]
+SkCanvas
+void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);
+
+[Canvas_drawIRect]
+SkCanvas
+void drawIRect(const SkIRect& rect, const SkPaint& paint);
+
+[Canvas_drawImage]
+SkCanvas
+void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr);
+
+[Canvas_drawImage_2]
+SkCanvas
+void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr);
+
+[Canvas_drawImageNine]
+SkCanvas
+void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, const SkPaint* paint = nullptr);
+
+[Canvas_drawImageNine]
+SkCanvas
+void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, const SkPaint* paint = nullptr);
+
+[Canvas_drawImageNine_2]
+SkCanvas
+void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst, const SkPaint* paint = nullptr);
+
+[Canvas_drawImageRect_2]
+SkCanvas
+void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawImageRect_3]
+SkCanvas
+void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint);
+
+[Canvas_drawImageRect]
+SkCanvas
+void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawImageRect_5]
+SkCanvas
+void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawImageRect_6]
+SkCanvas
+void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint);
+
+[Canvas_drawImageRect_4]
+SkCanvas
+void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+[Canvas_drawLine_2]
+SkCanvas
+void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint);
+
+[Canvas_drawLine]
+SkCanvas
+void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
+
+[Canvas_drawOval]
+SkCanvas
+void drawOval(const SkRect& oval, const SkPaint& paint);
+
+[Canvas_drawPaint]
+SkCanvas
+void drawPaint(const SkPaint& paint);
+
+[Canvas_drawPatch]
+SkCanvas
+void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+
+[Canvas_drawPatch_2_a]
+[Canvas_drawPatch_2_b]
+SkCanvas
+void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], const SkPaint& paint);
+
+[Canvas_drawPath]
+SkCanvas
+void drawPath(const SkPath& path, const SkPaint& paint);
+
+[Canvas_drawPicture_2]
+SkCanvas
+void drawPicture(const SkPicture* picture);
+
+[Canvas_drawPicture_3]
+SkCanvas
+void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
+
+[Canvas_drawPicture_2]
+SkCanvas
+void drawPicture(const sk_sp<SkPicture>& picture);
+
+[Canvas_drawPicture_4]
+SkCanvas
+void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint);
+
+[Canvas_drawPoint_2]
+SkCanvas
+void drawPoint(SkPoint p, const SkPaint& paint);
+
+[Canvas_drawPoint]
+SkCanvas
+void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawPoints]
+SkCanvas
+void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
+
+[Canvas_drawPosText]
+SkCanvas
+void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint);
+
+[Canvas_drawPosTextH]
+SkCanvas
+void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint);
+
+[Canvas_drawRRect]
+SkCanvas
+void drawRRect(const SkRRect& rrect, const SkPaint& paint);
+
+[Canvas_drawRect]
+SkCanvas
+void drawRect(const SkRect& rect, const SkPaint& paint);
+
+[Canvas_drawRegion]
+SkCanvas
+void drawRegion(const SkRegion& region, const SkPaint& paint);
+
+[Canvas_drawRoundRect]
+SkCanvas
+void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
+
+[Canvas_drawString_2]
+SkCanvas
+void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawString]
+SkCanvas
+void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawText]
+SkCanvas
+void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawTextBlob]
+SkCanvas
+void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawTextBlob_2]
+SkCanvas
+void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+[Canvas_drawTextRSXform]
+SkCanvas
+void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], const SkRect* cullRect, const SkPaint& paint);
+
+[Canvas_drawVertices]
+SkCanvas
+void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
+
+[Canvas_drawVertices_2]
+SkCanvas
+void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
+
+[Canvas_PointMode]
+SkCanvas
+enum PointMode { kPoints_PointMode, kLines_PointMode, kPolygon_PointMode, };
+
+[Canvas_kInitWithPrevious_SaveLayerFlag]
+SkCanvas
+enum SaveLayerFlagsSet { kPreserveLCDText_SaveLayerFlag = 1 << 1, kInitWithPrevious_SaveLayerFlag = 1 << 2, };
+
+[Canvas_SrcRectConstraint]
+SkCanvas
+enum SrcRectConstraint { kStrict_SrcRectConstraint, kFast_SrcRectConstraint, };
+
+[Canvas_getBaseLayerSize]
+SkCanvas
+virtual SkISize getBaseLayerSize() const;
+
+[Canvas_getDeviceClipBounds]
+SkCanvas
+SkIRect getDeviceClipBounds() const;
+
+[Canvas_getDeviceClipBounds_2]
+SkCanvas
+bool getDeviceClipBounds(SkIRect* bounds) const;
+
+[Canvas_getGrContext]
+SkCanvas
+virtual GrContext* getGrContext();
+
+[Canvas_getLocalClipBounds]
+SkCanvas
+SkRect getLocalClipBounds() const;
+
+[Canvas_getLocalClipBounds_2]
+SkCanvas
+bool getLocalClipBounds(SkRect* bounds) const;
+
+[Canvas_getProps]
+SkCanvas
+bool getProps(SkSurfaceProps* props) const;
+
+[Canvas_getSaveCount]
+SkCanvas
+int getSaveCount() const;
+
+[Canvas_getTotalMatrix]
+[Clip]
+SkCanvas
+const SkMatrix& getTotalMatrix() const;
+
+[Canvas_imageInfo]
+SkCanvas
+SkImageInfo imageInfo() const;
+
+[Canvas_isClipEmpty]
+SkCanvas
+virtual bool isClipEmpty() const;
+
+[Canvas_isClipRect]
+SkCanvas
+virtual bool isClipRect() const;
+
+[Canvas_makeSurface]
+SkCanvas
+sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
+
+[Canvas_peekPixels]
+SkCanvas
+bool peekPixels(SkPixmap* pixmap);
+
+[Canvas_quickReject_2]
+SkCanvas
+bool quickReject(const SkPath& path) const;
+
+[Canvas_quickReject]
+SkCanvas
+bool quickReject(const SkRect& rect) const;
+
+[Canvas_readPixels_3]
+SkCanvas
+bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
+
+[Canvas_readPixels_a]
+[Canvas_readPixels_b]
+SkCanvas
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY);
+
+[Canvas_readPixels_2]
+SkCanvas
+bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
+
+[Canvas_resetMatrix]
+SkCanvas
+void resetMatrix();
+
+[Canvas_restore]
+SkCanvas
+void restore();
+
+[Canvas_restoreToCount]
+SkCanvas
+void restoreToCount(int saveCount);
+
+[Canvas_rotate]
+SkCanvas
+void rotate(SkScalar degrees);
+
+[Canvas_rotate_2]
+SkCanvas
+void rotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+[Canvas_save]
+SkCanvas
+int save();
+
+[Canvas_saveLayer_3]
+SkCanvas
+int saveLayer(const SaveLayerRec& layerRec);
+
+[Canvas_saveLayer_2]
+SkCanvas
+int saveLayer(const SkRect& bounds, const SkPaint* paint);
+
+[Canvas_saveLayer]
+SkCanvas
+int saveLayer(const SkRect* bounds, const SkPaint* paint);
+
+[Canvas_saveLayerAlpha]
+SkCanvas
+int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
+
+[Canvas_saveLayerPreserveLCDTextRequests]
+SkCanvas
+int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
+
+[Canvas_scale]
+SkCanvas
+void scale(SkScalar sx, SkScalar sy);
+
+[Canvas_setMatrix]
+SkCanvas
+void setMatrix(const SkMatrix& matrix);
+
+[Canvas_skew]
+SkCanvas
+void skew(SkScalar sx, SkScalar sy);
+
+[Canvas_translate]
+SkCanvas
+void translate(SkScalar dx, SkScalar dy);
+
+[Canvas_writePixels_2]
+[State_Stack_a]
+[State_Stack_b]
+SkCanvas
+bool writePixels(const SkBitmap& bitmap, int x, int y);
+
+[Canvas_writePixels]
+SkCanvas
+bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
+
+[Canvas_destructor]
+SkCanvas
+virtual ~SkCanvas();
+
+[ColorGetA]
+SkColor
+#define SkColorGetA(color) (((color) >> 24) & 0xFF) color;
+
+[ColorGetB]
+SkColor
+#define SkColorGetB(color) (((color) >> 0) & 0xFF) color;
+
+[ColorGetG]
+SkColor
+#define SkColorGetG(color) (((color) >> 8) & 0xFF) color;
+
+[ColorGetR]
+SkColor
+#define SkColorGetR(color) (((color) >> 16) & 0xFF) color;
+
+[ColorSetA]
+SkColor
+static constexpr inline SkColor SkColorSetA(SkColor c, U8CPU a);
+
+[ColorSetRGB]
+SkColor
+#define SkColorSetRGB(r, g, b) SkColorSetARGB(0xFF, r, g, b) r g b;
+
+[ColorSetARGB]
+SkColor
+static constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+[ColorToHSV]
+SkColor
+static void SkColorToHSV(SkColor color, SkScalar hsv[3]);
+
+[HSVToColor]
+SkColor
+SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
+
+[HSVToColor_2]
+SkColor
+static SkColor SkHSVToColor(const SkScalar hsv[3]);
+
+[PreMultiplyARGB]
+SkColor
+SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+[PreMultiplyColor]
+SkColor
+SkPMColor SkPreMultiplyColor(SkColor c);
+
+[RGBToHSV]
+SkColor
+void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
+
+[Alpha_Constants_a]
+[Alpha_Constants_b]
+SkColor
+constexpr SkAlpha SK_AlphaTRANSPARENT = 0x00; constexpr SkAlpha SK_AlphaOPAQUE = 0xFF;
+
+[Color_Constants_a]
+[Color_Constants_b]
+[Color_Constants_c]
+[Color_Constants_d]
+SkColor
+constexpr SkColor SK_ColorTRANSPARENT; constexpr SkColor SK_ColorBLACK; constexpr SkColor SK_ColorDKGRAY; constexpr SkColor SK_ColorGRAY; constexpr SkColor SK_ColorLTGRAY; constexpr SkColor SK_ColorWHITE; constexpr SkColor SK_ColorRED; constexpr SkColor SK_ColorGREEN; constexpr SkColor SK_ColorBLUE; constexpr SkColor SK_ColorYELLOW; constexpr SkColor SK_ColorCYAN; constexpr SkColor SK_ColorMAGENTA;
+
+[RGBA4f_FromColor]
+SkColor4f
+static SkRGBA4f FromColor(SkColor color);
+
+[RGBA4f_notequal1_operator]
+SkColor4f
+bool operator!=(const SkRGBA4f& other) const;
+
+[RGBA4f_equal1_operator]
+SkColor4f
+bool operator==(const SkRGBA4f& other) const;
+
+[RGBA4f_toSkColor]
+SkColor4f
+SkColor toSkColor() const;
+
+[RGBA4f_vec]
+SkColor4f
+const float* vec() const;
+
+[RGBA4f_vec_2]
+SkColor4f
+float* vec();
+
+[Font_breakText]
+SkFont
+size_t breakText(const void* text, size_t length, SkTextEncoding encoding, SkScalar maxWidth, SkScalar* measuredWidth = nullptr) const;
+
+[IPoint_Make]
+SkIPoint
+static constexpr SkIPoint Make(int32_t x, int32_t y);
+
+[IPoint_equals]
+SkIPoint
+bool equals(int32_t x, int32_t y) const;
+
+[IPoint_isZero]
+SkIPoint
+bool isZero() const;
+
+[IPoint_notequal_operator]
+SkIPoint
+bool operator!=(const SkIPoint& a, const SkIPoint& b);
+
+[IPoint_add_operator]
+SkIPoint
+SkIPoint operator+(const SkIPoint& a, const SkIVector& b);
+
+[IPoint_addto_operator]
+SkIPoint
+void operator+=(const SkIVector& v);
+
+[IPoint_minus_operator]
+SkIPoint
+SkIPoint operator-() const;
+
+[IPoint_subtract_operator]
+SkIPoint
+SkIVector operator-(const SkIPoint& a, const SkIPoint& b);
+
+[IPoint_subtractfrom_operator]
+SkIPoint
+void operator-=(const SkIVector& v);
+
+[IPoint_equal_operator]
+SkIPoint
+bool operator==(const SkIPoint& a, const SkIPoint& b);
+
+[IPoint_set]
+SkIPoint
+void set(int32_t x, int32_t y);
+
+[IPoint_x]
+SkIPoint
+int32_t x() const;
+
+[IPoint_y]
+SkIPoint
+int32_t y() const;
+
+[IRect_EmptyIRect]
+SkIRect
+static const SkIRect& EmptyIRect();
+
+[IRect_Intersects]
+SkIRect
+static bool Intersects(const SkIRect& a, const SkIRect& b);
+
+[IRect_IntersectsNoEmptyCheck]
+SkIRect
+static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b);
+
+[IRect_MakeEmpty]
+SkIRect
+static constexpr SkIRect MakeEmpty();
+
+[IRect_MakeLTRB]
+SkIRect
+static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b);
+
+[IRect_MakeSize]
+SkIRect
+static constexpr SkIRect MakeSize(const SkISize& size);
+
+[IRect_MakeWH]
+SkIRect
+static constexpr SkIRect MakeWH(int32_t w, int32_t h);
+
+[IRect_MakeXYWH]
+SkIRect
+static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h);
+
+[IRect_adjust]
+SkIRect
+void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB);
+
+[IRect_bottom]
+SkIRect
+int32_t bottom() const;
+
+[IRect_contains_3]
+SkIRect
+bool contains(const SkIRect& r) const;
+
+[IRect_contains_4]
+SkIRect
+bool contains(const SkRect& r) const;
+
+[IRect_contains_2]
+SkIRect
+bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const;
+
+[IRect_contains]
+SkIRect
+bool contains(int32_t x, int32_t y) const;
+
+[IRect_containsNoEmptyCheck_2]
+SkIRect
+bool containsNoEmptyCheck(const SkIRect& r) const;
+
+[IRect_containsNoEmptyCheck]
+SkIRect
+bool containsNoEmptyCheck(int32_t left, int32_t top, int32_t right, int32_t bottom) const;
+
+[IRect_height]
+SkIRect
+int32_t height() const;
+
+[IRect_height64]
+SkIRect
+int64_t height64() const;
+
+[IRect_inset]
+SkIRect
+void inset(int32_t dx, int32_t dy);
+
+[IRect_intersect_2]
+SkIRect
+bool intersect(const SkIRect& a, const SkIRect& b);
+
+[IRect_intersect]
+SkIRect
+bool intersect(const SkIRect& r);
+
+[IRect_intersect_3]
+SkIRect
+bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+[IRect_intersectNoEmptyCheck]
+SkIRect
+bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b);
+
+[IRect_isEmpty]
+SkIRect
+bool isEmpty() const;
+
+[IRect_isEmpty64]
+SkIRect
+bool isEmpty64() const;
+
+[IRect_join_2]
+SkIRect
+void join(const SkIRect& r);
+
+[IRect_join]
+SkIRect
+void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+[IRect_left]
+SkIRect
+int32_t left() const;
+
+[IRect_makeInset]
+SkIRect
+SkIRect makeInset(int32_t dx, int32_t dy) const;
+
+[IRect_makeOffset]
+SkIRect
+SkIRect makeOffset(int32_t dx, int32_t dy) const;
+
+[IRect_makeOutset]
+SkIRect
+SkIRect makeOutset(int32_t dx, int32_t dy) const;
+
+[IRect_makeSorted]
+SkIRect
+SkIRect makeSorted() const;
+
+[IRect_offset_2]
+SkIRect
+void offset(const SkIPoint& delta);
+
+[IRect_offset]
+SkIRect
+void offset(int32_t dx, int32_t dy);
+
+[IRect_offsetTo]
+SkIRect
+void offsetTo(int32_t newX, int32_t newY);
+
+[IRect_notequal_operator]
+SkIRect
+bool operator!=(const SkIRect& a, const SkIRect& b);
+
+[IRect_equal_operator]
+SkIRect
+bool operator==(const SkIRect& a, const SkIRect& b);
+
+[IRect_outset]
+SkIRect
+void outset(int32_t dx, int32_t dy);
+
+[IRect_right]
+SkIRect
+int32_t right() const;
+
+[IRect_set]
+SkIRect
+void set(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+[IRect_setEmpty]
+SkIRect
+void setEmpty();
+
+[IRect_setLTRB]
+SkIRect
+void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+[IRect_setXYWH]
+SkIRect
+void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height);
+
+[IRect_size]
+SkIRect
+SkISize size() const;
+
+[IRect_sort]
+SkIRect
+void sort();
+
+[IRect_top]
+SkIRect
+int32_t top() const;
+
+[IRect_width]
+SkIRect
+int32_t width() const;
+
+[IRect_width64]
+SkIRect
+int64_t width64() const;
+
+[IRect_x]
+SkIRect
+int32_t x() const;
+
+[IRect_y]
+SkIRect
+int32_t y() const;
+
+[Image_MakeBackendTextureFromSkImage]
+SkImage
+static bool MakeBackendTextureFromSkImage(GrContext* context, sk_sp<SkImage> image, GrBackendTexture* backendTexture, BackendTextureReleaseProc* backendTextureReleaseProc);
+
+[Image_MakeCrossContextFromPixmap]
+SkImage
+static sk_sp<SkImage> MakeCrossContextFromPixmap(GrContext* context, const SkPixmap& pixmap, bool buildMips, bool limitToMaxTextureSize = false);
+
+[Image_MakeFromAdoptedTexture]
+SkImage
+static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin surfaceOrigin, SkColorType colorType, SkAlphaType alphaType = kPremul_SkAlphaType, sk_sp<SkColorSpace> colorSpace = nullptr);
+
+[Image_MakeFromBitmap]
+SkImage
+static sk_sp<SkImage> MakeFromBitmap(const SkBitmap& bitmap);
+
+[Image_MakeFromEncoded]
+SkImage
+static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
+
+[Image_MakeFromGenerator]
+SkImage
+static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator, const SkIRect* subset = nullptr);
+
+[Image_MakeFromPicture]
+SkImage
+static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions, const SkMatrix* matrix, const SkPaint* paint, BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace);
+
+[Image_MakeFromRaster]
+SkImage
+static sk_sp<SkImage> MakeFromRaster(const SkPixmap& pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext);
+
+[Image_MakeFromTexture]
+SkImage
+static sk_sp<SkImage> MakeFromTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace);
+
+[Image_MakeFromTexture_2]
+SkImage
+static sk_sp<SkImage> MakeFromTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace, TextureReleaseProc textureReleaseProc, ReleaseContext releaseContext);
+
+[Image_MakeRasterCopy]
+SkImage
+static sk_sp<SkImage> MakeRasterCopy(const SkPixmap& pixmap);
+
+[Image_MakeRasterData]
+SkImage
+static sk_sp<SkImage> MakeRasterData(const SkImageInfo& info, sk_sp<SkData> pixels, size_t rowBytes);
+
+[Image_alphaType]
+SkImage
+SkAlphaType alphaType() const;
+
+[Image_bounds]
+SkImage
+SkIRect bounds() const;
+
+[Image_colorSpace]
+SkImage
+SkColorSpace* colorSpace() const;
+
+[Image_colorType]
+SkImage
+SkColorType colorType() const;
+
+[Image_dimensions]
+SkImage
+SkISize dimensions() const;
+
+[Image_encodeToData_2]
+SkImage
+sk_sp<SkData> encodeToData() const;
+
+[Image_encodeToData]
+SkImage
+sk_sp<SkData> encodeToData(SkEncodedImageFormat encodedImageFormat, int quality) const;
+
+[Image_getBackendTexture]
+SkImage
+GrBackendTexture getBackendTexture(bool flushPendingGrContextIO, GrSurfaceOrigin* origin = nullptr) const;
+
+[Image_height]
+SkImage
+int height() const;
+
+[Image_isAlphaOnly]
+SkImage
+bool isAlphaOnly() const;
+
+[Image_isLazyGenerated_a]
+[Image_isLazyGenerated_b]
+SkImage
+bool isLazyGenerated() const;
+
+[Image_isOpaque]
+SkImage
+bool isOpaque() const;
+
+[Image_isTextureBacked]
+SkImage
+bool isTextureBacked() const;
+
+[Image_isValid]
+SkImage
+bool isValid(GrContext* context) const;
+
+[Image_makeColorSpace]
+SkImage
+sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target) const;
+
+[Image_makeNonTextureImage]
+SkImage
+sk_sp<SkImage> makeNonTextureImage() const;
+
+[Image_makeRasterImage]
+SkImage
+sk_sp<SkImage> makeRasterImage() const;
+
+[Image_makeShader]
+SkImage
+sk_sp<SkShader> makeShader(SkShader::TileMode tileMode1, SkShader::TileMode tileMode2, const SkMatrix* localMatrix = nullptr) const;
+
+[Image_makeShader_2]
+SkImage
+sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const;
+
+[Image_makeSubset]
+SkImage
+sk_sp<SkImage> makeSubset(const SkIRect& subset) const;
+
+[Image_makeTextureImage]
+SkImage
+sk_sp<SkImage> makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace, GrMipMapped mipMapped = GrMipMapped::kNo) const;
+
+[Image_makeWithFilter]
+SkImage
+sk_sp<SkImage> makeWithFilter(const SkImageFilter* filter, const SkIRect& subset, const SkIRect& clipBounds, SkIRect* outSubset, SkIPoint* offset) const;
+
+[Image_peekPixels]
+SkImage
+bool peekPixels(SkPixmap* pixmap) const;
+
+[Image_readPixels]
+SkImage
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
+
+[Image_readPixels_2]
+SkImage
+bool readPixels(const SkPixmap& dst, int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
+
+[Image_refColorSpace]
+SkImage
+sk_sp<SkColorSpace> refColorSpace() const;
+
+[Image_refEncodedData]
+SkImage
+sk_sp<SkData> refEncodedData() const;
+
+[Image_scalePixels]
+SkImage
+bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality, CachingHint cachingHint = kAllow_CachingHint) const;
+
+[Image_uniqueID]
+SkImage
+uint32_t uniqueID() const;
+
+[Image_width]
+SkImage
+int width() const;
+
+[ImageInfo_ByteSizeOverflowed]
+SkImageInfo
+static bool ByteSizeOverflowed(size_t byteSize);
+
+[ImageInfo_Make]
+SkImageInfo
+static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs = nullptr);
+
+[ImageInfo_MakeA8]
+SkImageInfo
+static SkImageInfo MakeA8(int width, int height);
+
+[ImageInfo_MakeN32]
+SkImageInfo
+static SkImageInfo MakeN32(int width, int height, SkAlphaType at, sk_sp<SkColorSpace> cs = nullptr);
+
+[ImageInfo_MakeN32Premul_2]
+SkImageInfo
+static SkImageInfo MakeN32Premul(const SkISize& size);
+
+[ImageInfo_MakeN32Premul]
+SkImageInfo
+static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr);
+
+[ImageInfo_MakeS32]
+SkImageInfo
+static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
+
+[ImageInfo_MakeUnknown_2]
+SkImageInfo
+static SkImageInfo MakeUnknown();
+
+[ImageInfo_MakeUnknown]
+SkImageInfo
+static SkImageInfo MakeUnknown(int width, int height);
+
+[ColorTypeBytesPerPixel]
+SkImageInfo
+int SkColorTypeBytesPerPixel(SkColorType ct);
+
+[ColorTypeIsAlwaysOpaque]
+SkImageInfo
+bool SkColorTypeIsAlwaysOpaque(SkColorType ct);
+
+[ColorTypeValidateAlphaType]
+SkImageInfo
+bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType, SkAlphaType* canonical = nullptr);
+
+[ImageInfo_empty_constructor]
+SkImageInfo
+SkImageInfo();
+
+[ImageInfo_alphaType]
+SkImageInfo
+SkAlphaType alphaType() const;
+
+[ImageInfo_bounds]
+SkImageInfo
+SkIRect bounds() const;
+
+[ImageInfo_bytesPerPixel]
+SkImageInfo
+int bytesPerPixel() const;
+
+[ImageInfo_colorSpace]
+SkImageInfo
+SkColorSpace* colorSpace() const;
+
+[ImageInfo_colorType]
+SkImageInfo
+SkColorType colorType() const;
+
+[ImageInfo_computeByteSize]
+SkImageInfo
+size_t computeByteSize(size_t rowBytes) const;
+
+[ImageInfo_computeMinByteSize]
+SkImageInfo
+size_t computeMinByteSize() const;
+
+[ImageInfo_computeOffset]
+SkImageInfo
+size_t computeOffset(int x, int y, size_t rowBytes) const;
+
+[ImageInfo_dimensions]
+SkImageInfo
+SkISize dimensions() const;
+
+[Alpha_Type_Opaque]
+SkImageInfo
+enum SkAlphaType { kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType, kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, };
+
+[Color_Type_ARGB_4444]
+[Color_Type_Alpha_8]
+[Color_Type_BGRA_8888]
+[Color_Type_Gray_8]
+[Color_Type_RGBA_1010102]
+[Color_Type_RGBA_8888]
+[Color_Type_RGBA_F16]
+[Color_Type_RGB_101010]
+[Color_Type_RGB_565]
+[Color_Type_RGB_888]
+SkImageInfo
+enum SkColorType { kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType, kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType, kGray_8_SkColorType, kRGBA_F16_SkColorType, kRGBA_F32_SkColorType, kLastEnum_SkColorType = kRGBA_F32_SkColorType, kN32_SkColorType = kBGRA_8888_SkColorType, kN32_SkColorType = kRGBA_8888_SkColorType, };
+
+[ImageInfo_gammaCloseToSRGB]
+SkImageInfo
+bool gammaCloseToSRGB() const;
+
+[ImageInfo_height]
+SkImageInfo
+int height() const;
+
+[ImageInfo_isEmpty]
+SkImageInfo
+bool isEmpty() const;
+
+[ImageInfo_isOpaque]
+SkImageInfo
+bool isOpaque() const;
+
+[ImageInfo_makeAlphaType]
+SkImageInfo
+SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const;
+
+[ImageInfo_makeColorSpace]
+SkImageInfo
+SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const;
+
+[ImageInfo_makeColorType]
+SkImageInfo
+SkImageInfo makeColorType(SkColorType newColorType) const;
+
+[ImageInfo_makeWH]
+SkImageInfo
+SkImageInfo makeWH(int newWidth, int newHeight) const;
+
+[ImageInfo_minRowBytes]
+SkImageInfo
+size_t minRowBytes() const;
+
+[ImageInfo_minRowBytes64]
+SkImageInfo
+uint64_t minRowBytes64() const;
+
+[ImageInfo_notequal1_operator]
+SkImageInfo
+bool operator!=(const SkImageInfo& other) const;
+
+[ImageInfo_equal1_operator]
+SkImageInfo
+bool operator==(const SkImageInfo& other) const;
+
+[ImageInfo_refColorSpace]
+SkImageInfo
+sk_sp<SkColorSpace> refColorSpace() const;
+
+[ImageInfo_reset]
+SkImageInfo
+void reset();
+
+[ImageInfo_shiftPerPixel]
+SkImageInfo
+int shiftPerPixel() const;
+
+[Alpha_Type_Premul]
+SkImageInfo
+stored color = original color * alpha / max alpha;
+
+[Alpha_Type_Unpremul]
+SkImageInfo
+stored color = original color * alpha / max alpha;
+
+[ImageInfo_validRowBytes]
+SkImageInfo
+bool validRowBytes(size_t rowBytes) const;
+
+[ImageInfo_width]
+SkImageInfo
+int width() const;
+
+[Matrix_Concat]
+SkMatrix
+static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b);
+
+[Matrix_I]
+SkMatrix
+static const SkMatrix& I();
+
+[Matrix_063]
+SkMatrix
+| sx 0 0 | | J K L | | sx*J sx*K sx*L | I(divx, divy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | | 0 0 1 | | P Q R | | P Q R |;
+
+[Matrix_InvalidMatrix]
+SkMatrix
+static const SkMatrix& InvalidMatrix();
+
+[Matrix_MakeAll]
+SkMatrix
+static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2);
+
+[Matrix_MakeRectToRect]
+SkMatrix
+static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+
+[Matrix_MakeScale_2]
+SkMatrix
+static SkMatrix MakeScale(SkScalar scale);
+
+[Matrix_MakeScale]
+SkMatrix
+static SkMatrix MakeScale(SkScalar sx, SkScalar sy);
+
+[Matrix_MakeTrans]
+SkMatrix
+static SkMatrix MakeTrans(SkScalar dx, SkScalar dy);
+
+[Matrix_SetAffineIdentity]
+SkMatrix
+static void SetAffineIdentity(SkScalar affine[6]);
+
+[Matrix_asAffine]
+SkMatrix
+bool asAffine(SkScalar affine[6]) const;
+
+[Matrix_cheapEqualTo]
+SkMatrix
+bool cheapEqualTo(const SkMatrix& m) const;
+
+[Matrix_decomposeScale]
+SkMatrix
+bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;
+
+[Matrix_dirtyMatrixTypeCache]
+SkMatrix
+void dirtyMatrixTypeCache();
+
+[Matrix_dump]
+SkMatrix
+void dump() const;
+
+[Matrix_ScaleToFit]
+SkMatrix
+enum ScaleToFit { kFill_ScaleToFit, kStart_ScaleToFit, kCenter_ScaleToFit, kEnd_ScaleToFit, };
+
+[Matrix_TypeMask]
+SkMatrix
+enum TypeMask { kIdentity_Mask = 0, kTranslate_Mask = 0x01, kScale_Mask = 0x02, kAffine_Mask = 0x04, kPerspective_Mask = 0x08, };
+
+[Matrix_fixedStepInX]
+SkMatrix
+SkVector fixedStepInX(SkScalar y) const;
+
+[Matrix_get]
+SkMatrix
+SkScalar get(int index) const;
+
+[Matrix_get9]
+SkMatrix
+void get9(SkScalar buffer[9]) const;
+
+[Matrix_getMaxScale]
+SkMatrix
+SkScalar getMaxScale() const;
+
+[Matrix_getMinMaxScales]
+SkMatrix
+bool getMinMaxScales(SkScalar scaleFactors[2]) const;
+
+[Matrix_getMinScale]
+SkMatrix
+SkScalar getMinScale() const;
+
+[Matrix_getPerspX]
+SkMatrix
+SkScalar getPerspX() const;
+
+[Matrix_getPerspY]
+SkMatrix
+SkScalar getPerspY() const;
+
+[Matrix_getScaleX]
+SkMatrix
+SkScalar getScaleX() const;
+
+[Matrix_getScaleY]
+SkMatrix
+SkScalar getScaleY() const;
+
+[Matrix_getSkewX]
+SkMatrix
+SkScalar getSkewX() const;
+
+[Matrix_getSkewY]
+SkMatrix
+SkScalar getSkewY() const;
+
+[Matrix_getTranslateX]
+SkMatrix
+SkScalar getTranslateX() const;
+
+[Matrix_getTranslateY]
+SkMatrix
+SkScalar getTranslateY() const;
+
+[Matrix_getType]
+SkMatrix
+TypeMask getType() const;
+
+[Matrix_hasPerspective]
+SkMatrix
+bool hasPerspective() const;
+
+[Matrix_invert]
+SkMatrix
+bool invert(SkMatrix* inverse) const;
+
+[Matrix_isFinite]
+SkMatrix
+bool isFinite() const;
+
+[Matrix_isFixedStepInX]
+SkMatrix
+bool isFixedStepInX() const;
+
+[Matrix_isIdentity]
+SkMatrix
+bool isIdentity() const;
+
+[Matrix_isScaleTranslate]
+SkMatrix
+bool isScaleTranslate() const;
+
+[Matrix_isSimilarity]
+SkMatrix
+bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
+
+[Matrix_isTranslate]
+SkMatrix
+bool isTranslate() const;
+
+[Matrix_mapHomogeneousPoints]
+SkMatrix
+void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
+
+[Matrix_mapPoints]
+SkMatrix
+void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
+
+[Matrix_mapPoints_2]
+SkMatrix
+void mapPoints(SkPoint pts[], int count) const;
+
+[Matrix_mapRadius]
+SkMatrix
+SkScalar mapRadius(SkScalar radius) const;
+
+[Matrix_mapRect_3]
+SkMatrix
+SkRect mapRect(const SkRect& src) const;
+
+[Matrix_mapRect]
+SkMatrix
+bool mapRect(SkRect* dst, const SkRect& src) const;
+
+[Matrix_mapRect_2]
+SkMatrix
+bool mapRect(SkRect* rect) const;
+
+[Matrix_mapRectScaleTranslate]
+SkMatrix
+void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
+
+[Matrix_mapRectToQuad]
+SkMatrix
+void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const;
+
+[Matrix_mapVector_2]
+SkMatrix
+SkVector mapVector(SkScalar dx, SkScalar dy) const;
+
+[Matrix_mapVector]
+SkMatrix
+void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const;
+
+[Matrix_mapVectors]
+SkMatrix
+void mapVectors(SkVector dst[], const SkVector src[], int count) const;
+
+[Matrix_mapVectors_2]
+SkMatrix
+void mapVectors(SkVector vecs[], int count) const;
+
+[Matrix_mapXY_2]
+SkMatrix
+SkPoint mapXY(SkScalar x, SkScalar y) const;
+
+[Matrix_mapXY]
+SkMatrix
+void mapXY(SkScalar x, SkScalar y, SkPoint* result) const;
+
+[Matrix_notequal_operator]
+SkMatrix
+bool operator!=(const SkMatrix& a, const SkMatrix& b);
+
+[Matrix_equal_operator]
+SkMatrix
+bool operator==(const SkMatrix& a, const SkMatrix& b);
+
+[Matrix_array_operator]
+SkMatrix
+SkScalar operator[](int index) const;
+
+[Matrix_dirtyMatrixTypeCache]
+SkMatrix
+SkScalar& operator[](int index);
+
+[Matrix_postConcat]
+SkMatrix
+void postConcat(const SkMatrix& other);
+
+[Matrix_postRotate_2]
+SkMatrix
+void postRotate(SkScalar degrees);
+
+[Matrix_postRotate]
+SkMatrix
+void postRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+[Matrix_postScale_2]
+SkMatrix
+void postScale(SkScalar sx, SkScalar sy);
+
+[Matrix_postScale]
+SkMatrix
+void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+[Matrix_postSkew_2]
+SkMatrix
+void postSkew(SkScalar kx, SkScalar ky);
+
+[Matrix_postSkew]
+SkMatrix
+void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+[Matrix_postTranslate]
+SkMatrix
+void postTranslate(SkScalar dx, SkScalar dy);
+
+[Matrix_preConcat]
+SkMatrix
+void preConcat(const SkMatrix& other);
+
+[Matrix_preRotate_2]
+SkMatrix
+void preRotate(SkScalar degrees);
+
+[Matrix_preRotate]
+SkMatrix
+void preRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+[Matrix_preScale_2]
+SkMatrix
+void preScale(SkScalar sx, SkScalar sy);
+
+[Matrix_preScale]
+SkMatrix
+void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+[Matrix_preSkew_2]
+SkMatrix
+void preSkew(SkScalar kx, SkScalar ky);
+
+[Matrix_preSkew]
+SkMatrix
+void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+[Matrix_preTranslate]
+SkMatrix
+void preTranslate(SkScalar dx, SkScalar dy);
+
+[Matrix_preservesAxisAlignment]
+SkMatrix
+bool preservesAxisAlignment() const;
+
+[Matrix_preservesRightAngles]
+SkMatrix
+bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
+
+[Matrix_rectStaysRect]
+SkMatrix
+bool rectStaysRect() const;
+
+[Matrix_reset]
+SkMatrix
+void reset();
+
+[Matrix_set]
+SkMatrix
+void set(int index, SkScalar value);
+
+[Matrix_set9]
+SkMatrix
+void set9(const SkScalar buffer[9]);
+
+[Matrix_setAffine]
+SkMatrix
+void setAffine(const SkScalar affine[6]);
+
+[Matrix_setAll]
+SkMatrix
+void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2);
+
+[Matrix_setConcat]
+SkMatrix
+void setConcat(const SkMatrix& a, const SkMatrix& b);
+
+[Matrix_setIdentity]
+SkMatrix
+void setIdentity();
+
+[Matrix_setPerspX]
+SkMatrix
+void setPerspX(SkScalar v);
+
+[Matrix_setPerspY]
+SkMatrix
+void setPerspY(SkScalar v);
+
+[Matrix_setPolyToPoly]
+SkMatrix
+bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
+
+[Matrix_setRSXform]
+SkMatrix
+SkMatrix& setRSXform(const SkRSXform& rsxForm);
+
+[Matrix_setRectToRect]
+SkMatrix
+bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+
+[Matrix_setRotate_2]
+SkMatrix
+void setRotate(SkScalar degrees);
+
+[Matrix_setRotate]
+SkMatrix
+void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+[Matrix_setScale_2]
+SkMatrix
+void setScale(SkScalar sx, SkScalar sy);
+
+[Matrix_setScale]
+SkMatrix
+void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+[Matrix_setScaleTranslate]
+SkMatrix
+void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty);
+
+[Matrix_setScaleX]
+SkMatrix
+void setScaleX(SkScalar v);
+
+[Matrix_setScaleY]
+SkMatrix
+void setScaleY(SkScalar v);
+
+[Matrix_setSinCos_2]
+SkMatrix
+void setSinCos(SkScalar sinValue, SkScalar cosValue);
+
+[Matrix_setSinCos]
+SkMatrix
+void setSinCos(SkScalar sinValue, SkScalar cosValue, SkScalar px, SkScalar py);
+
+[Matrix_setSkew_2]
+SkMatrix
+void setSkew(SkScalar kx, SkScalar ky);
+
+[Matrix_setSkew]
+SkMatrix
+void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+[Matrix_setSkewX]
+SkMatrix
+void setSkewX(SkScalar v);
+
+[Matrix_setSkewY]
+SkMatrix
+void setSkewY(SkScalar v);
+
+[Matrix_setTranslate]
+SkMatrix
+void setTranslate(SkScalar dx, SkScalar dy);
+
+[Matrix_setTranslate_2]
+SkMatrix
+void setTranslate(const SkVector& v);
+
+[Matrix_setTranslateX]
+SkMatrix
+void setTranslateX(SkScalar v);
+
+[Matrix_setTranslateY]
+SkMatrix
+void setTranslateY(SkScalar v);
+
+[MemberIndex]
+SkMatrix
+static constexpr int kMScaleX = 0; static constexpr int kMSkewX = 1; static constexpr int kMTransX = 2; static constexpr int kMSkewY = 3; static constexpr int kMScaleY = 4; static constexpr int kMTransY = 5; static constexpr int kMPersp0 = 6; static constexpr int kMPersp1 = 7; static constexpr int kMPersp2 = 8;
+
+[Paint_empty_constructor]
+SkPaint
+SkPaint();
+
+[Paint_move_SkPaint]
+SkPaint
+SkPaint(SkPaint&& paint);
+
+[Paint_copy_const_SkPaint]
+SkPaint
+SkPaint(const SkPaint& paint);
+
+[Paint_containsText]
+SkPaint
+bool containsText(const void* text, size_t byteLength) const;
+
+[Paint_countText]
+SkPaint
+int countText(const void* text, size_t byteLength) const;
+
+[Paint_getAlpha]
+SkPaint
+uint8_t getAlpha() const;
+
+[Paint_getBlendMode]
+SkPaint
+SkBlendMode getBlendMode() const;
+
+[Paint_getColor]
+SkPaint
+SkColor getColor() const;
+
+[Paint_getColor4f]
+SkPaint
+SkColor4f getColor4f() const;
+
+[Paint_getColorFilter]
+SkPaint
+SkColorFilter* getColorFilter() const;
+
+[Paint_getDrawLooper]
+SkPaint
+SkDrawLooper* getDrawLooper() const;
+
+[Paint_getFillPath_2]
+[Shader_Methods_a]
+[Shader_Methods_b]
+SkPaint
+bool getFillPath(const SkPath& src, SkPath* dst) const;
+
+[Paint_getFillPath]
+SkPaint
+bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, SkScalar resScale = 1) const;
+
+[Paint_getFilterQuality]
+SkPaint
+SkFilterQuality getFilterQuality() const;
+
+[Paint_getFlags]
+SkPaint
+uint32_t getFlags() const;
+
+[Paint_getFontMetrics]
+SkPaint
+SkScalar getFontMetrics(SkFontMetrics* metrics) const;
+
+[Paint_getFontSpacing]
+SkPaint
+SkScalar getFontSpacing() const;
+
+[Paint_getHash]
+SkPaint
+uint32_t getHash() const;
+
+[Paint_getHinting]
+SkPaint
+SkFontHinting getHinting() const;
+
+[Paint_getImageFilter]
+SkPaint
+SkImageFilter* getImageFilter() const;
+
+[Paint_getMaskFilter]
+SkPaint
+SkMaskFilter* getMaskFilter() const;
+
+[Paint_getPathEffect]
+SkPaint
+SkPathEffect* getPathEffect() const;
+
+[Paint_getPosTextPath]
+SkPaint
+void getPosTextPath(const void* text, size_t length, const SkPoint pos[], SkPath* path) const;
+
+[Paint_getShader]
+SkPaint
+SkShader* getShader() const;
+
+[Paint_getStrokeCap]
+SkPaint
+Cap getStrokeCap() const;
+
+[Paint_getStrokeJoin]
+SkPaint
+Join getStrokeJoin() const;
+
+[Paint_getStrokeMiter]
+SkPaint
+SkScalar getStrokeMiter() const;
+
+[Paint_getStrokeWidth]
+SkPaint
+SkScalar getStrokeWidth() const;
+
+[Paint_getStyle]
+SkPaint
+Style getStyle() const;
+
+[Paint_getTextEncoding]
+SkPaint
+SkTextEncoding getTextEncoding() const;
+
+[Paint_getTextPath]
+SkPaint
+void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y, SkPath* path) const;
+
+[Paint_getTextScaleX]
+SkPaint
+SkScalar getTextScaleX() const;
+
+[Paint_getTextSize]
+SkPaint
+SkScalar getTextSize() const;
+
+[Paint_getTextSkewX]
+SkPaint
+SkScalar getTextSkewX() const;
+
+[Paint_getTextWidths]
+SkPaint
+int getTextWidths(const void* text, size_t byteLength, SkScalar widths[], SkRect bounds[] = nullptr) const;
+
+[Paint_getTypeface]
+SkPaint
+SkTypeface* getTypeface() const;
+
+[Paint_isAntiAlias]
+SkPaint
+bool isAntiAlias() const;
+
+[Paint_isAutohinted]
+SkPaint
+bool isAutohinted() const;
+
+[Paint_isDither]
+SkPaint
+bool isDither() const;
+
+[Paint_isEmbeddedBitmapText]
+SkPaint
+bool isEmbeddedBitmapText() const;
+
+[Paint_isFakeBoldText]
+SkPaint
+bool isFakeBoldText() const;
+
+[Paint_isLCDRenderText]
+SkPaint
+bool isLCDRenderText() const;
+
+[Paint_isLinearText]
+SkPaint
+bool isLinearText() const;
+
+[Paint_setBlendMode]
+SkPaint
+bool isSrcOver() const;
+
+[Paint_isSubpixelText]
+SkPaint
+bool isSubpixelText() const;
+
+[Paint_measureText_2]
+SkPaint
+SkScalar measureText(const void* text, size_t length) const;
+
+[Paint_measureText]
+SkPaint
+SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
+
+[Paint_nothingToDraw]
+SkPaint
+bool nothingToDraw() const;
+
+[Paint_notequal_operator]
+SkPaint
+bool operator!=(const SkPaint& a, const SkPaint& b);
+
+[Paint_move_operator]
+SkPaint
+SkPaint& operator=(SkPaint&& paint);
+
+[Paint_copy_operator]
+SkPaint
+SkPaint& operator=(const SkPaint& paint);
+
+[Paint_equal_operator]
+SkPaint
+bool operator==(const SkPaint& a, const SkPaint& b);
+
+[Paint_refColorFilter]
+SkPaint
+sk_sp<SkColorFilter> refColorFilter() const;
+
+[Paint_refDrawLooper]
+SkPaint
+sk_sp<SkDrawLooper> refDrawLooper() const;
+
+[Paint_refImageFilter]
+SkPaint
+sk_sp<SkImageFilter> refImageFilter() const;
+
+[Paint_refMaskFilter]
+SkPaint
+sk_sp<SkMaskFilter> refMaskFilter() const;
+
+[Paint_refPathEffect]
+SkPaint
+sk_sp<SkPathEffect> refPathEffect() const;
+
+[Paint_refShader]
+SkPaint
+sk_sp<SkShader> refShader() const;
+
+[Paint_refTypeface]
+SkPaint
+sk_sp<SkTypeface> refTypeface() const;
+
+[Paint_reset]
+SkPaint
+void reset();
+
+[Paint_setARGB]
+SkPaint
+void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+[Paint_setAlpha]
+SkPaint
+void setAlpha(U8CPU a);
+
+[Dither_a]
+[Dither_b]
+[Paint_setAntiAlias]
+SkPaint
+void setAntiAlias(bool aa);
+
+[Fake_Bold]
+[Paint_setAutohinted]
+SkPaint
+void setAutohinted(bool useAutohinter);
+
+[Paint_setBlendMode]
+[Path_Effect_Methods]
+SkPaint
+void setBlendMode(SkBlendMode mode);
+
+[Paint_setColor]
+SkPaint
+void setColor(SkColor color);
+
+[Paint_setColor4f]
+SkPaint
+void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace);
+
+[Blend_Mode_Methods]
+[Paint_setColorFilter]
+SkPaint
+void setColorFilter(sk_sp<SkColorFilter> colorFilter);
+
+[Device_Text]
+[Paint_setDither]
+SkPaint
+void setDither(bool dither);
+
+[Paint_setDrawLooper]
+[Text_Size]
+SkPaint
+void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);
+
+[Paint_setEmbeddedBitmapText]
+SkPaint
+void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
+
+[Filter_Quality_Methods]
+[Paint_setFakeBoldText]
+SkPaint
+void setFakeBoldText(bool fakeBoldText);
+
+[Color_Methods]
+[Paint_setFilterQuality]
+SkPaint
+void setFilterQuality(SkFilterQuality quality);
+
+[Anti_Alias]
+[Paint_setFlags]
+SkPaint
+void setFlags(uint32_t flags);
+
+[Paint_setHinting]
+SkPaint
+void setHinting(SkFontHinting hintingLevel);
+
+[Draw_Looper_Methods]
+[Paint_setImageFilter]
+SkPaint
+void setImageFilter(sk_sp<SkImageFilter> imageFilter);
+
+[Paint_setLCDRenderText]
+SkPaint
+void setLCDRenderText(bool lcdText);
+
+[Paint_setLinearText]
+SkPaint
+void setLinearText(bool linearText);
+
+[Paint_setMaskFilter]
+[Typeface_Methods]
+SkPaint
+void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
+
+[Mask_Filter_Methods]
+[Paint_setPathEffect]
+SkPaint
+void setPathEffect(sk_sp<SkPathEffect> pathEffect);
+
+[Color_Filter_Methods]
+[Paint_setShader]
+SkPaint
+void setShader(sk_sp<SkShader> shader);
+
+[Paint_setStrokeCap_a]
+[Paint_setStrokeCap_b]
+SkPaint
+void setStrokeCap(Cap cap);
+
+[Paint_setStrokeJoin]
+SkPaint
+void setStrokeJoin(Join join);
+
+[Paint_setStrokeMiter]
+SkPaint
+void setStrokeMiter(SkScalar miter);
+
+[Miter_Limit]
+[Paint_setStrokeWidth]
+SkPaint
+void setStrokeWidth(SkScalar width);
+
+[Paint_setStyle]
+[Stroke_Width]
+SkPaint
+void setStyle(Style style);
+
+[Paint_setSubpixelText]
+SkPaint
+void setSubpixelText(bool subpixelText);
+
+[Paint_setTextEncoding]
+SkPaint
+void setTextEncoding(SkTextEncoding encoding);
+
+[Paint_setTextScaleX]
+[Text_Skew_X]
+SkPaint
+void setTextScaleX(SkScalar scaleX);
+
+[Paint_setTextSize]
+[Text_Scale_X]
+SkPaint
+void setTextSize(SkScalar textSize);
+
+[Paint_setTextSkewX]
+[Text_Encoding]
+SkPaint
+void setTextSkewX(SkScalar skewX);
+
+[Image_Filter_Methods]
+[Paint_setTypeface]
+SkPaint
+void setTypeface(sk_sp<SkTypeface> typeface);
+
+[Paint_053]
+SkPaint
+static constexpr int kCapCount = kLast_Cap + 1;
+
+[Paint_057]
+SkPaint
+static constexpr int kJoinCount = kLast_Join + 1;
+
+[Paint_textToGlyphs]
+SkPaint
+int textToGlyphs(const void* text, size_t byteLength, SkGlyphID glyphs[]) const;
+
+[Path_ConvertConicToQuads]
+SkPath
+static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2, SkScalar w, SkPoint pts[], int pow2);
+
+[Path_ConvertToNonInverseFillType]
+SkPath
+static FillType ConvertToNonInverseFillType(FillType fill);
+
+[Path_IsCubicDegenerate]
+SkPath
+static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3, const SkPoint& p4, bool exact);
+
+[Path_IsInverseFillType]
+SkPath
+static bool IsInverseFillType(FillType fill);
+
+[Path_IsLineDegenerate]
+SkPath
+static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact);
+
+[Path_IsQuadDegenerate]
+SkPath
+static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3, bool exact);
+
+[Path_Iter_Iter]
+SkPath
+Iter();
+
+[Path_Iter_const_SkPath]
+SkPath
+Iter(const SkPath& path, bool forceClose);
+
+[Path_empty_constructor]
+SkPath
+SkPath();
+
+[Path_copy_const_SkPath]
+SkPath
+SkPath(const SkPath& path);
+
+[Path_addArc]
+SkPath
+SkPath& addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+
+[Path_addCircle]
+SkPath
+SkPath& addCircle(SkScalar x, SkScalar y, SkScalar radius, Direction dir = kCW_Direction);
+
+[Path_addOval]
+SkPath
+SkPath& addOval(const SkRect& oval, Direction dir = kCW_Direction);
+
+[Path_addOval_2]
+SkPath
+SkPath& addOval(const SkRect& oval, Direction dir, unsigned start);
+
+[Path_addPath_2]
+SkPath
+SkPath& addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode);
+
+[Path_addPath]
+SkPath
+SkPath& addPath(const SkPath& src, SkScalar dx, SkScalar dy, AddPathMode mode = kAppend_AddPathMode);
+
+[Path_addPath_3]
+SkPath
+SkPath& addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
+
+[Path_addPoly]
+SkPath
+SkPath& addPoly(const SkPoint pts[], int count, bool close);
+
+[Path_addPoly_2]
+SkPath
+SkPath& addPoly(const std::initializer_list<SkPoint>& list, bool close);
+
+[Path_addRRect]
+SkPath
+SkPath& addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
+
+[Path_addRRect_2]
+SkPath
+SkPath& addRRect(const SkRRect& rrect, Direction dir, unsigned start);
+
+[Path_addRect_3]
+SkPath
+SkPath& addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, Direction dir = kCW_Direction);
+
+[Path_addRect]
+SkPath
+SkPath& addRect(const SkRect& rect, Direction dir = kCW_Direction);
+
+[Path_addRect_2]
+SkPath
+SkPath& addRect(const SkRect& rect, Direction dir, unsigned start);
+
+[Path_addRoundRect]
+SkPath
+SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, Direction dir = kCW_Direction);
+
+[Path_addRoundRect_2]
+SkPath
+SkPath& addRoundRect(const SkRect& rect, const SkScalar radii[], Direction dir = kCW_Direction);
+
+[Path_arcTo_4]
+SkPath
+SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, SkScalar x, SkScalar y);
+
+[Path_arcTo_2_a]
+[Path_arcTo_2_b]
+[Path_arcTo_2_c]
+SkPath
+SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
+
+[Path_arcTo_3]
+SkPath
+SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius);
+
+[Path_rArcTo]
+SkPath
+SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, const SkPoint xy);
+
+[Path_arcTo]
+SkPath
+SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
+
+[Path_close]
+SkPath
+SkPath& close();
+
+[Path_computeTightBounds]
+SkPath
+SkRect computeTightBounds() const;
+
+[Path_conicTo]
+SkPath
+SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w);
+
+[Path_conicTo_2]
+SkPath
+SkPath& conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w);
+
+[Path_Iter_conicWeight]
+[Path_RawIter_conicWeight]
+SkPath
+SkScalar conicWeight() const;
+
+[Path_conservativelyContainsRect]
+SkPath
+bool conservativelyContainsRect(const SkRect& rect) const;
+
+[Path_contains]
+SkPath
+bool contains(SkScalar x, SkScalar y) const;
+
+[Path_countPoints]
+SkPath
+int countPoints() const;
+
+[Path_countVerbs]
+SkPath
+int countVerbs() const;
+
+[Path_cubicTo]
+SkPath
+SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3);
+
+[Path_cubicTo_2]
+SkPath
+SkPath& cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3);
+
+[Path_dump_2]
+SkPath
+void dump() const;
+
+[Path_dump]
+SkPath
+void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const;
+
+[Path_dumpHex]
+SkPath
+void dumpHex() const;
+
+[Path_AddPathMode]
+SkPath
+enum AddPathMode { kAppend_AddPathMode, kExtend_AddPathMode, };
+
+[Path_ArcSize]
+SkPath
+enum ArcSize { kSmall_ArcSize, kLarge_ArcSize, };
+
+[Path_Convexity]
+SkPath
+enum Convexity : uint8_t { kUnknown_Convexity, kConvex_Convexity, kConcave_Convexity, };
+
+[Path_Direction]
+SkPath
+enum Direction : int { kCW_Direction, kCCW_Direction, };
+
+[Path_FillType_a]
+[Path_FillType_b]
+SkPath
+enum FillType { kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType, kInverseEvenOdd_FillType, };
+
+[Path_SegmentMask]
+SkPath
+enum SegmentMask { kLine_SegmentMask = 1 << 0, kQuad_SegmentMask = 1 << 1, kConic_SegmentMask = 1 << 2, kCubic_SegmentMask = 1 << 3, };
+
+[Path_Verb]
+SkPath
+enum Verb { kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb, kCubic_Verb, kClose_Verb, kDone_Verb, };
+
+[Path_getBounds]
+SkPath
+const SkRect& getBounds() const;
+
+[Path_getConvexity]
+SkPath
+Convexity getConvexity() const;
+
+[Path_getConvexityOrUnknown]
+SkPath
+Convexity getConvexityOrUnknown() const;
+
+[Path_getFillType]
+SkPath
+FillType getFillType() const;
+
+[Path_getGenerationID]
+SkPath
+uint32_t getGenerationID() const;
+
+[Path_getLastPt]
+SkPath
+bool getLastPt(SkPoint* lastPt) const;
+
+[Path_getPoint]
+SkPath
+SkPoint getPoint(int index) const;
+
+[Path_getPoints]
+SkPath
+int getPoints(SkPoint points[], int max) const;
+
+[Path_getSegmentMasks]
+SkPath
+uint32_t getSegmentMasks() const;
+
+[Path_getVerbs]
+SkPath
+int getVerbs(uint8_t verbs[], int max) const;
+
+[Path_incReserve]
+SkPath
+void incReserve(int extraPtCount);
+
+[Path_interpolate]
+SkPath
+bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
+
+[Path_Iter_isCloseLine]
+SkPath
+bool isCloseLine() const;
+
+[Path_Iter_isClosedContour]
+SkPath
+bool isClosedContour() const;
+
+[Path_Iter]
+SkPath
+class Iter { Iter(); Iter(const SkPath& path, bool forceClose); void setPath(const SkPath& path, bool forceClose); Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false); SkScalar conicWeight() const; bool isCloseLine() const; bool isClosedContour() const; };
+
+[Path_isConvex]
+SkPath
+bool isConvex() const;
+
+[Path_isEmpty]
+SkPath
+bool isEmpty() const;
+
+[Path_isFinite]
+SkPath
+bool isFinite() const;
+
+[Path_isInterpolatable]
+SkPath
+bool isInterpolatable(const SkPath& compare) const;
+
+[Path_isInverseFillType_2]
+SkPath
+bool isInverseFillType() const;
+
+[Path_isLastContourClosed]
+SkPath
+bool isLastContourClosed() const;
+
+[Path_isLine]
+SkPath
+bool isLine(SkPoint line[2]) const;
+
+[Path_isNestedFillRects]
+SkPath
+bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const;
+
+[Path_isOval]
+SkPath
+bool isOval(SkRect* bounds) const;
+
+[Path_isRRect]
+SkPath
+bool isRRect(SkRRect* rrect) const;
+
+[Path_isRect]
+SkPath
+bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const;
+
+[Path_isVolatile]
+SkPath
+bool isVolatile() const;
+
+[Path_lineTo]
+SkPath
+SkPath& lineTo(SkScalar x, SkScalar y);
+
+[Path_lineTo_2]
+SkPath
+SkPath& lineTo(const SkPoint& p);
+
+[Path_moveTo]
+SkPath
+SkPath& moveTo(SkScalar x, SkScalar y);
+
+[Path_moveTo_2]
+SkPath
+SkPath& moveTo(const SkPoint& p);
+
+[Path_RawIter_next]
+SkPath
+Verb next(SkPoint pts[4]);
+
+[Path_Iter_next]
+SkPath
+Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false);
+
+[Path_offset_2]
+SkPath
+void offset(SkScalar dx, SkScalar dy);
+
+[Path_offset]
+SkPath
+void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
+
+[Path_notequal_operator]
+SkPath
+bool operator!=(const SkPath& a, const SkPath& b);
+
+[Path_copy_operator]
+SkPath
+SkPath& operator=(const SkPath& path);
+
+[Path_equal_operator]
+SkPath
+bool operator==(const SkPath& a, const SkPath& b);
+
+[Path_RawIter_peek]
+SkPath
+Verb peek() const;
+
+[Path_quadTo]
+SkPath
+SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+
+[Path_quadTo_2]
+SkPath
+SkPath& quadTo(const SkPoint& p1, const SkPoint& p2);
+
+[Path_rArcTo]
+SkPath
+SkPath& rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, SkScalar dx, SkScalar dy);
+
+[Cubic]
+[Path_rConicTo]
+SkPath
+SkPath& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w);
+
+[Arc]
+[Path_rCubicTo]
+SkPath
+SkPath& rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar dx3, SkScalar dy3);
+
+[Path_rLineTo]
+[Quad_a]
+[Quad_b]
+SkPath
+SkPath& rLineTo(SkScalar dx, SkScalar dy);
+
+[Path_rMoveTo]
+SkPath
+SkPath& rMoveTo(SkScalar dx, SkScalar dy);
+
+[Conic_Weight_a]
+[Conic_Weight_b]
+[Conic_Weight_c]
+[Path_rQuadTo]
+SkPath
+SkPath& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+
+[Path_readFromMemory]
+SkPath
+size_t readFromMemory(const void* buffer, size_t length);
+
+[Path_reset]
+SkPath
+SkPath& reset();
+
+[Path_reverseAddPath]
+SkPath
+SkPath& reverseAddPath(const SkPath& src);
+
+[Path_rewind]
+SkPath
+SkPath& rewind();
+
+[Path_serialize]
+SkPath
+sk_sp<SkData> serialize() const;
+
+[Path_setConvexity]
+SkPath
+void setConvexity(Convexity convexity);
+
+[Path_setFillType]
+SkPath
+void setFillType(FillType ft);
+
+[Path_setIsVolatile]
+SkPath
+void setIsVolatile(bool isVolatile);
+
+[Path_setLastPt]
+SkPath
+void setLastPt(SkScalar x, SkScalar y);
+
+[Path_setLastPt_2]
+SkPath
+void setLastPt(const SkPoint& p);
+
+[Path_Iter_setPath]
+SkPath
+void setPath(const SkPath& path, bool forceClose);
+
+[Path_swap]
+SkPath
+void swap(SkPath& other);
+
+[Path_toggleInverseFillType]
+SkPath
+void toggleInverseFillType();
+
+[Path_transform_2]
+SkPath
+void transform(const SkMatrix& matrix);
+
+[Path_transform]
+SkPath
+void transform(const SkMatrix& matrix, SkPath* dst) const;
+
+[Path_updateBoundsCache]
+SkPath
+void updateBoundsCache() const;
+
+[Path_writeToMemory]
+SkPath
+size_t writeToMemory(void* buffer) const;
+
+[Path_destructor]
+SkPath
+~SkPath();
+
+[Picture_MakeFromData]
+SkPicture
+static sk_sp<SkPicture> MakeFromData(const SkData* data, const SkDeserialProcs* procs = nullptr);
+
+[Picture_serialize_2]
+SkPicture
+static sk_sp<SkPicture> MakeFromData(const void* data, size_t size, const SkDeserialProcs* procs = nullptr);
+
+[Picture_MakeFromStream]
+SkPicture
+static sk_sp<SkPicture> MakeFromStream(SkStream* stream, const SkDeserialProcs* procs = nullptr);
+
+[Picture_MakePlaceholder]
+SkPicture
+static sk_sp<SkPicture> MakePlaceholder(SkRect cull);
+
+[Picture_AbortCallback_abort]
+SkPicture
+virtual bool abort() = 0;
+
+[Picture_approximateBytesUsed]
+SkPicture
+virtual size_t approximateBytesUsed() const = 0;
+
+[Picture_approximateOpCount]
+SkPicture
+virtual int approximateOpCount() const = 0;
+
+[Picture_cullRect]
+SkPicture
+virtual SkRect cullRect() const = 0;
+
+[Picture_playback]
+SkPicture
+virtual void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const = 0;
+
+[Picture_serialize]
+SkPicture
+sk_sp<SkData> serialize(const SkSerialProcs* procs = nullptr) const;
+
+[Picture_serialize_2]
+SkPicture
+void serialize(SkWStream* stream, const SkSerialProcs* procs = nullptr) const;
+
+[Picture_uniqueID]
+SkPicture
+uint32_t uniqueID() const;
+
+[Pixmap_empty_constructor]
+SkPixmap
+SkPixmap();
+
+[Pixmap_const_SkImageInfo_const_star]
+SkPixmap
+SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes);
+
+[Pixmap_addr]
+SkPixmap
+const void* addr() const;
+
+[Pixmap_addr_2]
+SkPixmap
+const void* addr(int x, int y) const;
+
+[Pixmap_addr16]
+SkPixmap
+const uint16_t* addr16() const;
+
+[Pixmap_addr16_2]
+SkPixmap
+const uint16_t* addr16(int x, int y) const;
+
+[Pixmap_addr32]
+SkPixmap
+const uint32_t* addr32() const;
+
+[Pixmap_addr32_2]
+SkPixmap
+const uint32_t* addr32(int x, int y) const;
+
+[Pixmap_addr64]
+SkPixmap
+const uint64_t* addr64() const;
+
+[Pixmap_addr64_2]
+SkPixmap
+const uint64_t* addr64(int x, int y) const;
+
+[Pixmap_addr8]
+SkPixmap
+const uint8_t* addr8() const;
+
+[Pixmap_addr8_2]
+SkPixmap
+const uint8_t* addr8(int x, int y) const;
+
+[Pixmap_addrF16]
+SkPixmap
+const uint16_t* addrF16() const;
+
+[Pixmap_addrF16_2]
+SkPixmap
+const uint16_t* addrF16(int x, int y) const;
+
+[Pixmap_alphaType]
+SkPixmap
+SkAlphaType alphaType() const;
+
+[Pixmap_bounds]
+SkPixmap
+SkIRect bounds() const;
+
+[Pixmap_colorSpace]
+SkPixmap
+SkColorSpace* colorSpace() const;
+
+[Pixmap_colorType]
+SkPixmap
+SkColorType colorType() const;
+
+[Pixmap_computeByteSize]
+SkPixmap
+size_t computeByteSize() const;
+
+[Pixmap_computeIsOpaque]
+SkPixmap
+bool computeIsOpaque() const;
+
+[Pixmap_erase_2]
+SkPixmap
+bool erase(SkColor color) const;
+
+[Pixmap_erase]
+SkPixmap
+bool erase(SkColor color, const SkIRect& subset) const;
+
+[Pixmap_erase_3]
+SkPixmap
+bool erase(const SkColor4f& color, const SkIRect* subset = nullptr) const;
+
+[Pixmap_extractSubset]
+SkPixmap
+bool extractSubset(SkPixmap* subset, const SkIRect& area) const;
+
+[Pixmap_getColor]
+SkPixmap
+SkColor getColor(int x, int y) const;
+
+[Pixmap_height]
+SkPixmap
+int height() const;
+
+[Pixmap_info]
+SkPixmap
+const SkImageInfo& info() const;
+
+[Pixmap_isOpaque]
+SkPixmap
+bool isOpaque() const;
+
+[Pixmap_readPixels]
+SkPixmap
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const;
+
+[Pixmap_readPixels_2]
+SkPixmap
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY) const;
+
+[Pixmap_readPixels_4]
+SkPixmap
+bool readPixels(const SkPixmap& dst) const;
+
+[Pixmap_readPixels_3]
+SkPixmap
+bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
+
+[Pixmap_reset]
+SkPixmap
+void reset();
+
+[Pixmap_reset_2]
+SkPixmap
+void reset(const SkImageInfo& info, const void* addr, size_t rowBytes);
+
+[Pixmap_rowBytes]
+SkPixmap
+size_t rowBytes() const;
+
+[Pixmap_rowBytesAsPixels]
+SkPixmap
+int rowBytesAsPixels() const;
+
+[Pixmap_scalePixels]
+SkPixmap
+bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality) const;
+
+[Pixmap_setColorSpace]
+SkPixmap
+void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
+[Pixmap_shiftPerPixel]
+SkPixmap
+int shiftPerPixel() const;
+
+[Pixmap_width]
+SkPixmap
+int width() const;
+
+[Pixmap_writable_addr]
+SkPixmap
+void* writable_addr() const;
+
+[Pixmap_writable_addr_2]
+SkPixmap
+void* writable_addr(int x, int y) const;
+
+[Pixmap_writable_addr16]
+SkPixmap
+uint16_t* writable_addr16(int x, int y) const;
+
+[Pixmap_writable_addr32]
+SkPixmap
+uint32_t* writable_addr32(int x, int y) const;
+
+[Pixmap_writable_addr64]
+SkPixmap
+uint64_t* writable_addr64(int x, int y) const;
+
+[Pixmap_writable_addr8]
+SkPixmap
+uint8_t* writable_addr8(int x, int y) const;
+
+[Pixmap_writable_addrF16]
+SkPixmap
+uint16_t* writable_addrF16(int x, int y) const;
+
+[Point_CrossProduct]
+SkPoint
+static SkScalar CrossProduct(const SkVector& a, const SkVector& b);
+
+[Point_Distance]
+SkPoint
+static SkScalar Distance(const SkPoint& a, const SkPoint& b);
+
+[Point_DotProduct]
+SkPoint
+static SkScalar DotProduct(const SkVector& a, const SkVector& b);
+
+[Point_Length]
+SkPoint
+static SkScalar Length(SkScalar x, SkScalar y);
+
+[Point_Make]
+SkPoint
+static constexpr SkPoint Make(SkScalar x, SkScalar y);
+
+[Point_Normalize]
+SkPoint
+static SkScalar Normalize(SkVector* vec);
+
+[Point_Offset_2]
+SkPoint
+static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy);
+
+[Point_Offset]
+SkPoint
+static void Offset(SkPoint points[], int count, const SkVector& offset);
+
+[Point_cross]
+SkPoint
+SkScalar cross(const SkVector& vec) const;
+
+[Point_distanceToOrigin]
+SkPoint
+SkScalar distanceToOrigin() const;
+
+[Point_dot]
+SkPoint
+SkScalar dot(const SkVector& vec) const;
+
+[Point_equals]
+SkPoint
+bool equals(SkScalar x, SkScalar y) const;
+
+[Point_isFinite]
+SkPoint
+bool isFinite() const;
+
+[Point_isZero]
+SkPoint
+bool isZero() const;
+
+[Point_iset_2]
+SkPoint
+void iset(const SkIPoint& p);
+
+[Point_iset]
+SkPoint
+void iset(int32_t x, int32_t y);
+
+[Point_length_2]
+SkPoint
+SkScalar length() const;
+
+[Point_negate]
+SkPoint
+void negate();
+
+[Point_normalize_2]
+SkPoint
+bool normalize();
+
+[Point_offset_3]
+SkPoint
+void offset(SkScalar dx, SkScalar dy);
+
+[Point_notequal_operator]
+SkPoint
+bool operator!=(const SkPoint& a, const SkPoint& b);
+
+[Point_multiply_operator]
+SkPoint
+SkPoint operator*(SkScalar scale) const;
+
+[Point_multiplyby_operator]
+SkPoint
+SkPoint& operator*=(SkScalar scale);
+
+[Point_add_operator]
+SkPoint
+SkPoint operator+(const SkPoint& a, const SkVector& b);
+
+[Point_addto_operator]
+SkPoint
+void operator+=(const SkVector& v);
+
+[Point_minus_operator]
+SkPoint
+SkPoint operator-() const;
+
+[Point_subtract_operator]
+SkPoint
+SkVector operator-(const SkPoint& a, const SkPoint& b);
+
+[Point_subtractfrom_operator]
+SkPoint
+void operator-=(const SkVector& v);
+
+[Point_equal_operator]
+SkPoint
+bool operator==(const SkPoint& a, const SkPoint& b);
+
+[Point_scale]
+SkPoint
+void scale(SkScalar scale, SkPoint* dst) const;
+
+[Point_scale_2]
+SkPoint
+void scale(SkScalar value);
+
+[Point_set]
+SkPoint
+void set(SkScalar x, SkScalar y);
+
+[Point_setAbs]
+SkPoint
+void setAbs(const SkPoint& pt);
+
+[Point_setLength]
+SkPoint
+bool setLength(SkScalar length);
+
+[Point_setLength_2]
+SkPoint
+bool setLength(SkScalar x, SkScalar y, SkScalar length);
+
+[Point_setNormalize]
+SkPoint
+bool setNormalize(SkScalar x, SkScalar y);
+
+[Point_x]
+SkPoint
+SkScalar x() const;
+
+[Point_y]
+SkPoint
+SkScalar y() const;
+
+[RRect_MakeEmpty]
+SkRRect
+static SkRRect MakeEmpty();
+
+[RRect_MakeOval]
+SkRRect
+static SkRRect MakeOval(const SkRect& oval);
+
+[RRect_MakeRect]
+SkRRect
+static SkRRect MakeRect(const SkRect& r);
+
+[RRect_MakeRectXY]
+SkRRect
+static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
+
+[RRect_empty_constructor]
+SkRRect
+SkRRect();
+
+[RRect_copy_const_SkRRect]
+SkRRect
+SkRRect(const SkRRect& rrect);
+
+[RRect_contains]
+SkRRect
+bool contains(const SkRect& rect) const;
+
+[RRect_dump_2]
+SkRRect
+void dump() const;
+
+[RRect_dump]
+SkRRect
+void dump(bool asHex) const;
+
+[RRect_dumpHex]
+SkRRect
+void dumpHex() const;
+
+[RRect_Corner]
+SkRRect
+enum Corner { kUpperLeft_Corner, kUpperRight_Corner, kLowerRight_Corner, kLowerLeft_Corner, };
+
+[RRect_Type]
+SkRRect
+enum Type { kEmpty_Type, kRect_Type, kOval_Type, kSimple_Type, kNinePatch_Type, kComplex_Type, kLastType = kComplex_Type, };
+
+[RRect_getBounds]
+SkRRect
+const SkRect& getBounds() const;
+
+[RRect_getSimpleRadii]
+SkRRect
+SkVector getSimpleRadii() const;
+
+[RRect_getType]
+SkRRect
+Type getType() const;
+
+[RRect_height]
+SkRRect
+SkScalar height() const;
+
+[RRect_inset_2]
+SkRRect
+void inset(SkScalar dx, SkScalar dy);
+
+[RRect_inset]
+SkRRect
+void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
+
+[RRect_isComplex]
+SkRRect
+bool isComplex() const;
+
+[RRect_isEmpty]
+SkRRect
+bool isEmpty() const;
+
+[RRect_isNinePatch]
+SkRRect
+bool isNinePatch() const;
+
+[RRect_isOval]
+SkRRect
+bool isOval() const;
+
+[RRect_isRect]
+SkRRect
+bool isRect() const;
+
+[RRect_isSimple]
+SkRRect
+bool isSimple() const;
+
+[RRect_isValid]
+SkRRect
+bool isValid() const;
+
+[RRect_makeOffset]
+SkRRect
+SkRRect makeOffset(SkScalar dx, SkScalar dy) const;
+
+[RRect_offset]
+SkRRect
+void offset(SkScalar dx, SkScalar dy);
+
+[RRect_notequal_operator]
+SkRRect
+bool operator!=(const SkRRect& a, const SkRRect& b);
+
+[RRect_copy_operator]
+SkRRect
+SkRRect& operator=(const SkRRect& rrect);
+
+[RRect_equal_operator]
+SkRRect
+bool operator==(const SkRRect& a, const SkRRect& b);
+
+[RRect_outset_2]
+SkRRect
+void outset(SkScalar dx, SkScalar dy);
+
+[RRect_outset]
+SkRRect
+void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
+
+[RRect_radii]
+SkRRect
+SkVector radii(Corner corner) const;
+
+[RRect_readFromMemory]
+SkRRect
+size_t readFromMemory(const void* buffer, size_t length);
+
+[RRect_rect]
+SkRRect
+const SkRect& rect() const;
+
+[RRect_setEmpty]
+SkRRect
+void setEmpty();
+
+[RRect_setNinePatch]
+SkRRect
+void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad, SkScalar rightRad, SkScalar bottomRad);
+
+[RRect_setOval]
+SkRRect
+void setOval(const SkRect& oval);
+
+[RRect_setRect]
+SkRRect
+void setRect(const SkRect& rect);
+
+[RRect_setRectRadii]
+SkRRect
+void setRectRadii(const SkRect& rect, const SkVector radii[4]);
+
+[RRect_setRectXY]
+SkRRect
+void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
+
+[RRect_transform]
+SkRRect
+bool transform(const SkMatrix& matrix, SkRRect* dst) const;
+
+[RRect_type_2]
+SkRRect
+Type type() const;
+
+[RRect_width]
+SkRRect
+SkScalar width() const;
+
+[RRect_writeToMemory]
+SkRRect
+size_t writeToMemory(void* buffer) const;
+
+[Rect_Intersects]
+SkRect
+static bool Intersects(const SkRect& a, const SkRect& b);
+
+[Rect_Make_2]
+SkRect
+static SkRect Make(const SkIRect& irect);
+
+[Rect_Make]
+SkRect
+static SkRect Make(const SkISize& size);
+
+[Rect_MakeEmpty]
+SkRect
+static constexpr SkRect MakeEmpty();
+
+[Rect_MakeIWH]
+SkRect
+static SkRect MakeIWH(int w, int h);
+
+[Rect_MakeLTRB]
+SkRect
+static constexpr SkRect MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b);
+
+[Rect_MakeSize]
+SkRect
+static constexpr SkRect MakeSize(const SkSize& size);
+
+[Rect_MakeWH]
+SkRect
+static constexpr SkRect MakeWH(SkScalar w, SkScalar h);
+
+[Rect_MakeXYWH]
+SkRect
+static constexpr SkRect MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h);
+
+[Rect_asScalars]
+SkRect
+const SkScalar* asScalars() const;
+
+[Rect_bottom]
+SkRect
+SkScalar bottom() const;
+
+[Rect_centerX]
+SkRect
+SkScalar centerX() const;
+
+[Rect_centerY]
+SkRect
+SkScalar centerY() const;
+
+[Rect_contains]
+SkRect
+bool contains(SkScalar x, SkScalar y) const;
+
+[Rect_contains_3]
+SkRect
+bool contains(const SkIRect& r) const;
+
+[Rect_contains_2]
+SkRect
+bool contains(const SkRect& r) const;
+
+[Rect_dump_2]
+SkRect
+void dump() const;
+
+[Rect_dump]
+SkRect
+void dump(bool asHex) const;
+
+[Rect_dumpHex]
+SkRect
+void dumpHex() const;
+
+[Rect_height]
+SkRect
+SkScalar height() const;
+
+[Rect_inset]
+SkRect
+void inset(SkScalar dx, SkScalar dy);
+
+[Rect_intersect_2]
+SkRect
+bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+[Rect_intersect_3]
+SkRect
+bool intersect(const SkRect& a, const SkRect& b);
+
+[Rect_intersect]
+SkRect
+bool intersect(const SkRect& r);
+
+[Rect_intersects_3]
+SkRect
+bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const;
+
+[Rect_intersects_2]
+SkRect
+bool intersects(const SkRect& r) const;
+
+[Rect_isEmpty]
+SkRect
+bool isEmpty() const;
+
+[Rect_isFinite]
+SkRect
+bool isFinite() const;
+
+[Rect_isSorted]
+SkRect
+bool isSorted() const;
+
+[Rect_iset]
+SkRect
+void iset(int left, int top, int right, int bottom);
+
+[Rect_isetWH]
+SkRect
+void isetWH(int width, int height);
+
+[Rect_join]
+SkRect
+void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+[Rect_join_2]
+SkRect
+void join(const SkRect& r);
+
+[Rect_joinNonEmptyArg]
+SkRect
+void joinNonEmptyArg(const SkRect& r);
+
+[Rect_joinPossiblyEmptyRect]
+SkRect
+void joinPossiblyEmptyRect(const SkRect& r);
+
+[Rect_left]
+SkRect
+SkScalar left() const;
+
+[Rect_makeInset]
+SkRect
+SkRect makeInset(SkScalar dx, SkScalar dy) const;
+
+[Rect_makeOffset]
+SkRect
+SkRect makeOffset(SkScalar dx, SkScalar dy) const;
+
+[Rect_makeOutset]
+SkRect
+SkRect makeOutset(SkScalar dx, SkScalar dy) const;
+
+[Rect_makeSorted]
+SkRect
+SkRect makeSorted() const;
+
+[Rect_offset]
+SkRect
+void offset(SkScalar dx, SkScalar dy);
+
+[Rect_offset_2]
+SkRect
+void offset(const SkPoint& delta);
+
+[Rect_offsetTo]
+SkRect
+void offsetTo(SkScalar newX, SkScalar newY);
+
+[Rect_notequal_operator]
+SkRect
+bool operator!=(const SkRect& a, const SkRect& b);
+
+[Rect_equal_operator]
+SkRect
+bool operator==(const SkRect& a, const SkRect& b);
+
+[Rect_outset]
+SkRect
+void outset(SkScalar dx, SkScalar dy);
+
+[Rect_right]
+SkRect
+SkScalar right() const;
+
+[Rect_round_2]
+SkRect
+SkIRect round() const;
+
+[Rect_round]
+SkRect
+void round(SkIRect* dst) const;
+
+[Rect_roundIn]
+SkRect
+void roundIn(SkIRect* dst) const;
+
+[Rect_roundOut_3]
+SkRect
+SkIRect roundOut() const;
+
+[Rect_roundOut]
+SkRect
+void roundOut(SkIRect* dst) const;
+
+[Rect_roundOut_2]
+SkRect
+void roundOut(SkRect* dst) const;
+
+[Rect_set_2]
+SkRect
+void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+[Rect_set]
+SkRect
+void set(const SkIRect& src);
+
+[Rect_set_3]
+SkRect
+void set(const SkPoint pts[], int count);
+
+[Rect_set_4]
+SkRect
+void set(const SkPoint& p0, const SkPoint& p1);
+
+[Rect_setBounds]
+SkRect
+void setBounds(const SkPoint pts[], int count);
+
+[Rect_setBoundsCheck]
+SkRect
+bool setBoundsCheck(const SkPoint pts[], int count);
+
+[Rect_setBoundsNoCheck]
+SkRect
+void setBoundsNoCheck(const SkPoint pts[], int count);
+
+[Rect_setEmpty]
+SkRect
+void setEmpty();
+
+[Rect_setLTRB]
+SkRect
+void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+[Rect_setWH]
+SkRect
+void setWH(SkScalar width, SkScalar height);
+
+[Rect_setXYWH]
+SkRect
+void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height);
+
+[Rect_sort]
+SkRect
+void sort();
+
+[Rect_toQuad]
+SkRect
+void toQuad(SkPoint quad[4]) const;
+
+[Rect_top]
+SkRect
+SkScalar top() const;
+
+[Rect_width]
+SkRect
+SkScalar width() const;
+
+[Rect_x]
+SkRect
+SkScalar x() const;
+
+[Rect_y]
+SkRect
+SkScalar y() const;
+
+[Region_Cliperator_const_SkRegion_const_SkIRect]
+SkRegion
+Cliperator(const SkRegion& region, const SkIRect& clip);
+
+[Region_Iterator_Iterator]
+SkRegion
+Iterator();
+
+[Region_Iterator_copy_const_SkRegion]
+SkRegion
+Iterator(const SkRegion& region);
+
+[Region_copy_const_SkIRect]
+SkRegion
+explicit SkRegion(const SkIRect& rect);
+
+[Region_empty_constructor]
+SkRegion
+SkRegion();
+
+[Region_copy_const_SkRegion]
+SkRegion
+SkRegion(const SkRegion& region);
+
+[Region_Spanerator_const_SkRegion_int_int_int]
+SkRegion
+Spanerator(const SkRegion& region, int y, int left, int right);
+
+[Region_computeRegionComplexity]
+SkRegion
+int computeRegionComplexity() const;
+
+[Region_contains_2]
+SkRegion
+bool contains(const SkIRect& other) const;
+
+[Region_contains_3]
+SkRegion
+bool contains(const SkRegion& other) const;
+
+[Region_contains]
+SkRegion
+bool contains(int32_t x, int32_t y) const;
+
+[Region_Iterator_done]
+SkRegion
+bool done() const;
+
+[Region_Cliperator_done]
+SkRegion
+bool done();
+
+[Region_Op]
+SkRegion
+enum Op { kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, kReplace_Op, kLastOp = kReplace_Op, };
+
+[Region_getBoundaryPath]
+SkRegion
+bool getBoundaryPath(SkPath* path) const;
+
+[Region_getBounds]
+SkRegion
+const SkIRect& getBounds() const;
+
+[Region_intersects]
+SkRegion
+bool intersects(const SkIRect& rect) const;
+
+[Region_intersects_2]
+SkRegion
+bool intersects(const SkRegion& other) const;
+
+[Region_isComplex]
+SkRegion
+bool isComplex() const;
+
+[Region_isEmpty]
+SkRegion
+bool isEmpty() const;
+
+[Region_isRect]
+SkRegion
+bool isRect() const;
+
+[Region_Spanerator_next]
+SkRegion
+bool next(int* left, int* right);
+
+[Region_Cliperator_next]
+SkRegion
+void next();
+
+[Region_Iterator_next]
+SkRegion
+void next();
+
+[Region_op_1]
+SkRegion
+bool op(const SkIRect& rect, Op op);
+
+[Region_op_4]
+SkRegion
+bool op(const SkIRect& rect, const SkRegion& rgn, Op op);
+
+[Region_op_3]
+SkRegion
+bool op(const SkRegion& rgn, Op op);
+
+[Region_op_5]
+SkRegion
+bool op(const SkRegion& rgn, const SkIRect& rect, Op op);
+
+[Region_op_6]
+SkRegion
+bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
+
+[Region_op_2]
+SkRegion
+bool op(int left, int top, int right, int bottom, Op op);
+
+[Region_notequal1_operator]
+SkRegion
+bool operator!=(const SkRegion& other) const;
+
+[Region_copy_operator]
+SkRegion
+SkRegion& operator=(const SkRegion& region);
+
+[Region_equal1_operator]
+SkRegion
+bool operator==(const SkRegion& other) const;
+
+[Region_quickContains]
+SkRegion
+bool quickContains(const SkIRect& r) const;
+
+[Region_quickContains_2]
+SkRegion
+bool quickContains(int32_t left, int32_t top, int32_t right, int32_t bottom) const;
+
+[Region_quickReject]
+SkRegion
+bool quickReject(const SkIRect& rect) const;
+
+[Region_quickReject_2]
+SkRegion
+bool quickReject(const SkRegion& rgn) const;
+
+[Region_readFromMemory]
+SkRegion
+size_t readFromMemory(const void* buffer, size_t length);
+
+[Region_Cliperator_rect]
+[Region_Iterator_rect]
+SkRegion
+const SkIRect& rect() const;
+
+[Region_Iterator_reset]
+SkRegion
+void reset(const SkRegion& region);
+
+[Region_Iterator_rewind]
+SkRegion
+bool rewind();
+
+[Region_Iterator_rgn]
+SkRegion
+const SkRegion* rgn() const;
+
+[Region_set]
+SkRegion
+bool set(const SkRegion& src);
+
+[Region_setEmpty]
+SkRegion
+bool setEmpty();
+
+[Region_setPath]
+SkRegion
+bool setPath(const SkPath& path, const SkRegion& clip);
+
+[Region_setRect]
+SkRegion
+bool setRect(const SkIRect& rect);
+
+[Region_setRect_2]
+SkRegion
+bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+[Region_setRects]
+SkRegion
+bool setRects(const SkIRect rects[], int count);
+
+[Region_setRegion]
+SkRegion
+bool setRegion(const SkRegion& region);
+
+[Region_swap]
+SkRegion
+void swap(SkRegion& other);
+
+[Region_translate]
+SkRegion
+void translate(int dx, int dy);
+
+[Region_translate_2]
+SkRegion
+void translate(int dx, int dy, SkRegion* dst) const;
+
+[Region_writeToMemory]
+SkRegion
+size_t writeToMemory(void* buffer) const;
+
+[Region_destructor]
+SkRegion
+~SkRegion();
+
+[Surface_MakeFromBackendTexture]
+SkSurface
+static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* surfaceProps);
+
+[Surface_MakeFromBackendTextureAsRenderTarget]
+SkSurface
+static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* surfaceProps);
+
+[Surface_MakeNull]
+SkSurface
+static sk_sp<SkSurface> MakeNull(int width, int height);
+
+[Surface_MakeRaster_2]
+SkSurface
+static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, const SkSurfaceProps* props = nullptr);
+
+[Surface_MakeRaster]
+SkSurface
+static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes, const SkSurfaceProps* surfaceProps);
+
+[Surface_MakeRasterDirect]
+SkSurface
+static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels, size_t rowBytes, const SkSurfaceProps* surfaceProps = nullptr);
+
+[Surface_MakeRasterDirectReleaseProc]
+SkSurface
+static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels, size_t rowBytes, void (*releaseProc) (void* pixels, void* context) , void* context, const SkSurfaceProps* surfaceProps = nullptr);
+
+[Surface_MakeRasterN32Premul]
+SkSurface
+static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height, const SkSurfaceProps* surfaceProps = nullptr);
+
+[Surface_MakeRenderTarget_3]
+SkSurface
+static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo);
+
+[Surface_MakeRenderTarget]
+SkSurface
+static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps* surfaceProps, bool shouldCreateWithMips = false);
+
+[Surface_MakeRenderTarget_2]
+SkSurface
+static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo, int sampleCount, const SkSurfaceProps* props);
+
+[Surface_characterize]
+SkSurface
+bool characterize(SkSurfaceCharacterization* characterization) const;
+
+[Surface_draw_2]
+SkSurface
+bool draw(SkDeferredDisplayList* deferredDisplayList);
+
+[Surface_draw]
+SkSurface
+void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint);
+
+[Surface_notifyContentWillChange]
+SkSurface
+uint32_t generationID();
+
+[Surface_getCanvas]
+SkSurface
+SkCanvas* getCanvas();
+
+[Surface_height]
+SkSurface
+int height() const;
+
+[Surface_makeImageSnapshot]
+SkSurface
+sk_sp<SkImage> makeImageSnapshot();
+
+[Surface_makeImageSnapshot_2]
+SkSurface
+sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds);
+
+[Surface_makeSurface]
+SkSurface
+sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo);
+
+[Surface_notifyContentWillChange]
+SkSurface
+void notifyContentWillChange(ContentChangeMode mode);
+
+[Surface_peekPixels]
+SkSurface
+bool peekPixels(SkPixmap* pixmap);
+
+[Surface_props]
+SkSurface
+const SkSurfaceProps& props() const;
+
+[Surface_readPixels_3]
+SkSurface
+bool readPixels(const SkBitmap& dst, int srcX, int srcY);
+
+[Surface_readPixels_2]
+SkSurface
+bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY);
+
+[Surface_readPixels]
+SkSurface
+bool readPixels(const SkPixmap& dst, int srcX, int srcY);
+
+[Surface_width]
+SkSurface
+int width() const;
+
+[Surface_writePixels_2]
+SkSurface
+void writePixels(const SkBitmap& src, int dstX, int dstY);
+
+[Surface_writePixels]
+SkSurface
+void writePixels(const SkPixmap& src, int dstX, int dstY);
+
+[TextBlob_Deserialize]
+SkTextBlob
+static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, const SkDeserialProcs& procs);
+
+[TextBlob_MakeFromString]
+SkTextBlob
+static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkFont& font, SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+[TextBlob_MakeFromText]
+SkTextBlob
+static sk_sp<SkTextBlob> MakeFromText(const void* text, size_t byteLength, const SkFont& font, SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+[TextBlob_bounds]
+SkTextBlob
+const SkRect& bounds() const;
+
+[TextBlob_getIntercepts]
+SkTextBlob
+int getIntercepts(const SkScalar bounds[2], SkScalar intervals[], const SkPaint* paint = nullptr) const;
+
+[TextBlob_serialize]
+SkTextBlob
+size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const;
+
+[TextBlob_serialize_2]
+SkTextBlob
+sk_sp<SkData> serialize(const SkSerialProcs& procs) const;
+
+[TextBlob_uniqueID]
+SkTextBlob
+uint32_t uniqueID() const;
+
+[TextBlobBuilder_empty_constructor]
+SkTextBlobBuilder
+SkTextBlobBuilder();
+
+[TextBlobBuilder_allocRun]
+SkTextBlobBuilder
+const RunBuffer& allocRun(const SkFont& font, int count, SkScalar x, SkScalar y, const SkRect* bounds = nullptr);
+
+[TextBlobBuilder_allocRunPos]
+SkTextBlobBuilder
+const RunBuffer& allocRunPos(const SkFont& font, int count, const SkRect* bounds = nullptr);
+
+[TextBlobBuilder_allocRunPosH]
+SkTextBlobBuilder
+const RunBuffer& allocRunPosH(const SkFont& font, int count, SkScalar y, const SkRect* bounds = nullptr);
+
+[TextBlobBuilder_make]
+SkTextBlobBuilder
+sk_sp<SkTextBlob> make();
+
diff --git a/src/third_party/skia/tools/fiddle/draw.cpp b/src/third_party/skia/tools/fiddle/draw.cpp
index 8e94883..32e52c0 100644
--- a/src/third_party/skia/tools/fiddle/draw.cpp
+++ b/src/third_party/skia/tools/fiddle/draw.cpp
@@ -9,11 +9,12 @@
// assembled by the fiddler program to compile into a fiddle: an
// implementation of the GetDrawOptions() and draw() functions.
-#include "fiddle_main.h"
+#include "tools/fiddle/fiddle_main.h"
DrawOptions GetDrawOptions() {
// path *should* be absolute.
- static const char path[] = "resources/color_wheel.png";
- return DrawOptions(256, 256, true, true, true, true, true, false, false, path);
+ static const char path[] = "resources/images/color_wheel.png";
+ return DrawOptions(256, 256, true, true, true, true, true, false, false, path,
+ GrMipMapped::kYes, 64, 64, 0, GrMipMapped::kYes);
}
void draw(SkCanvas* canvas) {
canvas->clear(SK_ColorWHITE);
@@ -21,9 +22,31 @@
matrix.setScale(0.75f, 0.75f);
matrix.preRotate(frame * 30.0f * duration); // If an animation, rotate at 30 deg/s.
SkPaint paint;
- paint.setShader(image->makeShader(SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode,
- &matrix));
+ paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &matrix));
canvas->drawPaint(paint);
SkDebugf("This is text output: %d", 2);
+
+ GrContext* context = canvas->getGrContext();
+ if (context) {
+ sk_sp<SkImage> tmp = SkImage::MakeFromTexture(context,
+ backEndTexture,
+ kTopLeft_GrSurfaceOrigin,
+ kRGBA_8888_SkColorType,
+ kOpaque_SkAlphaType,
+ nullptr);
+
+ // TODO: this sampleCnt parameter here should match that set in the options!
+ sk_sp<SkSurface> tmp2 = SkSurface::MakeFromBackendTexture(context,
+ backEndTextureRenderTarget,
+ kTopLeft_GrSurfaceOrigin,
+ 0, kRGBA_8888_SkColorType,
+ nullptr, nullptr);
+
+ // Note: this surface should only be renderable (i.e., not textureable)
+ sk_sp<SkSurface> tmp3 = SkSurface::MakeFromBackendRenderTarget(context,
+ backEndRenderTarget,
+ kTopLeft_GrSurfaceOrigin,
+ kRGBA_8888_SkColorType,
+ nullptr, nullptr);
+ }
}
diff --git a/src/third_party/skia/tools/fiddle/egl_context.cpp b/src/third_party/skia/tools/fiddle/egl_context.cpp
index 107bb4f..d7b6e58 100644
--- a/src/third_party/skia/tools/fiddle/egl_context.cpp
+++ b/src/third_party/skia/tools/fiddle/egl_context.cpp
@@ -5,77 +5,36 @@
* found in the LICENSE file.
*/
-#include "fiddle_main.h"
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/gl/GrGLFunctions.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/gpu/gl/GLTestContext.h"
#include <EGL/egl.h>
#include <GLES2/gl2.h>
-static const EGLint configAttribs[] = {
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_BLUE_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_RED_SIZE, 8,
- EGL_DEPTH_SIZE, 8,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- EGL_NONE
-};
-
-static const int pbufferWidth = 9;
-static const int pbufferHeight = 9;
-
-static const EGLint pbufferAttribs[] = {
- EGL_WIDTH, pbufferWidth,
- EGL_HEIGHT, pbufferHeight,
- EGL_NONE,
-};
+#include <sstream>
// create_grcontext implementation for EGL.
-sk_sp<GrContext> create_grcontext(std::ostringstream &driverinfo) {
- EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (EGL_NO_DISPLAY == eglDpy) {
+sk_sp<GrContext> create_grcontext(std::ostringstream& driverinfo,
+ std::unique_ptr<sk_gpu_test::GLTestContext>* glContext) {
+ // We are leaking tc, but that's OK because fiddle is a short lived proces.
+ glContext->reset(sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard));
+ if (!glContext) {
+ return nullptr;
+ }
+ (*glContext)->makeCurrent();
+ sk_sp<GrContext> result = (*glContext)->makeGrContext(GrContextOptions());
+ if (!result) {
+ glContext->reset();
return nullptr;
}
- EGLint major, minor;
- if (EGL_TRUE != eglInitialize(eglDpy, &major, &minor)) {
- return nullptr;
- }
+ driverinfo << "GL Version: " << glGetString(GL_VERSION) << "\n";
+ driverinfo << "GL Vendor: " << glGetString(GL_VENDOR) << "\n";
+ driverinfo << "GL Renderer: " << glGetString(GL_RENDERER) << "\n";
+ driverinfo << "GL Extensions: " << glGetString(GL_EXTENSIONS) << "\n";
- EGLint numConfigs;
- EGLConfig eglCfg;
- if (EGL_TRUE != eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs)) {
- return nullptr;
- }
-
- EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg, pbufferAttribs);
- if (EGL_NO_SURFACE == eglSurf) {
- return nullptr;
- }
-
- if (EGL_TRUE != eglBindAPI(EGL_OPENGL_API)) {
- return nullptr;
- }
-
- EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, NULL);
- if (EGL_NO_CONTEXT == eglCtx) {
- return nullptr;
- }
- if (EGL_FALSE == eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx)) {
- return nullptr;
- }
-
- driverinfo << "EGL " << major << "." << minor << "\n";
- GrGLGetStringProc getString = (GrGLGetStringProc )eglGetProcAddress("glGetString");
- driverinfo << "GL Versionr: " << getString(GL_VERSION) << "\n";
- driverinfo << "GL Vendor: " << getString(GL_VENDOR) << "\n";
- driverinfo << "GL Renderer: " << getString(GL_RENDERER) << "\n";
- driverinfo << "GL Extensions: " << getString(GL_EXTENSIONS) << "\n";
-
- auto interface = GrGLCreateNativeInterface();
- if (!interface) {
- return nullptr;
- }
- eglTerminate(eglDpy);
-
- return sk_sp<GrContext>(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)interface));
+ return result;
}
diff --git a/src/third_party/skia/tools/fiddle/examples.cpp b/src/third_party/skia/tools/fiddle/examples.cpp
new file mode 100644
index 0000000..03d3fd2
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/examples.cpp
@@ -0,0 +1,37 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "tools/fiddle/examples.h"
+
+template sk_tools::Registry<fiddle::Example>* sk_tools::Registry<fiddle::Example>::gHead;
+
+// These globals are needed by fiddles:
+GrBackendTexture backEndTexture;
+GrBackendRenderTarget backEndRenderTarget;
+GrBackendTexture backEndTextureRenderTarget;
+SkBitmap source;
+sk_sp<SkImage> image;
+double duration = 1.0;
+double frame = 1.0;
+
+int main() {
+ constexpr int kImgCount = 7;
+ sk_sp<SkImage> images[kImgCount];
+ SkBitmap bitmaps[kImgCount];
+ for (int i = 1; i < kImgCount; ++i) {
+ SkString path = SkStringPrintf("resources/images/example_%d.png", i);
+ images[i] = SkImage::MakeFromEncoded(SkData::MakeFromFileName(path.c_str()));
+ SkAssertResult(images[i] && images[i]->asLegacyBitmap(&bitmaps[i]));
+ }
+ for (const fiddle::Example& example : sk_tools::Registry<fiddle::Example>::Range()) {
+ SkASSERT((unsigned)example.fImageIndex < (unsigned)kImgCount);
+ image = images[example.fImageIndex];
+ source = bitmaps[example.fImageIndex];
+ SkBitmap bmp;
+ bmp.allocN32Pixels(example.fWidth, example.fHeight);
+ bmp.eraseColor(SK_ColorWHITE);
+ SkCanvas canvas(bmp);
+ SkDebugf("==> %s\n", example.fName);
+ example.fFunc(&canvas);
+ }
+}
diff --git a/src/third_party/skia/tools/fiddle/examples.h b/src/third_party/skia/tools/fiddle/examples.h
new file mode 100644
index 0000000..8ecc328
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/examples.h
@@ -0,0 +1,41 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef examples_DEFINED
+#define examples_DEFINED
+
+#include "tools/Registry.h"
+#include "skia.h"
+
+#include <cmath>
+#include <string>
+
+namespace fiddle {
+struct Example {
+ void (*fFunc)(SkCanvas*);
+ const char* fName;
+ int fImageIndex;
+ int fWidth;
+ int fHeight;
+ bool fText;
+ bool fSRGB;
+ bool fF16;
+ bool fAnimation;
+ bool fOffscreen;
+};
+}
+
+extern GrBackendTexture backEndTexture;
+extern GrBackendRenderTarget backEndRenderTarget;
+extern GrBackendTexture backEndTextureRenderTarget;
+extern SkBitmap source;
+extern sk_sp<SkImage> image;
+extern double duration; // The total duration of the animation in seconds.
+extern double frame; // A value in [0, 1] of where we are in the animation.
+
+#define REG_FIDDLE(NAME, W, H, TEXT, I) \
+ namespace example_##NAME { void draw(SkCanvas*); } \
+ sk_tools::Registry<fiddle::Example> reg_##NAME( \
+ fiddle::Example{&example_##NAME::draw, #NAME, I, W, H, TEXT, false, false, false, false}); \
+ namespace example_##NAME
+
+#endif // examples_DEFINED
diff --git a/src/third_party/skia/tools/fiddle/fiddle_main.cpp b/src/third_party/skia/tools/fiddle/fiddle_main.cpp
index 6ceffc9..156f561 100644
--- a/src/third_party/skia/tools/fiddle/fiddle_main.cpp
+++ b/src/third_party/skia/tools/fiddle/fiddle_main.cpp
@@ -10,14 +10,34 @@
#include <sstream>
#include <string>
-#include "SkCommandLineFlags.h"
+#include "src/core/SkAutoPixmapStorage.h"
+#include "src/core/SkMipMap.h"
+#include "src/core/SkUtils.h"
+#include "tools/flags/CommandLineFlags.h"
-#include "fiddle_main.h"
+#include "tools/fiddle/fiddle_main.h"
-DEFINE_double(duration, 1.0, "The total duration, in seconds, of the animation we are drawing.");
-DEFINE_double(frame, 1.0, "A double value in [0, 1] that specifies the point in animation to draw.");
+static DEFINE_double(duration, 1.0,
+ "The total duration, in seconds, of the animation we are drawing.");
+static DEFINE_double(frame, 1.0,
+ "A double value in [0, 1] that specifies the point in animation to draw.");
+
+#include "include/gpu/GrBackendSurface.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrRenderTarget.h"
+#include "tools/gpu/gl/GLTestContext.h"
// Globals externed in fiddle_main.h
+sk_sp<GrTexture> backingTexture; // not externed
+GrBackendTexture backEndTexture;
+
+sk_sp<GrRenderTarget> backingRenderTarget; // not externed
+GrBackendRenderTarget backEndRenderTarget;
+
+sk_sp<GrTexture> backingTextureRenderTarget; // not externed
+GrBackendTexture backEndTextureRenderTarget;
+
SkBitmap source;
sk_sp<SkImage> image;
double duration; // The total duration of the animation in seconds.
@@ -98,8 +118,130 @@
return canvas;
}
+static bool setup_backend_objects(GrContext* context,
+ const SkBitmap& bm,
+ const DrawOptions& options) {
+ if (!context) {
+ return false;
+ }
+
+ auto resourceProvider = context->priv().resourceProvider();
+
+ GrSurfaceDesc backingDesc;
+ backingDesc.fWidth = bm.width();
+ backingDesc.fHeight = bm.height();
+ // This config must match the SkColorType used in draw.cpp in the SkImage and Surface factories
+ backingDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ auto format = resourceProvider->caps()->getDefaultBackendFormat(
+ SkColorTypeToGrColorType(kRGBA_8888_SkColorType), GrRenderable::kNo);
+ auto renderableFormat = resourceProvider->caps()->getDefaultBackendFormat(
+ SkColorTypeToGrColorType(kRGBA_8888_SkColorType), GrRenderable::kYes);
+
+ if (!bm.empty()) {
+ SkPixmap originalPixmap;
+ SkPixmap* pixmap = &originalPixmap;
+ if (!bm.peekPixels(&originalPixmap)) {
+ return false;
+ }
+
+ SkAutoPixmapStorage rgbaPixmap;
+ if (kN32_SkColorType != kRGBA_8888_SkColorType) {
+ if (!rgbaPixmap.tryAlloc(bm.info().makeColorType(kRGBA_8888_SkColorType))) {
+ return false;
+ }
+ if (!bm.readPixels(rgbaPixmap)) {
+ return false;
+ }
+ pixmap = &rgbaPixmap;
+ }
+ int mipLevelCount = GrMipMapped::kYes == options.fMipMapping
+ ? SkMipMap::ComputeLevelCount(bm.width(), bm.height())
+ : 1;
+ std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
+
+ texels[0].fPixels = pixmap->addr();
+ texels[0].fRowBytes = pixmap->rowBytes();
+
+ for (int i = 1; i < mipLevelCount; i++) {
+ texels[i].fPixels = nullptr;
+ texels[i].fRowBytes = 0;
+ }
+
+ backingTexture = resourceProvider->createTexture(
+ backingDesc, format, GrColorType::kRGBA_8888, GrRenderable::kNo, 1, SkBudgeted::kNo,
+ GrProtected::kNo, texels.get(), mipLevelCount);
+ if (!backingTexture) {
+ return false;
+ }
+
+ backEndTexture = backingTexture->getBackendTexture();
+ if (!backEndTexture.isValid()) {
+ return false;
+ }
+ }
+
+ backingDesc.fWidth = options.fOffScreenWidth;
+ backingDesc.fHeight = options.fOffScreenHeight;
+
+ SkAutoTMalloc<uint32_t> data(backingDesc.fWidth * backingDesc.fHeight);
+ sk_memset32(data.get(), 0, backingDesc.fWidth * backingDesc.fHeight);
+
+
+ {
+ // This backend object should be renderable but not textureable. Given the limitations
+ // of how we're creating it though it will wind up being secretly textureable.
+ // We use this fact to initialize it with data but don't allow mipmaps
+ GrMipLevel level0 = { data.get(), backingDesc.fWidth*sizeof(uint32_t) };
+
+ sk_sp<GrTexture> tmp = resourceProvider->createTexture(
+ backingDesc, renderableFormat, GrColorType::kRGBA_8888, GrRenderable::kYes,
+ options.fOffScreenSampleCount, SkBudgeted::kNo, GrProtected::kNo, &level0, 1);
+ if (!tmp || !tmp->asRenderTarget()) {
+ return false;
+ }
+
+ backingRenderTarget = sk_ref_sp(tmp->asRenderTarget());
+
+ backEndRenderTarget = backingRenderTarget->getBackendRenderTarget();
+ if (!backEndRenderTarget.isValid()) {
+ return false;
+ }
+ }
+
+ {
+ int mipLevelCount = GrMipMapped::kYes == options.fOffScreenMipMapping
+ ? SkMipMap::ComputeLevelCount(backingDesc.fWidth, backingDesc.fHeight)
+ : 1;
+ std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
+
+ texels[0].fPixels = data.get();
+ texels[0].fRowBytes = backingDesc.fWidth*sizeof(uint32_t);
+
+ for (int i = 1; i < mipLevelCount; i++) {
+ texels[i].fPixels = nullptr;
+ texels[i].fRowBytes = 0;
+ }
+
+ backingTextureRenderTarget = resourceProvider->createTexture(
+ backingDesc, renderableFormat, GrColorType::kRGBA_8888, GrRenderable::kYes,
+ options.fOffScreenSampleCount, SkBudgeted::kNo, GrProtected::kNo, texels.get(),
+ mipLevelCount);
+ if (!backingTextureRenderTarget || !backingTextureRenderTarget->asRenderTarget()) {
+ return false;
+ }
+
+ backEndTextureRenderTarget = backingTextureRenderTarget->getBackendTexture();
+ if (!backEndTextureRenderTarget.isValid()) {
+ return false;
+ }
+ }
+
+
+ return true;
+}
+
int main(int argc, char** argv) {
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::Parse(argc, argv);
duration = FLAGS_duration;
frame = FLAGS_frame;
DrawOptions options = GetDrawOptions();
@@ -122,8 +264,7 @@
perror("Unable to decode the source image.");
return 1;
}
- SkAssertResult(image->asLegacyBitmap(
- &source, SkImage::kRO_LegacyBitmapMode));
+ SkAssertResult(image->asLegacyBitmap(&source));
}
}
sk_sp<SkData> rasterData, gpuData, pdfData, skpData;
@@ -145,10 +286,16 @@
rasterData = encode_snapshot(rasterSurface);
}
if (options.gpu) {
- auto grContext = create_grcontext(gGLDriverInfo);
+ std::unique_ptr<sk_gpu_test::GLTestContext> glContext;
+ sk_sp<GrContext> grContext = create_grcontext(gGLDriverInfo, &glContext);
if (!grContext) {
fputs("Unable to get GrContext.\n", stderr);
} else {
+ if (!setup_backend_objects(grContext.get(), source, options)) {
+ fputs("Unable to create backend objects.\n", stderr);
+ exit(1);
+ }
+
auto surface = SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kNo, info);
if (!surface) {
fputs("Unable to get render surface.\n", stderr);
@@ -161,7 +308,7 @@
}
if (options.pdf) {
SkDynamicMemoryWStream pdfStream;
- sk_sp<SkDocument> document(SkDocument::MakePDF(&pdfStream));
+ auto document = SkPDF::MakeDocument(&pdfStream);
if (document) {
srand(0);
draw(prepare_canvas(document->beginPage(options.size.width(), options.size.height())));
diff --git a/src/third_party/skia/tools/fiddle/fiddle_main.h b/src/third_party/skia/tools/fiddle/fiddle_main.h
index fb9d409..f497fe1 100644
--- a/src/third_party/skia/tools/fiddle/fiddle_main.h
+++ b/src/third_party/skia/tools/fiddle/fiddle_main.h
@@ -8,27 +8,41 @@
#define fiddle_main_DEFINED
#ifdef FIDDLE_BUILD_TEST
- #include "GrContext.h"
- #include "SkCanvas.h"
- #include "SkDocument.h"
- #include "SkPictureRecorder.h"
- #include "SkStream.h"
- #include "SkSurface.h"
- #include "gl/GrGLAssembleInterface.h"
- #include "gl/GrGLInterface.h"
+ #include "include/core/SkCanvas.h"
+ #include "include/core/SkDocument.h"
+ #include "include/core/SkPictureRecorder.h"
+ #include "include/core/SkStream.h"
+ #include "include/core/SkSurface.h"
+ #include "include/gpu/GrContext.h"
+ #include "include/gpu/gl/GrGLAssembleInterface.h"
+ #include "include/gpu/gl/GrGLInterface.h"
#else
#include "skia.h"
#endif
+#include <memory>
#include <sstream>
+extern GrBackendTexture backEndTexture;
+extern GrBackendRenderTarget backEndRenderTarget;
+extern GrBackendTexture backEndTextureRenderTarget;
extern SkBitmap source;
extern sk_sp<SkImage> image;
extern double duration; // The total duration of the animation in seconds.
extern double frame; // A value in [0, 1] of where we are in the animation.
+namespace sk_gpu_test {
+class GLTestContext;
+}
+
struct DrawOptions {
- DrawOptions(int w, int h, bool r, bool g, bool p, bool k, bool srgb, bool f16, bool textOnly, const char* s)
+ DrawOptions(int w, int h, bool r, bool g, bool p, bool k, bool srgb, bool f16,
+ bool textOnly, const char* s,
+ GrMipMapped mipMapping,
+ int offScreenWidth,
+ int offScreenHeight,
+ int offScreenSampleCount,
+ GrMipMapped offScreenMipMapping)
: size(SkISize::Make(w, h))
, raster(r)
, gpu(g)
@@ -38,7 +52,11 @@
, f16(f16)
, textOnly(textOnly)
, source(s)
- {
+ , fMipMapping(mipMapping)
+ , fOffScreenWidth(offScreenWidth)
+ , fOffScreenHeight(offScreenHeight)
+ , fOffScreenSampleCount(offScreenSampleCount)
+ , fOffScreenMipMapping(offScreenMipMapping) {
// F16 mode is only valid for color correct backends.
SkASSERT(srgb || !f16);
}
@@ -51,6 +69,20 @@
bool f16;
bool textOnly;
const char* source;
+
+ // This flag is used when a GPU texture resource is created and exposed as a GrBackendTexture.
+ // In this case the resource is created with extra room to accomodate mipmaps.
+ // TODO: The SkImage::makeTextureImage API would need to be widened to allow this to be true
+ // for the non-backend gpu SkImages.
+ GrMipMapped fMipMapping;
+
+ // Parameters for an GPU offscreen resource exposed as a GrBackendRenderTarget
+ int fOffScreenWidth;
+ int fOffScreenHeight;
+ int fOffScreenSampleCount;
+ // TODO: should we also expose stencilBits here? How about the config?
+
+ GrMipMapped fOffScreenMipMapping; // only applicable if the offscreen is also textureable
};
extern DrawOptions GetDrawOptions();
@@ -59,6 +91,7 @@
// There are different implementations of create_grcontext() for EGL, Mesa,
// and a fallback to a null context.
-extern sk_sp<GrContext> create_grcontext(std::ostringstream &driverinfo);
+extern sk_sp<GrContext> create_grcontext(std::ostringstream& driverinfo,
+ std::unique_ptr<sk_gpu_test::GLTestContext>* glContext);
#endif // fiddle_main_DEFINED
diff --git a/src/third_party/skia/tools/fiddle/make_all_examples_cpp.py b/src/third_party/skia/tools/fiddle/make_all_examples_cpp.py
new file mode 100755
index 0000000..4c8dcd2
--- /dev/null
+++ b/src/third_party/skia/tools/fiddle/make_all_examples_cpp.py
@@ -0,0 +1,15 @@
+#! /usr/bin/env python
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+''' Run this script to re-generate the `all_examples.cpp` file after adding or
+ deleting example fiddles. '''
+import glob
+import os
+os.chdir(os.path.dirname(__file__))
+with open('all_examples.cpp', 'w') as o:
+ o.write('// Copyright 2019 Google LLC.\n// Use of this source code is '
+ 'governed by a BSD-style license that can be found in the '
+ 'LICENSE file.\n')
+ for path in sorted(glob.glob('../../docs/examples/*.cpp')):
+ o.write('#include "%s"\n' % path)
diff --git a/src/third_party/skia/tools/fiddle/mesa_context.cpp b/src/third_party/skia/tools/fiddle/mesa_context.cpp
deleted file mode 100644
index 3b3726b..0000000
--- a/src/third_party/skia/tools/fiddle/mesa_context.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "fiddle_main.h"
-
-#include <GL/osmesa.h>
-
-// create_grcontext implementation for Mesa.
-sk_sp<GrContext> create_grcontext(std::ostringstream &driverinfo) {
- // We just leak the OSMesaContext... the process will die soon anyway.
- if (OSMesaContext osMesaContext = OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, nullptr)) {
- static uint32_t buffer[16 * 16];
- OSMesaMakeCurrent(osMesaContext, &buffer, GL_UNSIGNED_BYTE, 16, 16);
- }
- driverinfo << "Mesa";
-
- auto osmesa_get = [](void* ctx, const char name[]) {
- SkASSERT(nullptr == ctx);
- SkASSERT(OSMesaGetCurrentContext());
- return OSMesaGetProcAddress(name);
- };
- sk_sp<const GrGLInterface> mesa(GrGLAssembleInterface(nullptr, osmesa_get));
- if (!mesa) {
- return nullptr;
- }
- return sk_sp<GrContext>(GrContext::Create(
- kOpenGL_GrBackend,
- reinterpret_cast<intptr_t>(mesa.get())));
-}
diff --git a/src/third_party/skia/tools/fiddle/null_context.cpp b/src/third_party/skia/tools/fiddle/null_context.cpp
index 3fe0054..360ddd9 100644
--- a/src/third_party/skia/tools/fiddle/null_context.cpp
+++ b/src/third_party/skia/tools/fiddle/null_context.cpp
@@ -5,10 +5,11 @@
* found in the LICENSE file.
*/
-#include "fiddle_main.h"
+#include "tools/fiddle/fiddle_main.h"
// create_grcontext for when neither Mesa nor EGL are available.
-sk_sp<GrContext> create_grcontext(std::ostringstream &driverinfo) {
+sk_sp<GrContext> create_grcontext(std::ostringstream& driverinfo,
+ std::unique_ptr<sk_gpu_test::GLTestContext>* glContext) {
driverinfo << "(no GL driver available)";
return nullptr;
}
diff --git a/src/third_party/skia/tools/flags/SkCommandLineFlags.cpp b/src/third_party/skia/tools/flags/CommandLineFlags.cpp
similarity index 78%
rename from src/third_party/skia/tools/flags/SkCommandLineFlags.cpp
rename to src/third_party/skia/tools/flags/CommandLineFlags.cpp
index bfc9f5e..934ff12 100644
--- a/src/third_party/skia/tools/flags/SkCommandLineFlags.cpp
+++ b/src/third_party/skia/tools/flags/CommandLineFlags.cpp
@@ -5,27 +5,22 @@
* found in the LICENSE file.
*/
-#include "SkCommandLineFlags.h"
-#include "SkTDArray.h"
-#include "SkTSort.h"
+#include "include/private/SkTDArray.h"
+#include "src/core/SkTSort.h"
+#include "tools/flags/CommandLineFlags.h"
#include <stdlib.h>
-#if defined(GOOGLE3) && defined(SK_BUILD_FOR_IOS)
- // This is defined by //base only for iOS (I don't know why).
- DECLARE_bool(undefok)
-#else
- DEFINE_bool(undefok, false, "Silently ignore unknown flags instead of crashing.");
-#endif
-
template <typename T> static void ignore_result(const T&) {}
-bool SkFlagInfo::CreateStringFlag(const char* name, const char* shortName,
- SkCommandLineFlags::StringArray* pStrings,
- const char* defaultValue, const char* helpString,
- const char* extendedHelpString) {
- SkFlagInfo* info = new SkFlagInfo(name, shortName, kString_FlagType, helpString,
- extendedHelpString);
+bool SkFlagInfo::CreateStringFlag(const char* name,
+ const char* shortName,
+ CommandLineFlags::StringArray* pStrings,
+ const char* defaultValue,
+ const char* helpString,
+ const char* extendedHelpString) {
+ SkFlagInfo* info =
+ new SkFlagInfo(name, shortName, kString_FlagType, helpString, extendedHelpString);
info->fDefaultString.set(defaultValue);
info->fStrings = pStrings;
@@ -33,8 +28,8 @@
return true;
}
-void SkFlagInfo::SetDefaultStrings(SkCommandLineFlags::StringArray* pStrings,
- const char* defaultValue) {
+void SkFlagInfo::SetDefaultStrings(CommandLineFlags::StringArray* pStrings,
+ const char* defaultValue) {
pStrings->reset();
if (nullptr == defaultValue) {
return;
@@ -43,7 +38,7 @@
size_t defaultLength = strlen(defaultValue);
if (defaultLength > 0) {
const char* const defaultEnd = defaultValue + defaultLength;
- const char* begin = defaultValue;
+ const char* begin = defaultValue;
while (true) {
while (begin < defaultEnd && ' ' == *begin) {
begin++;
@@ -80,12 +75,12 @@
* @param boolean True if the string represents a boolean, false otherwise.
*/
static bool parse_bool_arg(const char* string, bool* result) {
- static const char* trueValues[] = { "1", "TRUE", "true" };
+ static const char* trueValues[] = {"1", "TRUE", "true"};
if (string_is_in(string, trueValues, SK_ARRAY_COUNT(trueValues))) {
*result = true;
return true;
}
- static const char* falseValues[] = { "0", "FALSE", "false" };
+ static const char* falseValues[] = {"0", "FALSE", "false"};
if (string_is_in(string, falseValues, SK_ARRAY_COUNT(falseValues))) {
*result = false;
return true;
@@ -143,24 +138,20 @@
return false;
}
-SkFlagInfo* SkCommandLineFlags::gHead;
-SkString SkCommandLineFlags::gUsage;
+SkFlagInfo* CommandLineFlags::gHead;
+SkString CommandLineFlags::gUsage;
-void SkCommandLineFlags::SetUsage(const char* usage) {
- gUsage.set(usage);
-}
+void CommandLineFlags::SetUsage(const char* usage) { gUsage.set(usage); }
-void SkCommandLineFlags::PrintUsage() {
- SkDebugf("%s", gUsage.c_str());
-}
+void CommandLineFlags::PrintUsage() { SkDebugf("%s", gUsage.c_str()); }
// Maximum line length for the help message.
#define LINE_LENGTH 72
static void print_indented(const SkString& text) {
- size_t length = text.size();
+ size_t length = text.size();
const char* currLine = text.c_str();
- const char* stop = currLine + length;
+ const char* stop = currLine + length;
while (currLine < stop) {
int lineBreak = SkStrFind(currLine, "\n");
if (lineBreak < 0) {
@@ -177,7 +168,7 @@
if (0 == spaceIndex) {
// No spaces on the entire line. Go ahead and break mid word.
spaceIndex = LINE_LENGTH;
- gap = 0;
+ gap = 0;
} else {
// Skip the space on the next line
gap = 1;
@@ -222,7 +213,7 @@
};
} // namespace
-void SkCommandLineFlags::Parse(int argc, char** argv) {
+void CommandLineFlags::Parse(int argc, const char* const* argv) {
// Only allow calling this function once.
static bool gOnce;
if (gOnce) {
@@ -232,7 +223,7 @@
}
gOnce = true;
- bool helpPrinted = false;
+ bool helpPrinted = false;
bool flagsPrinted = false;
// Loop over argv, starting with 1, since the first is just the name of the program.
for (int i = 1; i < argc; i++) {
@@ -256,12 +247,10 @@
if (0 == helpFlags.count()) {
// If no flags followed --help, print them all
SkTDArray<SkFlagInfo*> allFlags;
- for (SkFlagInfo* flag = SkCommandLineFlags::gHead; flag;
- flag = flag->next()) {
- allFlags.push(flag);
+ for (SkFlagInfo* flag = CommandLineFlags::gHead; flag; flag = flag->next()) {
+ allFlags.push_back(flag);
}
- SkTQSort(&allFlags[0], &allFlags[allFlags.count() - 1],
- CompareFlagsByName());
+ SkTQSort(&allFlags[0], &allFlags[allFlags.count() - 1], CompareFlagsByName());
for (int i = 0; i < allFlags.count(); ++i) {
print_help_for_flag(allFlags[i]);
if (allFlags[i]->extendedHelp().size() > 0) {
@@ -270,8 +259,7 @@
}
}
} else {
- for (SkFlagInfo* flag = SkCommandLineFlags::gHead; flag;
- flag = flag->next()) {
+ for (SkFlagInfo* flag = CommandLineFlags::gHead; flag; flag = flag->next()) {
for (int k = 0; k < helpFlags.count(); k++) {
if (flag->name().equals(helpFlags[k]) ||
flag->shortName().equals(helpFlags[k])) {
@@ -292,8 +280,8 @@
}
if (!helpPrinted) {
SkFlagInfo* matchedFlag = nullptr;
- SkFlagInfo* flag = gHead;
- int startI = i;
+ SkFlagInfo* flag = gHead;
+ int startI = i;
while (flag != nullptr) {
if (flag->match(argv[startI])) {
i = startI;
@@ -307,7 +295,7 @@
case SkFlagInfo::kBool_FlagType:
// Can be handled by match, above, but can also be set by the next
// string.
- if (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
+ if (i + 1 < argc && !SkStrStartsWith(argv[i + 1], '-')) {
i++;
bool value;
if (parse_bool_arg(argv[i], &value)) {
@@ -318,11 +306,11 @@
case SkFlagInfo::kString_FlagType:
flag->resetStrings();
// Add all arguments until another flag is reached.
- while (i+1 < argc) {
+ while (i + 1 < argc) {
char* end = nullptr;
// Negative numbers aren't flags.
- ignore_result(strtod(argv[i+1], &end));
- if (end == argv[i+1] && SkStrStartsWith(argv[i+1], '-')) {
+ ignore_result(strtod(argv[i + 1], &end));
+ if (end == argv[i + 1] && SkStrStartsWith(argv[i + 1], '-')) {
break;
}
i++;
@@ -337,32 +325,27 @@
i++;
flag->setDouble(atof(argv[i]));
break;
- default:
- SkDEBUGFAIL("Invalid flag type");
+ default: SkDEBUGFAIL("Invalid flag type");
}
}
flag = flag->next();
}
if (!matchedFlag) {
#if defined(SK_BUILD_FOR_MAC)
- if (SkStrStartsWith(argv[i], "NSDocumentRevisions")
- || SkStrStartsWith(argv[i], "-NSDocumentRevisions")) {
+ if (SkStrStartsWith(argv[i], "NSDocumentRevisions") ||
+ SkStrStartsWith(argv[i], "-NSDocumentRevisions")) {
i++; // skip YES
} else
#endif
- if (FLAGS_undefok) {
- SkDebugf("FYI: ignoring unknown flag '%s'.\n", argv[i]);
- } else {
SkDebugf("Got unknown flag '%s'. Exiting.\n", argv[i]);
- exit(-1);
- }
+ exit(-1);
}
}
}
// Since all of the flags have been set, release the memory used by each
// flag. FLAGS_x can still be used after this.
SkFlagInfo* flag = gHead;
- gHead = nullptr;
+ gHead = nullptr;
while (flag != nullptr) {
SkFlagInfo* next = flag->next();
delete flag;
@@ -375,15 +358,14 @@
namespace {
-template <typename Strings>
-bool ShouldSkipImpl(const Strings& strings, const char* name) {
- int count = strings.count();
- size_t testLen = strlen(name);
- bool anyExclude = count == 0;
+template <typename Strings> bool ShouldSkipImpl(const Strings& strings, const char* name) {
+ int count = strings.count();
+ size_t testLen = strlen(name);
+ bool anyExclude = count == 0;
for (int i = 0; i < strings.count(); ++i) {
const char* matchName = strings[i];
- size_t matchLen = strlen(matchName);
- bool matchExclude, matchStart, matchEnd;
+ size_t matchLen = strlen(matchName);
+ bool matchExclude, matchStart, matchEnd;
if ((matchExclude = matchName[0] == '~')) {
anyExclude = true;
matchName++;
@@ -396,11 +378,12 @@
if ((matchEnd = matchName[matchLen - 1] == '$')) {
matchLen--;
}
- if (matchStart ? (!matchEnd || matchLen == testLen)
- && strncmp(name, matchName, matchLen) == 0
- : matchEnd ? matchLen <= testLen
- && strncmp(name + testLen - matchLen, matchName, matchLen) == 0
- : strstr(name, matchName) != 0) {
+ if (matchStart
+ ? (!matchEnd || matchLen == testLen) && strncmp(name, matchName, matchLen) == 0
+ : matchEnd
+ ? matchLen <= testLen &&
+ strncmp(name + testLen - matchLen, matchName, matchLen) == 0
+ : strstr(name, matchName) != nullptr) {
return matchExclude;
}
}
@@ -409,9 +392,9 @@
} // namespace
-bool SkCommandLineFlags::ShouldSkip(const SkTDArray<const char*>& strings, const char* name) {
+bool CommandLineFlags::ShouldSkip(const SkTDArray<const char*>& strings, const char* name) {
return ShouldSkipImpl(strings, name);
}
-bool SkCommandLineFlags::ShouldSkip(const StringArray& strings, const char* name) {
+bool CommandLineFlags::ShouldSkip(const StringArray& strings, const char* name) {
return ShouldSkipImpl(strings, name);
}
diff --git a/src/third_party/skia/tools/flags/CommandLineFlags.h b/src/third_party/skia/tools/flags/CommandLineFlags.h
new file mode 100644
index 0000000..7fa3068
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommandLineFlags.h
@@ -0,0 +1,475 @@
+/*
+ * 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 SK_COMMAND_LINE_FLAGS_H
+#define SK_COMMAND_LINE_FLAGS_H
+
+#include "include/core/SkString.h"
+#include "include/private/SkTArray.h"
+#include "include/private/SkTDArray.h"
+
+/**
+ * Including this file (and compiling CommandLineFlags.cpp) provides command line
+ * parsing. In order to use it, use the following macros in global
+ * namespace:
+ *
+ * DEFINE_bool(name, defaultValue, helpString);
+ * DEFINE_string(name, defaultValue, helpString);
+ * DEFINE_int(name, defaultValue, helpString);
+ * DEFINE_double(name, defaultValue, helpString);
+ *
+ * Then, in main, call CommandLineFlags::SetUsage() to describe usage and call
+ * CommandLineFlags::Parse() to parse the flags. Henceforth, each flag can
+ * be referenced using
+ *
+ * FLAGS_name
+ *
+ * For example, the line
+ *
+ * DEFINE_bool(boolean, false, "The variable boolean does such and such");
+ *
+ * will create the following variable:
+ *
+ * bool FLAGS_boolean;
+ *
+ * which will initially be set to false, and can be set to true by using the
+ * flag "--boolean" on the commandline. "--noboolean" will set FLAGS_boolean
+ * to false. FLAGS_boolean can also be set using "--boolean=true" or
+ * "--boolean true" (where "true" can be replaced by "false", "TRUE", "FALSE",
+ * "1" or "0").
+ *
+ * The helpString will be printed if the help flag (-h or -help) is used.
+ *
+ * Similarly, the line
+ *
+ * DEFINE_int(integer, .., ..);
+ *
+ * will create
+ *
+ * int FLAGS_integer;
+ *
+ * and
+ *
+ * DEFINE_double(real, .., ..);
+ *
+ * will create
+ *
+ * double FLAGS_real;
+ *
+ * These flags can be set by specifying, for example, "--integer 7" and
+ * "--real 3.14" on the command line. Unsigned integers are parsed from the
+ * command line using strtoul() so will detect the base (0 for octal, and
+ * 0x or 0X for hex, otherwise assumes decimal).
+ *
+ * Unlike the others, the line
+ *
+ * DEFINE_string(args, .., ..);
+ *
+ * creates an array:
+ *
+ * CommandLineFlags::StringArray FLAGS_args;
+ *
+ * If the default value is the empty string, FLAGS_args will default to a size
+ * of zero. Otherwise it will default to a size of 1 with the default string
+ * as its value. All strings that follow the flag on the command line (until
+ * a string that begins with '-') will be entries in the array.
+ *
+ * DEFINE_extended_string(args, .., .., extendedHelpString);
+ *
+ * creates a similar string array flag as DEFINE_string. The flag will have extended help text
+ * (extendedHelpString) that can the user can see with '--help <args>' flag.
+ *
+ * Any flag can be referenced from another file after using the following:
+ *
+ * DECLARE_x(name);
+ *
+ * (where 'x' is the type specified in the DEFINE).
+ *
+ * Inspired by gflags (https://code.google.com/p/gflags/). Is not quite as
+ * robust as gflags, but suits our purposes. For example, allows creating
+ * a flag -h or -help which will never be used, since CommandLineFlags handles it.
+ * CommandLineFlags will also allow creating --flag and --noflag. Uses the same input
+ * format as gflags and creates similarly named variables (i.e. FLAGS_name).
+ * Strings are handled differently (resulting variable will be an array of
+ * strings) so that a flag can be followed by multiple parameters.
+ */
+
+class SkFlagInfo;
+
+class CommandLineFlags {
+public:
+ /**
+ * Call to set the help message to be displayed. Should be called before
+ * Parse.
+ */
+ static void SetUsage(const char* usage);
+
+ /**
+ * Call this to display the help message. Should be called after SetUsage.
+ */
+ static void PrintUsage();
+
+ /**
+ * Call at the beginning of main to parse flags created by DEFINE_x, above.
+ * Must only be called once.
+ */
+ static void Parse(int argc, const char* const* argv);
+
+ /**
+ * Custom class for holding the arguments for a string flag.
+ * Publicly only has accessors so the strings cannot be modified.
+ */
+ class StringArray {
+ public:
+ StringArray() {}
+ explicit StringArray(const SkTArray<SkString>& strings) : fStrings(strings) {}
+ const char* operator[](int i) const {
+ SkASSERT(i >= 0 && i < fStrings.count());
+ return fStrings[i].c_str();
+ }
+
+ int count() const { return fStrings.count(); }
+
+ bool isEmpty() const { return this->count() == 0; }
+
+ /**
+ * Returns true iff string is equal to one of the strings in this array.
+ */
+ bool contains(const char* string) const {
+ for (int i = 0; i < fStrings.count(); i++) {
+ if (fStrings[i].equals(string)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void set(int i, const char* str) {
+ if (i >= fStrings.count()) {
+ this->append(str);
+ return;
+ }
+ fStrings[i].set(str);
+ }
+
+ const SkString* begin() const { return fStrings.begin(); }
+ const SkString* end() const { return fStrings.end(); }
+
+ private:
+ void reset() { fStrings.reset(); }
+
+ void append(const char* string) { fStrings.push_back().set(string); }
+
+ void append(const char* string, size_t length) { fStrings.push_back().set(string, length); }
+
+ SkTArray<SkString> fStrings;
+
+ friend class SkFlagInfo;
+ };
+
+ /* Takes a list of the form [~][^]match[$]
+ ~ causes a matching test to always be skipped
+ ^ requires the start of the test to match
+ $ requires the end of the test to match
+ ^ and $ requires an exact match
+ If a test does not match any list entry, it is skipped unless some list entry starts with ~
+ */
+ static bool ShouldSkip(const SkTDArray<const char*>& strings, const char* name);
+ static bool ShouldSkip(const StringArray& strings, const char* name);
+
+private:
+ static SkFlagInfo* gHead;
+ static SkString gUsage;
+
+ // For access to gHead.
+ friend class SkFlagInfo;
+};
+
+#define TO_STRING2(s) #s
+#define TO_STRING(s) TO_STRING2(s)
+
+#define DEFINE_bool(name, defaultValue, helpString) \
+ bool FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateBoolFlag( \
+ TO_STRING(name), nullptr, &FLAGS_##name, defaultValue, helpString)
+
+// bool 2 allows specifying a short name. No check is done to ensure that shortName
+// is actually shorter than name.
+#define DEFINE_bool2(name, shortName, defaultValue, helpString) \
+ bool FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateBoolFlag( \
+ TO_STRING(name), TO_STRING(shortName), &FLAGS_##name, defaultValue, helpString)
+
+#define DECLARE_bool(name) extern bool FLAGS_##name;
+
+#define DEFINE_string(name, defaultValue, helpString) \
+ CommandLineFlags::StringArray FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag( \
+ TO_STRING(name), nullptr, &FLAGS_##name, defaultValue, helpString, nullptr)
+#define DEFINE_extended_string(name, defaultValue, helpString, extendedHelpString) \
+ CommandLineFlags::StringArray FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag( \
+ TO_STRING(name), nullptr, &FLAGS_##name, defaultValue, helpString, extendedHelpString)
+
+// string2 allows specifying a short name. There is an assert that shortName
+// is only 1 character.
+#define DEFINE_string2(name, shortName, defaultValue, helpString) \
+ CommandLineFlags::StringArray FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
+ TO_STRING(shortName), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString, \
+ nullptr)
+
+#define DECLARE_string(name) extern CommandLineFlags::StringArray FLAGS_##name;
+
+#define DEFINE_int(name, defaultValue, helpString) \
+ int FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = \
+ SkFlagInfo::CreateIntFlag(TO_STRING(name), &FLAGS_##name, defaultValue, helpString)
+
+#define DEFINE_int_2(name, shortName, defaultValue, helpString) \
+ int FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = SkFlagInfo::CreateIntFlag( \
+ TO_STRING(name), TO_STRING(shortName), &FLAGS_##name, defaultValue, helpString)
+
+#define DECLARE_int(name) extern int FLAGS_##name;
+
+#define DEFINE_double(name, defaultValue, helpString) \
+ double FLAGS_##name; \
+ SK_UNUSED static bool unused_##name = \
+ SkFlagInfo::CreateDoubleFlag(TO_STRING(name), &FLAGS_##name, defaultValue, helpString)
+
+#define DECLARE_double(name) extern double FLAGS_##name;
+
+class SkFlagInfo {
+public:
+ enum FlagTypes {
+ kBool_FlagType,
+ kString_FlagType,
+ kInt_FlagType,
+ kDouble_FlagType,
+ };
+
+ /**
+ * Each Create<Type>Flag function creates an SkFlagInfo of the specified type. The SkFlagInfo
+ * object is appended to a list, which is deleted when CommandLineFlags::Parse is called.
+ * Therefore, each call should be made before the call to ::Parse. They are not intended
+ * to be called directly. Instead, use the macros described above.
+ * @param name Long version (at least 2 characters) of the name of the flag. This name can
+ * be referenced on the command line as "--name" to set the value of this flag.
+ * @param shortName Short version (one character) of the name of the flag. This name can
+ * be referenced on the command line as "-shortName" to set the value of this flag.
+ * @param p<Type> Pointer to a global variable which holds the value set by CommandLineFlags.
+ * @param defaultValue The default value of this flag. The variable pointed to by p<Type> will
+ * be set to this value initially. This is also displayed as part of the help output.
+ * @param helpString Explanation of what this flag changes in the program.
+ */
+ static bool CreateBoolFlag(const char* name,
+ const char* shortName,
+ bool* pBool,
+ bool defaultValue,
+ const char* helpString) {
+ SkFlagInfo* info = new SkFlagInfo(name, shortName, kBool_FlagType, helpString, nullptr);
+ info->fBoolValue = pBool;
+ *info->fBoolValue = info->fDefaultBool = defaultValue;
+ return true;
+ }
+
+ /**
+ * See comments for CreateBoolFlag.
+ * @param pStrings Unlike the others, this is a pointer to an array of values.
+ * @param defaultValue Thise default will be parsed so that strings separated by spaces
+ * will be added to pStrings.
+ */
+ static bool CreateStringFlag(const char* name,
+ const char* shortName,
+ CommandLineFlags::StringArray* pStrings,
+ const char* defaultValue,
+ const char* helpString,
+ const char* extendedHelpString);
+
+ /**
+ * See comments for CreateBoolFlag.
+ */
+ static bool CreateIntFlag(const char* name,
+ int* pInt,
+ int defaultValue,
+ const char* helpString) {
+ SkFlagInfo* info = new SkFlagInfo(name, nullptr, kInt_FlagType, helpString, nullptr);
+ info->fIntValue = pInt;
+ *info->fIntValue = info->fDefaultInt = defaultValue;
+ return true;
+ }
+
+ static bool CreateIntFlag(const char* name,
+ const char* shortName,
+ int* pInt,
+ int defaultValue,
+ const char* helpString) {
+ SkFlagInfo* info = new SkFlagInfo(name, shortName, kInt_FlagType, helpString, nullptr);
+ info->fIntValue = pInt;
+ *info->fIntValue = info->fDefaultInt = defaultValue;
+ return true;
+ }
+
+ /**
+ * See comments for CreateBoolFlag.
+ */
+ static bool CreateDoubleFlag(const char* name,
+ double* pDouble,
+ double defaultValue,
+ const char* helpString) {
+ SkFlagInfo* info = new SkFlagInfo(name, nullptr, kDouble_FlagType, helpString, nullptr);
+ info->fDoubleValue = pDouble;
+ *info->fDoubleValue = info->fDefaultDouble = defaultValue;
+ return true;
+ }
+
+ /**
+ * Returns true if the string matches this flag.
+ * For a boolean flag, also sets the value, since a boolean flag can be set in a number of ways
+ * without looking at the following string:
+ * --name
+ * --noname
+ * --name=true
+ * --name=false
+ * --name=1
+ * --name=0
+ * --name=TRUE
+ * --name=FALSE
+ */
+ bool match(const char* string);
+
+ FlagTypes getFlagType() const { return fFlagType; }
+
+ void resetStrings() {
+ if (kString_FlagType == fFlagType) {
+ fStrings->reset();
+ } else {
+ SkDEBUGFAIL("Can only call resetStrings on kString_FlagType");
+ }
+ }
+
+ void append(const char* string) {
+ if (kString_FlagType == fFlagType) {
+ fStrings->append(string);
+ } else {
+ SkDEBUGFAIL("Can only append to kString_FlagType");
+ }
+ }
+
+ void setInt(int value) {
+ if (kInt_FlagType == fFlagType) {
+ *fIntValue = value;
+ } else {
+ SkDEBUGFAIL("Can only call setInt on kInt_FlagType");
+ }
+ }
+
+ void setDouble(double value) {
+ if (kDouble_FlagType == fFlagType) {
+ *fDoubleValue = value;
+ } else {
+ SkDEBUGFAIL("Can only call setDouble on kDouble_FlagType");
+ }
+ }
+
+ void setBool(bool value) {
+ if (kBool_FlagType == fFlagType) {
+ *fBoolValue = value;
+ } else {
+ SkDEBUGFAIL("Can only call setBool on kBool_FlagType");
+ }
+ }
+
+ SkFlagInfo* next() { return fNext; }
+
+ const SkString& name() const { return fName; }
+
+ const SkString& shortName() const { return fShortName; }
+
+ const SkString& help() const { return fHelpString; }
+ const SkString& extendedHelp() const { return fExtendedHelpString; }
+
+ SkString defaultValue() const {
+ SkString result;
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType:
+ result.printf("%s", fDefaultBool ? "true" : "false");
+ break;
+ case SkFlagInfo::kString_FlagType: return fDefaultString;
+ case SkFlagInfo::kInt_FlagType: result.printf("%i", fDefaultInt); break;
+ case SkFlagInfo::kDouble_FlagType: result.printf("%2.2f", fDefaultDouble); break;
+ default: SkDEBUGFAIL("Invalid flag type");
+ }
+ return result;
+ }
+
+ SkString typeAsString() const {
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType: return SkString("bool");
+ case SkFlagInfo::kString_FlagType: return SkString("string");
+ case SkFlagInfo::kInt_FlagType: return SkString("int");
+ case SkFlagInfo::kDouble_FlagType: return SkString("double");
+ default: SkDEBUGFAIL("Invalid flag type"); return SkString();
+ }
+ }
+
+private:
+ SkFlagInfo(const char* name,
+ const char* shortName,
+ FlagTypes type,
+ const char* helpString,
+ const char* extendedHelpString)
+ : fName(name)
+ , fShortName(shortName)
+ , fFlagType(type)
+ , fHelpString(helpString)
+ , fExtendedHelpString(extendedHelpString)
+ , fBoolValue(nullptr)
+ , fDefaultBool(false)
+ , fIntValue(nullptr)
+ , fDefaultInt(0)
+ , fDoubleValue(nullptr)
+ , fDefaultDouble(0)
+ , fStrings(nullptr) {
+ fNext = CommandLineFlags::gHead;
+ CommandLineFlags::gHead = this;
+ SkASSERT(name && strlen(name) > 1);
+ SkASSERT(nullptr == shortName || 1 == strlen(shortName));
+ }
+
+ /**
+ * Set a StringArray to hold the values stored in defaultStrings.
+ * @param array The StringArray to modify.
+ * @param defaultStrings Space separated list of strings that should be inserted into array
+ * individually.
+ */
+ static void SetDefaultStrings(CommandLineFlags::StringArray* array, const char* defaultStrings);
+
+ // Name of the flag, without initial dashes
+ SkString fName;
+ SkString fShortName;
+ FlagTypes fFlagType;
+ SkString fHelpString;
+ SkString fExtendedHelpString;
+ bool* fBoolValue;
+ bool fDefaultBool;
+ int* fIntValue;
+ int fDefaultInt;
+ double* fDoubleValue;
+ double fDefaultDouble;
+ CommandLineFlags::StringArray* fStrings;
+ // Both for the help string and in case fStrings is empty.
+ SkString fDefaultString;
+
+ // In order to keep a linked list.
+ SkFlagInfo* fNext;
+};
+#endif // SK_COMMAND_LINE_FLAGS_H
diff --git a/src/third_party/skia/tools/flags/CommonFlags.h b/src/third_party/skia/tools/flags/CommonFlags.h
new file mode 100644
index 0000000..83ed083
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlags.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#pragma once
+
+#include "include/core/SkString.h"
+#include "include/private/SkTArray.h"
+#include "tools/flags/CommandLineFlags.h"
+
+/**
+ * Helper to assist in collecting image paths from |dir| specified through a command line
+ * flag.
+ *
+ * Populates |output|, an array of strings with paths to images to test.
+ *
+ * Returns true if each argument to the images flag is meaningful:
+ * - If the file/directory does not exist, return false.
+ * - If |dir| does not have any supported images (based on file type), return false.
+ * - If |dir| is a single file, assume the user is deliberately testing this image,
+ * regardless of file type.
+ */
+bool CollectImages(CommandLineFlags::StringArray dir, SkTArray<SkString>* output);
+
+/**
+ * Helper to set GrContextOptions from common GPU flags, including
+ * --gpuThreads
+ * --cachePathMasks
+ * --noGS
+ * --pr
+ * --disableDriverCorrectnessWorkarounds
+ * --reduceOpsTaskSplitting
+ * --dontReduceOpsTaskSplitting
+ */
+void SetCtxOptionsFromCommonFlags(struct GrContextOptions*);
+
+/**
+ * Enable, disable, or force analytic anti-aliasing using --analyticAA and --forceAnalyticAA.
+ */
+void SetAnalyticAAFromCommonFlags();
diff --git a/src/third_party/skia/tools/flags/CommonFlagsAA.cpp b/src/third_party/skia/tools/flags/CommonFlagsAA.cpp
new file mode 100644
index 0000000..e2df08a
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlagsAA.cpp
@@ -0,0 +1,16 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "src/core/SkScan.h"
+#include "tools/flags/CommonFlags.h"
+
+static DEFINE_bool(analyticAA, true, "If false, disable analytic anti-aliasing");
+static DEFINE_bool(forceAnalyticAA, false,
+ "Force analytic anti-aliasing even if the path is complicated: "
+ "whether it's concave or convex, we consider a path complicated"
+ "if its number of points is comparable to its resolution.");
+
+void SetAnalyticAAFromCommonFlags() {
+ gSkUseAnalyticAA = FLAGS_analyticAA;
+ gSkForceAnalyticAA = FLAGS_forceAnalyticAA;
+}
diff --git a/src/third_party/skia/tools/flags/CommonFlagsConfig.cpp b/src/third_party/skia/tools/flags/CommonFlagsConfig.cpp
new file mode 100644
index 0000000..dee1d90
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlagsConfig.cpp
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkImageInfo.h"
+#include "include/private/SkTHash.h"
+#include "src/core/SkColorSpacePriv.h"
+#include "tools/flags/CommonFlagsConfig.h"
+
+#include <stdlib.h>
+
+using sk_gpu_test::GrContextFactory;
+
+#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
+#define DEFAULT_GPU_CONFIG "gles"
+#else
+#define DEFAULT_GPU_CONFIG "gl"
+#endif
+
+static const char defaultConfigs[] = "8888 " DEFAULT_GPU_CONFIG
+ " nonrendering "
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ " angle_d3d11_es2"
+#endif
+ ;
+
+#undef DEFAULT_GPU_CONFIG
+
+// clang-format off
+static const struct {
+ const char* predefinedConfig;
+ const char* backend;
+ const char* options;
+} gPredefinedConfigs[] = {
+ { "gl", "gpu", "api=gl" },
+ { "gles", "gpu", "api=gles" },
+ { "glmsaa4", "gpu", "api=gl,samples=4" },
+ { "glmsaa8" , "gpu", "api=gl,samples=8" },
+ { "glesmsaa4", "gpu", "api=gles,samples=4" },
+ { "glbetex", "gpu", "api=gl,surf=betex" },
+ { "glesbetex", "gpu", "api=gles,surf=betex" },
+ { "glbert", "gpu", "api=gl,surf=bert" },
+ { "glesbert", "gpu", "api=gles,surf=bert" },
+ { "gl4444", "gpu", "api=gl,color=4444" },
+ { "gles4444", "gpu", "api=gles,color=4444" },
+ { "gl565", "gpu", "api=gl,color=565" },
+ { "gl888x", "gpu", "api=gl,color=888x" },
+ { "gles888x", "gpu", "api=gles,color=888x" },
+ { "gl1010102", "gpu", "api=gl,color=1010102" },
+ { "gles1010102", "gpu", "api=gles,color=1010102" },
+ { "glsrgb", "gpu", "api=gl,color=srgb" },
+ { "glp3", "gpu", "api=gl,color=p3" },
+ { "glesrgb", "gpu", "api=gl,color=esrgb" },
+ { "glnarrow", "gpu", "api=gl,color=narrow" },
+ { "glenarrow", "gpu", "api=gl,color=enarrow" },
+ { "glf16", "gpu", "api=gl,color=f16" },
+ { "glf16norm", "gpu", "api=gl,color=f16norm" },
+ { "glessrgb", "gpu", "api=gles,color=srgb" },
+ { "glesesrgb", "gpu", "api=gles,color=esrgb" },
+ { "glesnarrow", "gpu", "api=gles,color=narrow" },
+ { "glesenarrow", "gpu", "api=gles,color=enarrow" },
+ { "glesf16", "gpu", "api=gles,color=f16" },
+ { "glnostencils", "gpu", "api=gl,stencils=false" },
+ { "gldft", "gpu", "api=gl,dit=true" },
+ { "glesdft", "gpu", "api=gles,dit=true" },
+ { "gltestthreading", "gpu", "api=gl,testThreading=true" },
+ { "gltestpersistentcache", "gpu", "api=gl,testPersistentCache=1" },
+ { "gltestglslcache", "gpu", "api=gl,testPersistentCache=2" },
+ { "gltestprecompile", "gpu", "api=gl,testPrecompile=true" },
+ { "glestestprecompile", "gpu", "api=gles,testPrecompile=true" },
+ { "angle_d3d11_es2", "gpu", "api=angle_d3d11_es2" },
+ { "angle_d3d11_es3", "gpu", "api=angle_d3d11_es3" },
+ { "angle_d3d9_es2", "gpu", "api=angle_d3d9_es2" },
+ { "angle_d3d11_es2_msaa4", "gpu", "api=angle_d3d11_es2,samples=4" },
+ { "angle_d3d11_es2_msaa8", "gpu", "api=angle_d3d11_es2,samples=8" },
+ { "angle_d3d11_es3_msaa4", "gpu", "api=angle_d3d11_es3,samples=4" },
+ { "angle_d3d11_es3_msaa8", "gpu", "api=angle_d3d11_es3,samples=8" },
+ { "angle_gl_es2", "gpu", "api=angle_gl_es2" },
+ { "angle_gl_es3", "gpu", "api=angle_gl_es3" },
+ { "angle_gl_es2_msaa8", "gpu", "api=angle_gl_es2,samples=8" },
+ { "angle_gl_es3_msaa8", "gpu", "api=angle_gl_es3,samples=8" },
+ { "commandbuffer", "gpu", "api=commandbuffer" },
+ { "mock", "gpu", "api=mock" },
+#ifdef SK_DAWN
+ { "dawn", "gpu", "api=dawn" },
+#endif
+#ifdef SK_VULKAN
+ { "vk", "gpu", "api=vulkan" },
+ { "vknostencils", "gpu", "api=vulkan,stencils=false" },
+ { "vk1010102", "gpu", "api=vulkan,color=1010102" },
+ { "vksrgb", "gpu", "api=vulkan,color=srgb" },
+ { "vkesrgb", "gpu", "api=vulkan,color=esrgb" },
+ { "vknarrow", "gpu", "api=vulkan,color=narrow" },
+ { "vkenarrow", "gpu", "api=vulkan,color=enarrow" },
+ { "vkf16", "gpu", "api=vulkan,color=f16" },
+ { "vkmsaa4", "gpu", "api=vulkan,samples=4" },
+ { "vkmsaa8", "gpu", "api=vulkan,samples=8" },
+ { "vkbetex", "gpu", "api=vulkan,surf=betex" },
+ { "vkbert", "gpu", "api=vulkan,surf=bert" },
+ { "vktestpersistentcache", "gpu", "api=vulkan,testPersistentCache=1" },
+#endif
+#ifdef SK_METAL
+ { "mtl", "gpu", "api=metal" },
+ { "mtl1010102", "gpu", "api=metal,color=1010102" },
+ { "mtlmsaa4", "gpu", "api=metal,samples=4" },
+ { "mtlmsaa8", "gpu", "api=metal,samples=8" },
+#endif
+};
+// clang-format on
+
+static const char configHelp[] =
+ "Options: 565 8888 srgb f16 nonrendering null pdf pdfa skp pipe svg xps";
+
+static const char* config_help_fn() {
+ static SkString helpString;
+ helpString.set(configHelp);
+ for (const auto& config : gPredefinedConfigs) {
+ helpString.appendf(" %s", config.predefinedConfig);
+ }
+ helpString.append(" or use extended form 'backend[option=value,...]'.\n");
+ return helpString.c_str();
+}
+
+static const char configExtendedHelp[] =
+ "Extended form: 'backend(option=value,...)'\n\n"
+ "Possible backends and options:\n"
+ "\n"
+ "gpu[api=string,color=string,dit=bool,samples=int]\n"
+ "\tapi\ttype: string\trequired\n"
+ "\t Select graphics API to use with gpu backend.\n"
+ "\t Options:\n"
+ "\t\tgl \t\t\tUse OpenGL.\n"
+ "\t\tgles \t\t\tUse OpenGL ES.\n"
+ "\t\tnullgl \t\t\tUse null OpenGL.\n"
+ "\t\tangle_d3d9_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n"
+ "\t\tangle_d3d11_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n"
+ "\t\tangle_d3d11_es3\t\tUse OpenGL ES3 on the ANGLE Direct3D11 backend.\n"
+ "\t\tangle_gl_es2\t\tUse OpenGL ES2 on the ANGLE OpenGL backend.\n"
+ "\t\tangle_gl_es3\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
+ "\t\tcommandbuffer\t\tUse command buffer.\n"
+ "\t\tmock\t\t\tUse mock context.\n"
+#ifdef SK_VULKAN
+ "\t\tvulkan\t\t\tUse Vulkan.\n"
+#endif
+#ifdef SK_METAL
+ "\t\tmetal\t\t\tUse Metal.\n"
+#endif
+ "\tcolor\ttype: string\tdefault: 8888.\n"
+ "\t Select framebuffer color format.\n"
+ "\t Options:\n"
+ "\t\t8888\t\t\tLinear 8888.\n"
+ "\t\t888x\t\t\tLinear 888x.\n"
+ "\t\t4444\t\t\tLinear 4444.\n"
+ "\t\t565\t\t\tLinear 565.\n"
+ "\t\t1010102\t\t\tLinear 1010102.\n"
+ "\t\tsrgb\t\t\tsRGB 8888.\n"
+ "\t\tesrgb\t\t\tsRGB 16-bit floating point.\n"
+ "\t\tnarrow\t\t\tNarrow gamut 8888.\n"
+ "\t\tenarrow\t\t\tNarrow gamut 16-bit floating point.\n"
+ "\t\tf16\t\t\tLinearly blended 16-bit floating point.\n"
+ "\tdit\ttype: bool\tdefault: false.\n"
+ "\t Use device independent text.\n"
+ "\tsamples\ttype: int\tdefault: 0.\n"
+ "\t Use multisampling with N samples.\n"
+ "\tstencils\ttype: bool\tdefault: true.\n"
+ "\t Allow the use of stencil buffers.\n"
+ "\ttestThreading\ttype: bool\tdefault: false.\n"
+ "\t Run with and without worker threads, check that results match.\n"
+ "\ttestPersistentCache\ttype: int\tdefault: 0.\n"
+ "\t 1: Run using a pre-warmed binary GrContextOptions::fPersistentCache.\n"
+ "\t 2: Run using a pre-warmed GLSL GrContextOptions::fPersistentCache.\n"
+ "\tsurf\ttype: string\tdefault: default.\n"
+ "\t Controls the type of backing store for SkSurfaces.\n"
+ "\t Options:\n"
+ "\t\tdefault\t\t\tA renderable texture created in Skia's resource cache.\n"
+ "\t\tbetex\t\t\tA wrapped backend texture.\n"
+ "\t\tbert\t\t\tA wrapped backend render target\n"
+ "\n"
+ "Predefined configs:\n\n"
+ // Help text for pre-defined configs is auto-generated from gPredefinedConfigs
+ ;
+
+static const char* config_extended_help_fn() {
+ static SkString helpString;
+ helpString.set(configExtendedHelp);
+ for (const auto& config : gPredefinedConfigs) {
+ helpString.appendf("\t%-10s\t= gpu(%s)\n", config.predefinedConfig, config.options);
+ }
+ return helpString.c_str();
+}
+
+DEFINE_extended_string(config, defaultConfigs, config_help_fn(), config_extended_help_fn());
+
+SkCommandLineConfig::SkCommandLineConfig(const SkString& tag,
+ const SkString& backend,
+ const SkTArray<SkString>& viaParts)
+ : fTag(tag), fBackend(backend), fViaParts(viaParts) {}
+SkCommandLineConfig::~SkCommandLineConfig() {}
+
+static bool parse_option_int(const SkString& value, int* outInt) {
+ if (value.isEmpty()) {
+ return false;
+ }
+ char* endptr = nullptr;
+ long intValue = strtol(value.c_str(), &endptr, 10);
+ if (*endptr != '\0') {
+ return false;
+ }
+ *outInt = static_cast<int>(intValue);
+ return true;
+}
+static bool parse_option_bool(const SkString& value, bool* outBool) {
+ if (value.equals("true")) {
+ *outBool = true;
+ return true;
+ }
+ if (value.equals("false")) {
+ *outBool = false;
+ return true;
+ }
+ return false;
+}
+static bool parse_option_gpu_api(const SkString& value,
+ SkCommandLineConfigGpu::ContextType* outContextType) {
+ if (value.equals("gl")) {
+ *outContextType = GrContextFactory::kGL_ContextType;
+ return true;
+ }
+ if (value.equals("gles")) {
+ *outContextType = GrContextFactory::kGLES_ContextType;
+ return true;
+ }
+ if (value.equals("angle_d3d9_es2")) {
+ *outContextType = GrContextFactory::kANGLE_D3D9_ES2_ContextType;
+ return true;
+ }
+ if (value.equals("angle_d3d11_es2")) {
+ *outContextType = GrContextFactory::kANGLE_D3D11_ES2_ContextType;
+ return true;
+ }
+ if (value.equals("angle_d3d11_es3")) {
+ *outContextType = GrContextFactory::kANGLE_D3D11_ES3_ContextType;
+ return true;
+ }
+ if (value.equals("angle_gl_es2")) {
+ *outContextType = GrContextFactory::kANGLE_GL_ES2_ContextType;
+ return true;
+ }
+ if (value.equals("angle_gl_es3")) {
+ *outContextType = GrContextFactory::kANGLE_GL_ES3_ContextType;
+ return true;
+ }
+ if (value.equals("commandbuffer")) {
+ *outContextType = GrContextFactory::kCommandBuffer_ContextType;
+ return true;
+ }
+ if (value.equals("mock")) {
+ *outContextType = GrContextFactory::kMock_ContextType;
+ return true;
+ }
+#ifdef SK_VULKAN
+ if (value.equals("vulkan")) {
+ *outContextType = GrContextFactory::kVulkan_ContextType;
+ return true;
+ }
+#endif
+#ifdef SK_METAL
+ if (value.equals("metal")) {
+ *outContextType = GrContextFactory::kMetal_ContextType;
+ return true;
+ }
+#endif
+#ifdef SK_DAWN
+ if (value.equals("dawn")) {
+ *outContextType = GrContextFactory::kDawn_ContextType;
+ return true;
+ }
+#endif
+ return false;
+}
+
+static bool parse_option_gpu_color(const SkString& value,
+ SkColorType* outColorType,
+ SkAlphaType* alphaType,
+ sk_sp<SkColorSpace>* outColorSpace) {
+ // We always use premul unless the color type is 565.
+ *alphaType = kPremul_SkAlphaType;
+
+ if (value.equals("8888")) {
+ *outColorType = kRGBA_8888_SkColorType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("888x")) {
+ *outColorType = kRGB_888x_SkColorType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("8888s")) {
+ *outColorType = kRGBA_8888_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGB();
+ } else if (value.equals("bgra8")) {
+ *outColorType = kBGRA_8888_SkColorType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("bgra8s")) {
+ *outColorType = kBGRA_8888_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGB();
+ } else if (value.equals("4444")) {
+ *outColorType = kARGB_4444_SkColorType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("565")) {
+ *outColorType = kRGB_565_SkColorType;
+ *alphaType = kOpaque_SkAlphaType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("1010102")) {
+ *outColorType = kRGBA_1010102_SkColorType;
+ *outColorSpace = nullptr;
+ } else if (value.equals("srgb")) {
+ *outColorType = kRGBA_8888_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGB();
+ } else if (value.equals("p3")) {
+ *outColorType = kRGBA_8888_SkColorType;
+ *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ } else if (value.equals("esrgb")) {
+ *outColorType = kRGBA_F16_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGB();
+ } else if (value.equals("narrow") || value.equals("enarrow")) {
+ *outColorType = value.equals("narrow") ? kRGBA_8888_SkColorType : kRGBA_F16_SkColorType;
+ *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gNarrow_toXYZD50);
+ } else if (value.equals("f16")) {
+ *outColorType = kRGBA_F16_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGBLinear();
+ } else if (value.equals("f16norm")) {
+ *outColorType = kRGBA_F16Norm_SkColorType;
+ *outColorSpace = SkColorSpace::MakeSRGB();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool parse_option_gpu_surf_type(const SkString& value,
+ SkCommandLineConfigGpu::SurfType* surfType) {
+ if (value.equals("default")) {
+ *surfType = SkCommandLineConfigGpu::SurfType::kDefault;
+ return true;
+ }
+ if (value.equals("betex")) {
+ *surfType = SkCommandLineConfigGpu::SurfType::kBackendTexture;
+ return true;
+ }
+ if (value.equals("bert")) {
+ *surfType = SkCommandLineConfigGpu::SurfType::kBackendRenderTarget;
+ return true;
+ }
+ return false;
+}
+
+// Extended options take form --config item[key1=value1,key2=value2,...]
+// Example: --config gpu[api=gl,color=8888]
+class ExtendedOptions {
+public:
+ ExtendedOptions(const SkString& optionsString, bool* outParseSucceeded) {
+ SkTArray<SkString> optionParts;
+ SkStrSplit(optionsString.c_str(), ",", kStrict_SkStrSplitMode, &optionParts);
+ for (int i = 0; i < optionParts.count(); ++i) {
+ SkTArray<SkString> keyValueParts;
+ SkStrSplit(optionParts[i].c_str(), "=", kStrict_SkStrSplitMode, &keyValueParts);
+ if (keyValueParts.count() != 2) {
+ *outParseSucceeded = false;
+ return;
+ }
+ const SkString& key = keyValueParts[0];
+ const SkString& value = keyValueParts[1];
+ if (fOptionsMap.find(key) == nullptr) {
+ fOptionsMap.set(key, value);
+ } else {
+ // Duplicate values are not allowed.
+ *outParseSucceeded = false;
+ return;
+ }
+ }
+ *outParseSucceeded = true;
+ }
+
+ bool get_option_gpu_color(const char* optionKey,
+ SkColorType* outColorType,
+ SkAlphaType* alphaType,
+ sk_sp<SkColorSpace>* outColorSpace,
+ bool optional = true) const {
+ SkString* optionValue = fOptionsMap.find(SkString(optionKey));
+ if (optionValue == nullptr) {
+ return optional;
+ }
+ return parse_option_gpu_color(*optionValue, outColorType, alphaType, outColorSpace);
+ }
+
+ bool get_option_gpu_api(const char* optionKey,
+ SkCommandLineConfigGpu::ContextType* outContextType,
+ bool optional = true) const {
+ SkString* optionValue = fOptionsMap.find(SkString(optionKey));
+ if (optionValue == nullptr) {
+ return optional;
+ }
+ return parse_option_gpu_api(*optionValue, outContextType);
+ }
+
+ bool get_option_gpu_surf_type(const char* optionKey,
+ SkCommandLineConfigGpu::SurfType* outSurfType,
+ bool optional = true) const {
+ SkString* optionValue = fOptionsMap.find(SkString(optionKey));
+ if (optionValue == nullptr) {
+ return optional;
+ }
+ return parse_option_gpu_surf_type(*optionValue, outSurfType);
+ }
+
+ bool get_option_int(const char* optionKey, int* outInt, bool optional = true) const {
+ SkString* optionValue = fOptionsMap.find(SkString(optionKey));
+ if (optionValue == nullptr) {
+ return optional;
+ }
+ return parse_option_int(*optionValue, outInt);
+ }
+
+ bool get_option_bool(const char* optionKey, bool* outBool, bool optional = true) const {
+ SkString* optionValue = fOptionsMap.find(SkString(optionKey));
+ if (optionValue == nullptr) {
+ return optional;
+ }
+ return parse_option_bool(*optionValue, outBool);
+ }
+
+private:
+ SkTHashMap<SkString, SkString> fOptionsMap;
+};
+
+SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag,
+ const SkTArray<SkString>& viaParts,
+ ContextType contextType,
+ bool useDIText,
+ int samples,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ bool useStencilBuffers,
+ bool testThreading,
+ int testPersistentCache,
+ bool testPrecompile,
+ SurfType surfType)
+ : SkCommandLineConfig(tag, SkString("gpu"), viaParts)
+ , fContextType(contextType)
+ , fContextOverrides(ContextOverrides::kNone)
+ , fUseDIText(useDIText)
+ , fSamples(samples)
+ , fColorType(colorType)
+ , fAlphaType(alphaType)
+ , fColorSpace(std::move(colorSpace))
+ , fTestThreading(testThreading)
+ , fTestPersistentCache(testPersistentCache)
+ , fTestPrecompile(testPrecompile)
+ , fSurfType(surfType) {
+ if (!useStencilBuffers) {
+ fContextOverrides |= ContextOverrides::kAvoidStencilBuffers;
+ }
+}
+
+SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
+ const SkTArray<SkString>& vias,
+ const SkString& options) {
+ // Defaults for GPU backend.
+ SkCommandLineConfigGpu::ContextType contextType = GrContextFactory::kGL_ContextType;
+ bool useDIText = false;
+ int samples = 1;
+ SkColorType colorType = kRGBA_8888_SkColorType;
+ SkAlphaType alphaType = kPremul_SkAlphaType;
+ sk_sp<SkColorSpace> colorSpace = nullptr;
+ bool useStencils = true;
+ bool testThreading = false;
+ int testPersistentCache = 0;
+ bool testPrecompile = false;
+ SkCommandLineConfigGpu::SurfType surfType = SkCommandLineConfigGpu::SurfType::kDefault;
+
+ bool parseSucceeded = false;
+ ExtendedOptions extendedOptions(options, &parseSucceeded);
+ if (!parseSucceeded) {
+ return nullptr;
+ }
+
+ bool validOptions =
+ extendedOptions.get_option_gpu_api("api", &contextType, false) &&
+ extendedOptions.get_option_bool("dit", &useDIText) &&
+ extendedOptions.get_option_int("samples", &samples) &&
+ extendedOptions.get_option_gpu_color("color", &colorType, &alphaType, &colorSpace) &&
+ extendedOptions.get_option_bool("stencils", &useStencils) &&
+ extendedOptions.get_option_bool("testThreading", &testThreading) &&
+ extendedOptions.get_option_int("testPersistentCache", &testPersistentCache) &&
+ extendedOptions.get_option_bool("testPrecompile", &testPrecompile) &&
+ extendedOptions.get_option_gpu_surf_type("surf", &surfType);
+
+ // testing threading and the persistent cache are mutually exclusive.
+ if (!validOptions || (testThreading && (testPersistentCache != 0))) {
+ return nullptr;
+ }
+
+ return new SkCommandLineConfigGpu(tag,
+ vias,
+ contextType,
+ useDIText,
+ samples,
+ colorType,
+ alphaType,
+ colorSpace,
+ useStencils,
+ testThreading,
+ testPersistentCache,
+ testPrecompile,
+ surfType);
+}
+
+SkCommandLineConfigSvg::SkCommandLineConfigSvg(const SkString& tag,
+ const SkTArray<SkString>& viaParts,
+ int pageIndex)
+ : SkCommandLineConfig(tag, SkString("svg"), viaParts), fPageIndex(pageIndex) {}
+
+SkCommandLineConfigSvg* parse_command_line_config_svg(const SkString& tag,
+ const SkTArray<SkString>& vias,
+ const SkString& options) {
+ // Defaults for SVG backend.
+ int pageIndex = 0;
+
+ bool parseSucceeded = false;
+ ExtendedOptions extendedOptions(options, &parseSucceeded);
+ if (!parseSucceeded) {
+ return nullptr;
+ }
+
+ bool validOptions = extendedOptions.get_option_int("page", &pageIndex);
+
+ if (!validOptions) {
+ return nullptr;
+ }
+
+ return new SkCommandLineConfigSvg(tag, vias, pageIndex);
+}
+
+void ParseConfigs(const CommandLineFlags::StringArray& configs,
+ SkCommandLineConfigArray* outResult) {
+ outResult->reset();
+ for (int i = 0; i < configs.count(); ++i) {
+ SkString extendedBackend;
+ SkString extendedOptions;
+ SkString simpleBackend;
+ SkTArray<SkString> vias;
+
+ SkString tag(configs[i]);
+ SkTArray<SkString> parts;
+ SkStrSplit(tag.c_str(), "[", kStrict_SkStrSplitMode, &parts);
+ if (parts.count() == 2) {
+ SkTArray<SkString> parts2;
+ SkStrSplit(parts[1].c_str(), "]", kStrict_SkStrSplitMode, &parts2);
+ if (parts2.count() == 2 && parts2[1].isEmpty()) {
+ SkStrSplit(parts[0].c_str(), "-", kStrict_SkStrSplitMode, &vias);
+ if (vias.count()) {
+ extendedBackend = vias[vias.count() - 1];
+ vias.pop_back();
+ } else {
+ extendedBackend = parts[0];
+ }
+ extendedOptions = parts2[0];
+ simpleBackend.printf("%s[%s]", extendedBackend.c_str(), extendedOptions.c_str());
+ }
+ }
+
+ if (extendedBackend.isEmpty()) {
+ simpleBackend = tag;
+ SkStrSplit(tag.c_str(), "-", kStrict_SkStrSplitMode, &vias);
+ if (vias.count()) {
+ simpleBackend = vias[vias.count() - 1];
+ vias.pop_back();
+ }
+ for (auto& predefinedConfig : gPredefinedConfigs) {
+ if (simpleBackend.equals(predefinedConfig.predefinedConfig)) {
+ extendedBackend = predefinedConfig.backend;
+ extendedOptions = predefinedConfig.options;
+ break;
+ }
+ }
+ }
+ SkCommandLineConfig* parsedConfig = nullptr;
+ if (extendedBackend.equals("gpu")) {
+ parsedConfig = parse_command_line_config_gpu(tag, vias, extendedOptions);
+ }
+ if (extendedBackend.equals("svg")) {
+ parsedConfig = parse_command_line_config_svg(tag, vias, extendedOptions);
+ }
+ if (!parsedConfig) {
+ parsedConfig = new SkCommandLineConfig(tag, simpleBackend, vias);
+ }
+ outResult->emplace_back(parsedConfig);
+ }
+}
diff --git a/src/third_party/skia/tools/flags/CommonFlagsConfig.h b/src/third_party/skia/tools/flags/CommonFlagsConfig.h
new file mode 100644
index 0000000..6eb5cba
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlagsConfig.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SK_COMMON_FLAGS_CONFIG_H
+#define SK_COMMON_FLAGS_CONFIG_H
+
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/gpu/GrContextFactory.h"
+
+DECLARE_string(config);
+
+class SkCommandLineConfigGpu;
+class SkCommandLineConfigSvg;
+
+// SkCommandLineConfig represents a Skia rendering configuration string.
+// The string has following form:
+// tag:
+// [via-]*backend
+// where 'backend' consists of chars excluding hyphen
+// and each 'via' consists of chars excluding hyphen.
+class SkCommandLineConfig {
+public:
+ SkCommandLineConfig(const SkString& tag,
+ const SkString& backend,
+ const SkTArray<SkString>& viaParts);
+ virtual ~SkCommandLineConfig();
+ virtual const SkCommandLineConfigGpu* asConfigGpu() const { return nullptr; }
+ virtual const SkCommandLineConfigSvg* asConfigSvg() const { return nullptr; }
+ const SkString& getTag() const { return fTag; }
+ const SkString& getBackend() const { return fBackend; }
+ const SkTArray<SkString>& getViaParts() const { return fViaParts; }
+
+private:
+ SkString fTag;
+ SkString fBackend;
+ SkTArray<SkString> fViaParts;
+};
+
+// SkCommandLineConfigGpu is a SkCommandLineConfig that extracts information out of the backend
+// part of the tag. It is constructed tags that have:
+// * backends of form "gpu[option=value,option2=value,...]"
+// * backends that represent a shorthand of above (such as "glmsaa16" representing
+// "gpu(api=gl,samples=16)")
+class SkCommandLineConfigGpu : public SkCommandLineConfig {
+public:
+ enum class SurfType { kDefault, kBackendTexture, kBackendRenderTarget };
+ typedef sk_gpu_test::GrContextFactory::ContextType ContextType;
+ typedef sk_gpu_test::GrContextFactory::ContextOverrides ContextOverrides;
+
+ SkCommandLineConfigGpu(const SkString& tag,
+ const SkTArray<SkString>& viaParts,
+ ContextType contextType,
+ bool useDIText,
+ int samples,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ bool useStencilBuffers,
+ bool testThreading,
+ int testPersistentCache,
+ bool testPrecompile,
+ SurfType);
+
+ const SkCommandLineConfigGpu* asConfigGpu() const override { return this; }
+ ContextType getContextType() const { return fContextType; }
+ ContextOverrides getContextOverrides() const { return fContextOverrides; }
+ bool getUseDIText() const { return fUseDIText; }
+ int getSamples() const { return fSamples; }
+ SkColorType getColorType() const { return fColorType; }
+ SkAlphaType getAlphaType() const { return fAlphaType; }
+ SkColorSpace* getColorSpace() const { return fColorSpace.get(); }
+ bool getTestThreading() const { return fTestThreading; }
+ int getTestPersistentCache() const { return fTestPersistentCache; }
+ bool getTestPrecompile() const { return fTestPrecompile; }
+ SurfType getSurfType() const { return fSurfType; }
+
+private:
+ ContextType fContextType;
+ ContextOverrides fContextOverrides;
+ bool fUseDIText;
+ int fSamples;
+ SkColorType fColorType;
+ SkAlphaType fAlphaType;
+ sk_sp<SkColorSpace> fColorSpace;
+ bool fTestThreading;
+ int fTestPersistentCache;
+ bool fTestPrecompile;
+ SurfType fSurfType;
+};
+
+// SkCommandLineConfigSvg is a SkCommandLineConfig that extracts information out of the backend
+// part of the tag. It is constructed tags that have:
+// * backends of form "svg[option=value,option2=value,...]"
+class SkCommandLineConfigSvg : public SkCommandLineConfig {
+public:
+ SkCommandLineConfigSvg(const SkString& tag, const SkTArray<SkString>& viaParts, int pageIndex);
+ const SkCommandLineConfigSvg* asConfigSvg() const override { return this; }
+
+ int getPageIndex() const { return fPageIndex; }
+
+private:
+ int fPageIndex;
+};
+
+typedef SkTArray<std::unique_ptr<SkCommandLineConfig>, true> SkCommandLineConfigArray;
+void ParseConfigs(const CommandLineFlags::StringArray& configList,
+ SkCommandLineConfigArray* outResult);
+
+#endif
diff --git a/src/third_party/skia/tools/flags/CommonFlagsGpu.cpp b/src/third_party/skia/tools/flags/CommonFlagsGpu.cpp
new file mode 100644
index 0000000..d341ce5
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlagsGpu.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkExecutor.h"
+#include "include/gpu/GrContextOptions.h"
+#include "tools/flags/CommonFlags.h"
+
+DEFINE_int(gpuThreads,
+ 2,
+ "Create this many extra threads to assist with GPU work, "
+ "including software path rendering. Defaults to two.");
+
+static DEFINE_bool(cachePathMasks, true,
+ "Allows path mask textures to be cached in GPU configs.");
+
+static DEFINE_bool(noGS, false, "Disables support for geometry shaders.");
+
+static DEFINE_bool(cc, false, "Allow coverage counting shortcuts to render paths?");
+
+static DEFINE_string(pr, "",
+ "Set of enabled gpu path renderers. Defined as a list of: "
+ "[~]none [~]dashline [~]nvpr [~]ccpr [~]aahairline [~]aaconvex [~]aalinearizing "
+ "[~]small [~]tess] [~]all");
+
+static DEFINE_bool(disableDriverCorrectnessWorkarounds, false,
+ "Disables all GPU driver correctness workarounds");
+
+static DEFINE_bool(reduceOpsTaskSplitting, false, "Improve opsTask sorting");
+static DEFINE_bool(dontReduceOpsTaskSplitting, false, "Allow more opsTask splitting");
+
+static GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
+ if (!strcmp(name, "none")) {
+ return GpuPathRenderers::kNone;
+ } else if (!strcmp(name, "dashline")) {
+ return GpuPathRenderers::kDashLine;
+ } else if (!strcmp(name, "nvpr")) {
+ return GpuPathRenderers::kStencilAndCover;
+ } else if (!strcmp(name, "ccpr")) {
+ return GpuPathRenderers::kCoverageCounting;
+ } else if (!strcmp(name, "aahairline")) {
+ return GpuPathRenderers::kAAHairline;
+ } else if (!strcmp(name, "aaconvex")) {
+ return GpuPathRenderers::kAAConvex;
+ } else if (!strcmp(name, "aalinearizing")) {
+ return GpuPathRenderers::kAALinearizing;
+ } else if (!strcmp(name, "small")) {
+ return GpuPathRenderers::kSmall;
+ } else if (!strcmp(name, "tess")) {
+ return GpuPathRenderers::kTessellating;
+ } else if (!strcmp(name, "all")) {
+ return GpuPathRenderers::kAll;
+ }
+ SK_ABORT(SkStringPrintf("error: unknown named path renderer \"%s\"\n", name).c_str());
+}
+
+static GpuPathRenderers collect_gpu_path_renderers_from_flags() {
+ if (FLAGS_pr.isEmpty()) {
+ return GpuPathRenderers::kAll;
+ }
+
+ GpuPathRenderers gpuPathRenderers = ('~' == FLAGS_pr[0][0])
+ ? GpuPathRenderers::kAll
+ : GpuPathRenderers::kNone;
+
+ for (int i = 0; i < FLAGS_pr.count(); ++i) {
+ const char* name = FLAGS_pr[i];
+ if (name[0] == '~') {
+ gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]);
+ } else {
+ gpuPathRenderers |= get_named_pathrenderers_flags(name);
+ }
+ }
+ return gpuPathRenderers;
+}
+
+void SetCtxOptionsFromCommonFlags(GrContextOptions* ctxOptions) {
+ static std::unique_ptr<SkExecutor> gGpuExecutor = (0 != FLAGS_gpuThreads)
+ ? SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)
+ : nullptr;
+
+ ctxOptions->fExecutor = gGpuExecutor.get();
+ ctxOptions->fDisableCoverageCountingPaths = !FLAGS_cc;
+ ctxOptions->fAllowPathMaskCaching = FLAGS_cachePathMasks;
+ ctxOptions->fSuppressGeometryShaders = FLAGS_noGS;
+ ctxOptions->fGpuPathRenderers = collect_gpu_path_renderers_from_flags();
+ ctxOptions->fDisableDriverCorrectnessWorkarounds = FLAGS_disableDriverCorrectnessWorkarounds;
+
+ if (FLAGS_reduceOpsTaskSplitting) {
+ SkASSERT(!FLAGS_dontReduceOpsTaskSplitting);
+ ctxOptions->fReduceOpsTaskSplitting = GrContextOptions::Enable::kYes;
+ } else if (FLAGS_dontReduceOpsTaskSplitting) {
+ ctxOptions->fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
+ }
+}
diff --git a/src/third_party/skia/tools/flags/CommonFlagsImages.cpp b/src/third_party/skia/tools/flags/CommonFlagsImages.cpp
new file mode 100644
index 0000000..60b5f12
--- /dev/null
+++ b/src/third_party/skia/tools/flags/CommonFlagsImages.cpp
@@ -0,0 +1,94 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "src/core/SkOSFile.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/flags/CommonFlags.h"
+
+bool CollectImages(CommandLineFlags::StringArray images, SkTArray<SkString>* output) {
+ SkASSERT(output);
+
+ static const char* const exts[] = {
+ "bmp",
+ "gif",
+ "jpg",
+ "jpeg",
+ "png",
+ "webp",
+ "ktx",
+ "astc",
+ "wbmp",
+ "ico",
+#if !defined(SK_BUILD_FOR_WIN)
+ "BMP",
+ "GIF",
+ "JPG",
+ "JPEG",
+ "PNG",
+ "WEBP",
+ "KTX",
+ "ASTC",
+ "WBMP",
+ "ICO",
+#endif
+#ifdef SK_HAS_HEIF_LIBRARY
+ "heic",
+#if !defined(SK_BUILD_FOR_WIN)
+ "HEIC",
+#endif
+#endif
+#ifdef SK_CODEC_DECODES_RAW
+ "arw",
+ "cr2",
+ "dng",
+ "nef",
+ "nrw",
+ "orf",
+ "raf",
+ "rw2",
+ "pef",
+ "srw",
+#if !defined(SK_BUILD_FOR_WIN)
+ "ARW",
+ "CR2",
+ "DNG",
+ "NEF",
+ "NRW",
+ "ORF",
+ "RAF",
+ "RW2",
+ "PEF",
+ "SRW",
+#endif
+#endif
+ };
+
+ for (int i = 0; i < images.count(); ++i) {
+ const char* flag = images[i];
+ if (!sk_exists(flag)) {
+ SkDebugf("%s does not exist!\n", flag);
+ return false;
+ }
+
+ if (sk_isdir(flag)) {
+ // If the value passed in is a directory, add all the images
+ bool foundAnImage = false;
+ for (const char* ext : exts) {
+ SkOSFile::Iter it(flag, ext);
+ SkString file;
+ while (it.next(&file)) {
+ foundAnImage = true;
+ output->push_back() = SkOSPath::Join(flag, file.c_str());
+ }
+ }
+ if (!foundAnImage) {
+ SkDebugf("No supported images found in %s!\n", flag);
+ return false;
+ }
+ } else {
+ // Also add the value if it is a single image
+ output->push_back() = flag;
+ }
+ }
+ return true;
+}
diff --git a/src/third_party/skia/tools/flags/SkCommandLineFlags.h b/src/third_party/skia/tools/flags/SkCommandLineFlags.h
deleted file mode 100644
index 78919c1..0000000
--- a/src/third_party/skia/tools/flags/SkCommandLineFlags.h
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * 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 SK_COMMAND_LINE_FLAGS_H
-#define SK_COMMAND_LINE_FLAGS_H
-
-#include "../private/SkTArray.h"
-#include "../private/SkTDArray.h"
-#include "SkString.h"
-
-/**
- * Including this file (and compiling SkCommandLineFlags.cpp) provides command line
- * parsing. In order to use it, use the following macros in global
- * namespace:
- *
- * DEFINE_bool(name, defaultValue, helpString);
- * DEFINE_string(name, defaultValue, helpString);
- * DEFINE_int32(name, defaultValue, helpString);
- * DEFINE_double(name, defaultValue, helpString);
- *
- * Then, in main, call SkCommandLineFlags::SetUsage() to describe usage and call
- * SkCommandLineFlags::Parse() to parse the flags. Henceforth, each flag can
- * be referenced using
- *
- * FLAGS_name
- *
- * For example, the line
- *
- * DEFINE_bool(boolean, false, "The variable boolean does such and such");
- *
- * will create the following variable:
- *
- * bool FLAGS_boolean;
- *
- * which will initially be set to false, and can be set to true by using the
- * flag "--boolean" on the commandline. "--noboolean" will set FLAGS_boolean
- * to false. FLAGS_boolean can also be set using "--boolean=true" or
- * "--boolean true" (where "true" can be replaced by "false", "TRUE", "FALSE",
- * "1" or "0").
- *
- * The helpString will be printed if the help flag (-h or -help) is used.
- *
- * Similarly, the line
- *
- * DEFINE_int32(integer, .., ..);
- *
- * will create
- *
- * int32_t FLAGS_integer;
- *
- * and
- *
- * DEFINE_double(real, .., ..);
- *
- * will create
- *
- * double FLAGS_real;
- *
- * These flags can be set by specifying, for example, "--integer 7" and
- * "--real 3.14" on the command line.
- *
- * Unlike the others, the line
- *
- * DEFINE_string(args, .., ..);
- *
- * creates an array:
- *
- * SkCommandLineFlags::StringArray FLAGS_args;
- *
- * If the default value is the empty string, FLAGS_args will default to a size
- * of zero. Otherwise it will default to a size of 1 with the default string
- * as its value. All strings that follow the flag on the command line (until
- * a string that begins with '-') will be entries in the array.
- *
- * DEFINE_extended_string(args, .., .., extendedHelpString);
- *
- * creates a similar string array flag as DEFINE_string. The flag will have extended help text
- * (extendedHelpString) that can the user can see with '--help <args>' flag.
- *
- * Any flag can be referenced from another file after using the following:
- *
- * DECLARE_x(name);
- *
- * (where 'x' is the type specified in the DEFINE).
- *
- * Inspired by gflags (https://code.google.com/p/gflags/). Is not quite as
- * robust as gflags, but suits our purposes. For example, allows creating
- * a flag -h or -help which will never be used, since SkCommandLineFlags handles it.
- * SkCommandLineFlags will also allow creating --flag and --noflag. Uses the same input
- * format as gflags and creates similarly named variables (i.e. FLAGS_name).
- * Strings are handled differently (resulting variable will be an array of
- * strings) so that a flag can be followed by multiple parameters.
- */
-
-class SkFlagInfo;
-
-class SkCommandLineFlags {
-
-public:
- /**
- * Call to set the help message to be displayed. Should be called before
- * Parse.
- */
- static void SetUsage(const char* usage);
-
- /**
- * Call this to display the help message. Should be called after SetUsage.
- */
- static void PrintUsage();
-
- /**
- * Call at the beginning of main to parse flags created by DEFINE_x, above.
- * Must only be called once.
- */
- static void Parse(int argc, char** argv);
-
- /**
- * Custom class for holding the arguments for a string flag.
- * Publicly only has accessors so the strings cannot be modified.
- */
- class StringArray {
- public:
- StringArray() { }
- explicit StringArray(const SkTArray<SkString>& strings)
- : fStrings(strings) {
- }
- const char* operator[](int i) const {
- SkASSERT(i >= 0 && i < fStrings.count());
- return fStrings[i].c_str();
- }
-
- int count() const {
- return fStrings.count();
- }
-
- bool isEmpty() const { return this->count() == 0; }
-
- /**
- * Returns true iff string is equal to one of the strings in this array.
- */
- bool contains(const char* string) const {
- for (int i = 0; i < fStrings.count(); i++) {
- if (fStrings[i].equals(string)) {
- return true;
- }
- }
- return false;
- }
-
- void set(int i, const char* str) {
- fStrings[i].set(str);
- }
-
- private:
- void reset() { fStrings.reset(); }
-
- void append(const char* string) {
- fStrings.push_back().set(string);
- }
-
- void append(const char* string, size_t length) {
- fStrings.push_back().set(string, length);
- }
-
- SkTArray<SkString> fStrings;
-
- friend class SkFlagInfo;
- };
-
- /* Takes a list of the form [~][^]match[$]
- ~ causes a matching test to always be skipped
- ^ requires the start of the test to match
- $ requires the end of the test to match
- ^ and $ requires an exact match
- If a test does not match any list entry, it is skipped unless some list entry starts with ~
- */
- static bool ShouldSkip(const SkTDArray<const char*>& strings, const char* name);
- static bool ShouldSkip(const StringArray& strings, const char* name);
-
-private:
- static SkFlagInfo* gHead;
- static SkString gUsage;
-
- // For access to gHead.
- friend class SkFlagInfo;
-};
-
-#define TO_STRING2(s) #s
-#define TO_STRING(s) TO_STRING2(s)
-
-#define DEFINE_bool(name, defaultValue, helpString) \
-bool FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateBoolFlag(TO_STRING(name), \
- nullptr, \
- &FLAGS_##name, \
- defaultValue, \
- helpString)
-
-// bool 2 allows specifying a short name. No check is done to ensure that shortName
-// is actually shorter than name.
-#define DEFINE_bool2(name, shortName, defaultValue, helpString) \
-bool FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateBoolFlag(TO_STRING(name), \
- TO_STRING(shortName),\
- &FLAGS_##name, \
- defaultValue, \
- helpString)
-
-#define DECLARE_bool(name) extern bool FLAGS_##name;
-
-#define DEFINE_string(name, defaultValue, helpString) \
-SkCommandLineFlags::StringArray FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
- nullptr, \
- &FLAGS_##name, \
- defaultValue, \
- helpString, nullptr)
-#define DEFINE_extended_string(name, defaultValue, helpString, extendedHelpString) \
-SkCommandLineFlags::StringArray FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
- nullptr, \
- &FLAGS_##name, \
- defaultValue, \
- helpString, \
- extendedHelpString)
-
-// string2 allows specifying a short name. There is an assert that shortName
-// is only 1 character.
-#define DEFINE_string2(name, shortName, defaultValue, helpString) \
-SkCommandLineFlags::StringArray FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
- TO_STRING(shortName), \
- &FLAGS_##name, \
- defaultValue, \
- helpString, nullptr)
-
-#define DECLARE_string(name) extern SkCommandLineFlags::StringArray FLAGS_##name;
-
-
-
-
-#define DEFINE_int32(name, defaultValue, helpString) \
-int32_t FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateIntFlag(TO_STRING(name), \
- &FLAGS_##name, \
- defaultValue, \
- helpString)
-
-#define DEFINE_int32_2(name, shortName, defaultValue, helpString) \
-int32_t FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateIntFlag(TO_STRING(name), \
- TO_STRING(shortName), \
- &FLAGS_##name, \
- defaultValue, \
- helpString)
-
-#define DECLARE_int32(name) extern int32_t FLAGS_##name;
-
-#define DEFINE_double(name, defaultValue, helpString) \
-double FLAGS_##name; \
-SK_UNUSED static bool unused_##name = SkFlagInfo::CreateDoubleFlag(TO_STRING(name), \
- &FLAGS_##name, \
- defaultValue, \
- helpString)
-
-#define DECLARE_double(name) extern double FLAGS_##name;
-
-class SkFlagInfo {
-
-public:
- enum FlagTypes {
- kBool_FlagType,
- kString_FlagType,
- kInt_FlagType,
- kDouble_FlagType,
- };
-
- /**
- * Each Create<Type>Flag function creates an SkFlagInfo of the specified type. The SkFlagInfo
- * object is appended to a list, which is deleted when SkCommandLineFlags::Parse is called.
- * Therefore, each call should be made before the call to ::Parse. They are not intended
- * to be called directly. Instead, use the macros described above.
- * @param name Long version (at least 2 characters) of the name of the flag. This name can
- * be referenced on the command line as "--name" to set the value of this flag.
- * @param shortName Short version (one character) of the name of the flag. This name can
- * be referenced on the command line as "-shortName" to set the value of this flag.
- * @param p<Type> Pointer to a global variable which holds the value set by SkCommandLineFlags.
- * @param defaultValue The default value of this flag. The variable pointed to by p<Type> will
- * be set to this value initially. This is also displayed as part of the help output.
- * @param helpString Explanation of what this flag changes in the program.
- */
- static bool CreateBoolFlag(const char* name, const char* shortName, bool* pBool,
- bool defaultValue, const char* helpString) {
- SkFlagInfo* info = new SkFlagInfo(name, shortName, kBool_FlagType, helpString, nullptr);
- info->fBoolValue = pBool;
- *info->fBoolValue = info->fDefaultBool = defaultValue;
- return true;
- }
-
- /**
- * See comments for CreateBoolFlag.
- * @param pStrings Unlike the others, this is a pointer to an array of values.
- * @param defaultValue Thise default will be parsed so that strings separated by spaces
- * will be added to pStrings.
- */
- static bool CreateStringFlag(const char* name, const char* shortName,
- SkCommandLineFlags::StringArray* pStrings,
- const char* defaultValue, const char* helpString,
- const char* extendedHelpString);
-
- /**
- * See comments for CreateBoolFlag.
- */
- static bool CreateIntFlag(const char* name, int32_t* pInt,
- int32_t defaultValue, const char* helpString) {
- SkFlagInfo* info = new SkFlagInfo(name, nullptr, kInt_FlagType, helpString, nullptr);
- info->fIntValue = pInt;
- *info->fIntValue = info->fDefaultInt = defaultValue;
- return true;
- }
-
- static bool CreateIntFlag(const char* name, const char* shortName, int32_t* pInt,
- int32_t defaultValue, const char* helpString) {
- SkFlagInfo* info = new SkFlagInfo(name, shortName, kInt_FlagType, helpString, nullptr);
- info->fIntValue = pInt;
- *info->fIntValue = info->fDefaultInt = defaultValue;
- return true;
- }
-
- /**
- * See comments for CreateBoolFlag.
- */
- static bool CreateDoubleFlag(const char* name, double* pDouble,
- double defaultValue, const char* helpString) {
- SkFlagInfo* info = new SkFlagInfo(name, nullptr, kDouble_FlagType, helpString, nullptr);
- info->fDoubleValue = pDouble;
- *info->fDoubleValue = info->fDefaultDouble = defaultValue;
- return true;
- }
-
- /**
- * Returns true if the string matches this flag.
- * For a boolean flag, also sets the value, since a boolean flag can be set in a number of ways
- * without looking at the following string:
- * --name
- * --noname
- * --name=true
- * --name=false
- * --name=1
- * --name=0
- * --name=TRUE
- * --name=FALSE
- */
- bool match(const char* string);
-
- FlagTypes getFlagType() const { return fFlagType; }
-
- void resetStrings() {
- if (kString_FlagType == fFlagType) {
- fStrings->reset();
- } else {
- SkDEBUGFAIL("Can only call resetStrings on kString_FlagType");
- }
- }
-
- void append(const char* string) {
- if (kString_FlagType == fFlagType) {
- fStrings->append(string);
- } else {
- SkDEBUGFAIL("Can only append to kString_FlagType");
- }
- }
-
- void setInt(int32_t value) {
- if (kInt_FlagType == fFlagType) {
- *fIntValue = value;
- } else {
- SkDEBUGFAIL("Can only call setInt on kInt_FlagType");
- }
- }
-
- void setDouble(double value) {
- if (kDouble_FlagType == fFlagType) {
- *fDoubleValue = value;
- } else {
- SkDEBUGFAIL("Can only call setDouble on kDouble_FlagType");
- }
- }
-
- void setBool(bool value) {
- if (kBool_FlagType == fFlagType) {
- *fBoolValue = value;
- } else {
- SkDEBUGFAIL("Can only call setBool on kBool_FlagType");
- }
- }
-
- SkFlagInfo* next() { return fNext; }
-
- const SkString& name() const { return fName; }
-
- const SkString& shortName() const { return fShortName; }
-
- const SkString& help() const { return fHelpString; }
- const SkString& extendedHelp() const { return fExtendedHelpString; }
-
- SkString defaultValue() const {
- SkString result;
- switch (fFlagType) {
- case SkFlagInfo::kBool_FlagType:
- result.printf("%s", fDefaultBool ? "true" : "false");
- break;
- case SkFlagInfo::kString_FlagType:
- return fDefaultString;
- case SkFlagInfo::kInt_FlagType:
- result.printf("%i", fDefaultInt);
- break;
- case SkFlagInfo::kDouble_FlagType:
- result.printf("%2.2f", fDefaultDouble);
- break;
- default:
- SkDEBUGFAIL("Invalid flag type");
- }
- return result;
- }
-
- SkString typeAsString() const {
- switch (fFlagType) {
- case SkFlagInfo::kBool_FlagType:
- return SkString("bool");
- case SkFlagInfo::kString_FlagType:
- return SkString("string");
- case SkFlagInfo::kInt_FlagType:
- return SkString("int");
- case SkFlagInfo::kDouble_FlagType:
- return SkString("double");
- default:
- SkDEBUGFAIL("Invalid flag type");
- return SkString();
- }
- }
-
-private:
- SkFlagInfo(const char* name, const char* shortName, FlagTypes type, const char* helpString,
- const char* extendedHelpString)
- : fName(name)
- , fShortName(shortName)
- , fFlagType(type)
- , fHelpString(helpString)
- , fExtendedHelpString(extendedHelpString)
- , fBoolValue(nullptr)
- , fDefaultBool(false)
- , fIntValue(nullptr)
- , fDefaultInt(0)
- , fDoubleValue(nullptr)
- , fDefaultDouble(0)
- , fStrings(nullptr) {
- fNext = SkCommandLineFlags::gHead;
- SkCommandLineFlags::gHead = this;
- SkASSERT(name && strlen(name) > 1);
- SkASSERT(nullptr == shortName || 1 == strlen(shortName));
- }
-
- /**
- * Set a StringArray to hold the values stored in defaultStrings.
- * @param array The StringArray to modify.
- * @param defaultStrings Space separated list of strings that should be inserted into array
- * individually.
- */
- static void SetDefaultStrings(SkCommandLineFlags::StringArray* array,
- const char* defaultStrings);
-
- // Name of the flag, without initial dashes
- SkString fName;
- SkString fShortName;
- FlagTypes fFlagType;
- SkString fHelpString;
- SkString fExtendedHelpString;
- bool* fBoolValue;
- bool fDefaultBool;
- int32_t* fIntValue;
- int32_t fDefaultInt;
- double* fDoubleValue;
- double fDefaultDouble;
- SkCommandLineFlags::StringArray* fStrings;
- // Both for the help string and in case fStrings is empty.
- SkString fDefaultString;
-
- // In order to keep a linked list.
- SkFlagInfo* fNext;
-};
-#endif // SK_COMMAND_LINE_FLAGS_H
diff --git a/src/third_party/skia/tools/flags/SkCommonFlags.cpp b/src/third_party/skia/tools/flags/SkCommonFlags.cpp
deleted file mode 100644
index 35fc0cf..0000000
--- a/src/third_party/skia/tools/flags/SkCommonFlags.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCommonFlags.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-
-DEFINE_bool(cpu, true, "master switch for running CPU-bound work.");
-
-DEFINE_bool(dryRun, false,
- "just print the tests that would be run, without actually running them.");
-
-DEFINE_bool(gpu, true, "master switch for running GPU-bound work.");
-
-DEFINE_string(images, "", "List of images and/or directories to decode. A directory with no images"
- " is treated as a fatal error.");
-
-DEFINE_string(colorImages, "", "List of images and/or directories to decode with color correction. "
- "A directory with no images is treated as a fatal error.");
-
-DEFINE_bool(simpleCodec, false, "Runs of a subset of the codec tests. "
- "For DM, this means no scaling or subsetting, always using the "
- "canvas color type. "
- "For nanobench, this means always N32, Premul or Opaque.");
-
-DEFINE_string2(match, m, nullptr,
- "[~][^]substring[$] [...] of GM name to run.\n"
- "Multiple matches may be separated by spaces.\n"
- "~ causes a matching GM to always be skipped\n"
- "^ requires the start of the GM to match\n"
- "$ requires the end of the GM to match\n"
- "^ and $ requires an exact match\n"
- "If a GM does not match any list entry,\n"
- "it is skipped unless some list entry starts with ~");
-
-DEFINE_bool2(quiet, q, false, "if true, don't print status updates.");
-
-DEFINE_bool(preAbandonGpuContext, false, "Test abandoning the GrContext before running the test.");
-
-DEFINE_bool(abandonGpuContext, false, "Test abandoning the GrContext after running each test.");
-
-DEFINE_bool(releaseAndAbandonGpuContext, false,
- "Test releasing all gpu resources and abandoning the GrContext after running each "
- "test");
-
-DEFINE_string(skps, "skps", "Directory to read skps from.");
-
-DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
-
-DEFINE_int32_2(threads, j, -1, "Run threadsafe tests on a threadpool with this many extra threads, "
- "defaulting to one extra thread per core.");
-
-DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
-
-DEFINE_bool2(veryVerbose, V, false, "tell individual tests to be verbose.");
-
-DEFINE_string2(writePath, w, "", "If set, write bitmaps here as .pngs.");
-
-DEFINE_string(key, "",
- "Space-separated key/value pairs to add to JSON identifying this builder.");
-DEFINE_string(properties, "",
- "Space-separated key/value pairs to add to JSON identifying this run.");
-DEFINE_bool2(pre_log, p, false, "Log before running each test. May be incomprehensible when threading");
-
-DEFINE_bool(analyticAA, true, "If false, disable analytic anti-aliasing");
-
-DEFINE_bool(forceAnalyticAA, false, "Force analytic anti-aliasing even if the path is complicated: "
- "whether it's concave or convex, we consider a path complicated"
- "if its number of points is comparable to its resolution.");
-
-DEFINE_bool(trace, false, "Show trace events using SkDebugf.");
-
-bool CollectImages(SkCommandLineFlags::StringArray images, SkTArray<SkString>* output) {
- SkASSERT(output);
-
- static const char* const exts[] = {
- "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico",
- "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO",
-#ifdef SK_CODEC_DECODES_RAW
- "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
- "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
-#endif
- };
-
- for (int i = 0; i < images.count(); ++i) {
- const char* flag = images[i];
- if (!sk_exists(flag)) {
- SkDebugf("%s does not exist!\n", flag);
- return false;
- }
-
- if (sk_isdir(flag)) {
- // If the value passed in is a directory, add all the images
- bool foundAnImage = false;
- for (const char* ext : exts) {
- SkOSFile::Iter it(flag, ext);
- SkString file;
- while (it.next(&file)) {
- foundAnImage = true;
- output->push_back() = SkOSPath::Join(flag, file.c_str());
- }
- }
- if (!foundAnImage) {
- SkDebugf("No supported images found in %s!\n", flag);
- return false;
- }
- } else {
- // Also add the value if it is a single image
- output->push_back() = flag;
- }
- }
- return true;
-}
diff --git a/src/third_party/skia/tools/flags/SkCommonFlags.h b/src/third_party/skia/tools/flags/SkCommonFlags.h
deleted file mode 100644
index 71ff8c3..0000000
--- a/src/third_party/skia/tools/flags/SkCommonFlags.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SK_COMMON_FLAGS_H
-#define SK_COMMON_FLAGS_H
-
-#include "../private/SkTArray.h"
-#include "SkCommandLineFlags.h"
-#include "SkString.h"
-
-DECLARE_bool(cpu);
-DECLARE_bool(dryRun);
-DECLARE_bool(gpu);
-DECLARE_string(images);
-DECLARE_string(colorImages);
-DECLARE_bool(simpleCodec);
-DECLARE_string(match);
-DECLARE_bool(quiet);
-DECLARE_bool(resetGpuContext);
-DECLARE_bool(preAbandonGpuContext);
-DECLARE_bool(abandonGpuContext);
-DECLARE_bool(releaseAndAbandonGpuContext);
-DECLARE_string(skps);
-DECLARE_string(svgs);
-DECLARE_int32(threads);
-DECLARE_string(resourcePath);
-DECLARE_bool(verbose);
-DECLARE_bool(veryVerbose);
-DECLARE_string(writePath);
-DECLARE_bool(pre_log);
-DECLARE_bool(analyticAA);
-DECLARE_bool(forceAnalyticAA);
-DECLARE_bool(trace)
-
-DECLARE_string(key);
-DECLARE_string(properties);
-
-/**
- * Helper to assist in collecting image paths from |dir| specified through a command line flag.
- *
- * Populates |output|, an array of strings with paths to images to test.
- *
- * Returns true if each argument to the images flag is meaningful:
- * - If the file/directory does not exist, return false.
- * - If |dir| does not have any supported images (based on file type), return false.
- * - If |dir| is a single file, assume the user is deliberately testing this image,
- * regardless of file type.
- */
-bool CollectImages(SkCommandLineFlags::StringArray dir, SkTArray<SkString>* output);
-
-#endif
diff --git a/src/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp b/src/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
deleted file mode 100644
index 03b3b96..0000000
--- a/src/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkColorSpace_Base.h"
-#include "SkCommonFlagsConfig.h"
-#include "SkImageInfo.h"
-
-#include <stdlib.h>
-
-#if SK_SUPPORT_GPU
-using sk_gpu_test::GrContextFactory;
-#endif
-
-#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
-# define DEFAULT_GPU_CONFIG "gles"
-#else
-# define DEFAULT_GPU_CONFIG "gl"
-#endif
-
-static const char defaultConfigs[] =
- "8888 " DEFAULT_GPU_CONFIG " nonrendering "
-#if defined(SK_BUILD_FOR_WIN)
- " angle_d3d11_es2"
-#endif
- ;
-
-#undef DEFAULT_GPU_CONFIG
-
-static const struct {
- const char* predefinedConfig;
- const char* backend;
- const char* options;
-} gPredefinedConfigs[] ={
-#if SK_SUPPORT_GPU
- { "gl", "gpu", "api=gl" },
- { "gles", "gpu", "api=gles" },
- { "glmsaa4", "gpu", "api=gl,samples=4" },
- { "glmsaa8" , "gpu", "api=gl,samples=8" },
- { "glesmsaa4", "gpu", "api=gles,samples=4" },
- { "glnvpr4", "gpu", "api=gl,nvpr=true,samples=4" },
- { "glnvpr8" , "gpu", "api=gl,nvpr=true,samples=8" },
- { "glnvprdit4", "gpu", "api=gl,nvpr=true,samples=4,dit=true" },
- { "glnvprdit8" , "gpu", "api=gl,nvpr=true,samples=8,dit=true" },
- { "glesnvpr4", "gpu", "api=gles,nvpr=true,samples=4" },
- { "glesnvprdit4", "gpu", "api=gles,nvpr=true,samples=4,dit=true" },
- { "glinst", "gpu", "api=gl,inst=true" },
- { "glinst4", "gpu", "api=gl,inst=true,samples=4" },
- { "glinstdit4", "gpu", "api=gl,inst=true,samples=4,dit=true" },
- { "glinst8" , "gpu", "api=gl,inst=true,samples=8" },
- { "glinstdit8" , "gpu", "api=gl,inst=true,samples=8,dit=true" },
- { "glesinst", "gpu", "api=gles,inst=true" },
- { "glesinst4", "gpu", "api=gles,inst=true,samples=4" },
- { "glesinstdit4", "gpu", "api=gles,inst=true,samples=4,dit=true" },
- { "gl4444", "gpu", "api=gl,color=4444" },
- { "gl565", "gpu", "api=gl,color=565" },
- { "glf16", "gpu", "api=gl,color=f16" },
- { "glsrgb", "gpu", "api=gl,color=srgb" },
- { "glsrgbnl", "gpu", "api=gl,color=srgbnl" },
- { "glesf16", "gpu", "api=gles,color=f16" },
- { "glessrgb", "gpu", "api=gles,color=srgb" },
- { "glessrgbnl", "gpu", "api=gles,color=srgbnl" },
- { "glsrgb", "gpu", "api=gl,color=srgb" },
- { "glwide", "gpu", "api=gl,color=f16_wide" },
- { "glnarrow", "gpu", "api=gl,color=f16_narrow" },
- { "glnostencils", "gpu", "api=gl,stencils=false" },
- { "glessrgb", "gpu", "api=gles,color=srgb" },
- { "gleswide", "gpu", "api=gles,color=f16_wide" },
- { "glesnarrow", "gpu", "api=gles,color=f16_narrow" },
- { "gldft", "gpu", "api=gl,dit=true" },
- { "glesdft", "gpu", "api=gles,dit=true" },
- { "debuggl", "gpu", "api=debuggl" },
- { "nullgl", "gpu", "api=nullgl" },
- { "angle_d3d11_es2", "gpu", "api=angle_d3d11_es2" },
- { "angle_d3d11_es3", "gpu", "api=angle_d3d11_es3" },
- { "angle_d3d9_es2", "gpu", "api=angle_d3d9_es2" },
- { "angle_d3d11_es2_msaa4", "gpu", "api=angle_d3d11_es2,samples=4" },
- { "angle_d3d11_es2_msaa8", "gpu", "api=angle_d3d11_es2,samples=8" },
- { "angle_d3d11_es3_msaa4", "gpu", "api=angle_d3d11_es3,samples=4" },
- { "angle_d3d11_es3_msaa8", "gpu", "api=angle_d3d11_es3,samples=8" },
- { "angle_gl_es2", "gpu", "api=angle_gl_es2" },
- { "angle_gl_es3", "gpu", "api=angle_gl_es3" },
- { "commandbuffer", "gpu", "api=commandbuffer" },
- { "mock", "gpu", "api=mock" }
-#if SK_MESA
- ,{ "mesa", "gpu", "api=mesa" }
-#endif
-#ifdef SK_VULKAN
- ,{ "vk", "gpu", "api=vulkan" }
- ,{ "vksrgb", "gpu", "api=vulkan,color=srgb" }
- ,{ "vkwide", "gpu", "api=vulkan,color=f16_wide" }
- ,{ "vkmsaa4", "gpu", "api=vulkan,samples=4" }
- ,{ "vkmsaa8", "gpu", "api=vulkan,samples=8" }
-#endif
-#ifdef SK_METAL
- ,{ "mtl", "gpu", "api=metal" }
- ,{ "mtlsrgb", "gpu", "api=metal,color=srgb" }
- ,{ "mtlwide", "gpu", "api=metal,color=f16_wide" }
- ,{ "mtlmsaa4", "gpu", "api=metal,samples=4" }
- ,{ "mtlmsaa8", "gpu", "api=metal,samples=8" }
-#endif
-#else
- { "", "", "" }
-#endif
-};
-
-static const char configHelp[] =
- "Options: 565 8888 srgb f16 nonrendering null pdf pdfa skp pipe svg xps";
-
-static const char* config_help_fn() {
- static SkString helpString;
- helpString.set(configHelp);
- for (const auto& config : gPredefinedConfigs) {
- helpString.appendf(" %s", config.predefinedConfig);
- }
- helpString.append(" or use extended form 'backend[option=value,...]'.\n");
- return helpString.c_str();
-}
-
-static const char configExtendedHelp[] =
- "Extended form: 'backend(option=value,...)'\n\n"
- "Possible backends and options:\n"
-#if SK_SUPPORT_GPU
- "\n"
- "gpu[api=string,color=string,dit=bool,nvpr=bool,inst=bool,samples=int]\n"
- "\tapi\ttype: string\trequired\n"
- "\t Select graphics API to use with gpu backend.\n"
- "\t Options:\n"
- "\t\tgl \t\t\tUse OpenGL.\n"
- "\t\tgles \t\t\tUse OpenGL ES.\n"
- "\t\tdebuggl \t\t\tUse debug OpenGL.\n"
- "\t\tnullgl \t\t\tUse null OpenGL.\n"
- "\t\tangle_d3d9_es2\t\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n"
- "\t\tangle_d3d11_es2\t\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n"
- "\t\tangle_d3d11_es3\t\t\tUse OpenGL ES3 on the ANGLE Direct3D11 backend.\n"
- "\t\tangle_gl_es2\t\t\tUse OpenGL ES2 on the ANGLE OpenGL backend.\n"
- "\t\tangle_gl_es3\t\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
- "\t\tcommandbuffer\t\tUse command buffer.\n"
- "\t\tmock\t\tUse mock context.\n"
-#if SK_MESA
- "\t\tmesa\t\t\tUse MESA.\n"
-#endif
-#ifdef SK_VULKAN
- "\t\tvulkan\t\t\tUse Vulkan.\n"
-#endif
-#ifdef SK_METAL
- "\t\tmetal\t\t\tUse Metal.\n"
-#endif
- "\tcolor\ttype: string\tdefault: 8888.\n"
- "\t Select framebuffer color format.\n"
- "\t Options:\n"
- "\t\t8888\t\t\tLinear 8888.\n"
- "\t\t4444\t\t\tLinear 4444.\n"
- "\t\t565\t\t\tLinear 565.\n"
- "\t\tf16{_gamut}\t\tLinear 16-bit floating point.\n"
- "\t\tsrgb{_gamut}\t\tsRGB 8888.\n"
- "\t gamut\ttype: string\tdefault: srgb.\n"
- "\t Select color gamut for f16 or sRGB format buffers.\n"
- "\t Options:\n"
- "\t\tsrgb\t\t\tsRGB gamut.\n"
- "\t\twide\t\t\tWide Gamut RGB.\n"
- "\tdit\ttype: bool\tdefault: false.\n"
- "\t Use device independent text.\n"
- "\tnvpr\ttype: bool\tdefault: false.\n"
- "\t Use NV_path_rendering OpenGL and OpenGL ES extension.\n"
- "\tsamples\ttype: int\tdefault: 0.\n"
- "\t Use multisampling with N samples.\n"
- "\tstencils\ttype: bool\tdefault: true.\n"
- "\t Allow the use of stencil buffers.\n"
- "\n"
- "Predefined configs:\n\n"
- // Help text for pre-defined configs is auto-generated from gPredefinedConfigs
-#endif
- ;
-
-static const char* config_extended_help_fn() {
- static SkString helpString;
- helpString.set(configExtendedHelp);
- for (const auto& config : gPredefinedConfigs) {
- helpString.appendf("\t%-10s\t= gpu(%s)\n", config.predefinedConfig, config.options);
- }
- return helpString.c_str();
-}
-
-DEFINE_extended_string(config, defaultConfigs, config_help_fn(), config_extended_help_fn());
-
-SkCommandLineConfig::SkCommandLineConfig(const SkString& tag, const SkString& backend,
- const SkTArray<SkString>& viaParts)
- : fTag(tag)
- , fBackend(backend)
- , fViaParts(viaParts) {
-}
-SkCommandLineConfig::~SkCommandLineConfig() {
-}
-
-#if SK_SUPPORT_GPU
-SkCommandLineConfigGpu::SkCommandLineConfigGpu(
- const SkString& tag, const SkTArray<SkString>& viaParts, ContextType contextType, bool useNVPR,
- bool useInstanced, bool useDIText, int samples, SkColorType colorType, SkAlphaType alphaType,
- sk_sp<SkColorSpace> colorSpace, bool useStencilBuffers)
- : SkCommandLineConfig(tag, SkString("gpu"), viaParts)
- , fContextType(contextType)
- , fContextOverrides(ContextOverrides::kNone)
- , fUseDIText(useDIText)
- , fSamples(samples)
- , fColorType(colorType)
- , fAlphaType(alphaType)
- , fColorSpace(std::move(colorSpace)) {
- if (useNVPR) {
- fContextOverrides |= ContextOverrides::kRequireNVPRSupport;
- } else if (!useInstanced) {
- // We don't disable NVPR for instanced configs. Otherwise the caps wouldn't use mixed
- // samples and we couldn't test the mixed samples backend for simple shapes.
- fContextOverrides |= ContextOverrides::kDisableNVPR;
- }
- if (useInstanced) {
- fContextOverrides |= ContextOverrides::kUseInstanced;
- }
- // Subtle logic: If the config has a color space attached, we're going to be rendering to sRGB,
- // so we need that capability. In addition, to get the widest test coverage, we DO NOT require
- // that we can disable sRGB decode. (That's for rendering sRGB sources to legacy surfaces).
- //
- // If the config doesn't have a color space attached, we're going to be rendering in legacy
- // mode. In that case, we don't require sRGB capability and we defer to the client to decide on
- // sRGB decode control.
- if (fColorSpace) {
- fContextOverrides |= ContextOverrides::kRequireSRGBSupport;
- fContextOverrides |= ContextOverrides::kAllowSRGBWithoutDecodeControl;
- }
- if (!useStencilBuffers) {
- fContextOverrides |= ContextOverrides::kAvoidStencilBuffers;
- }
-}
-static bool parse_option_int(const SkString& value, int* outInt) {
- if (value.isEmpty()) {
- return false;
- }
- char* endptr = nullptr;
- long intValue = strtol(value.c_str(), &endptr, 10);
- if (*endptr != '\0') {
- return false;
- }
- *outInt = static_cast<int>(intValue);
- return true;
-}
-static bool parse_option_bool(const SkString& value, bool* outBool) {
- if (value.equals("true")) {
- *outBool = true;
- return true;
- }
- if (value.equals("false")) {
- *outBool = false;
- return true;
- }
- return false;
-}
-static bool parse_option_gpu_api(const SkString& value,
- SkCommandLineConfigGpu::ContextType* outContextType) {
- if (value.equals("gl")) {
- *outContextType = GrContextFactory::kGL_ContextType;
- return true;
- }
- if (value.equals("gles")) {
- *outContextType = GrContextFactory::kGLES_ContextType;
- return true;
- }
- if (value.equals("debuggl")) {
- *outContextType = GrContextFactory::kDebugGL_ContextType;
- return true;
- }
- if (value.equals("nullgl")) {
- *outContextType = GrContextFactory::kNullGL_ContextType;
- return true;
- }
- if (value.equals("angle_d3d9_es2")) {
- *outContextType = GrContextFactory::kANGLE_D3D9_ES2_ContextType;
- return true;
- }
- if (value.equals("angle_d3d11_es2")) {
- *outContextType = GrContextFactory::kANGLE_D3D11_ES2_ContextType;
- return true;
- }
- if (value.equals("angle_d3d11_es3")) {
- *outContextType = GrContextFactory::kANGLE_D3D11_ES3_ContextType;
- return true;
- }
- if (value.equals("angle_gl_es2")) {
- *outContextType = GrContextFactory::kANGLE_GL_ES2_ContextType;
- return true;
- }
- if (value.equals("angle_gl_es3")) {
- *outContextType = GrContextFactory::kANGLE_GL_ES3_ContextType;
- return true;
- }
- if (value.equals("commandbuffer")) {
- *outContextType = GrContextFactory::kCommandBuffer_ContextType;
- return true;
- }
- if (value.equals("mock")) {
- *outContextType = GrContextFactory::kMock_ContextType;
- return true;
- }
-#if SK_MESA
- if (value.equals("mesa")) {
- *outContextType = GrContextFactory::kMESA_ContextType;
- return true;
- }
-#endif
-#ifdef SK_VULKAN
- if (value.equals("vulkan")) {
- *outContextType = GrContextFactory::kVulkan_ContextType;
- return true;
- }
-#endif
-#ifdef SK_METAL
- if (value.equals("metal")) {
- *outContextType = GrContextFactory::kMetal_ContextType;
- return true;
- }
-#endif
- return false;
-}
-static bool parse_option_gpu_color(const SkString& value,
- SkColorType* outColorType,
- SkAlphaType* alphaType,
- sk_sp<SkColorSpace>* outColorSpace) {
- // We always use premul unless the color type is 565.
- *alphaType = kPremul_SkAlphaType;
-
- if (value.equals("8888")) {
- *outColorType = kRGBA_8888_SkColorType;
- *outColorSpace = nullptr;
- return true;
- } else if (value.equals("4444")) {
- *outColorType = kARGB_4444_SkColorType;
- *outColorSpace = nullptr;
- return true;
- } else if (value.equals("565")) {
- *outColorType = kRGB_565_SkColorType;
- *alphaType = kOpaque_SkAlphaType;
- *outColorSpace = nullptr;
- return true;
- }
-
- SkTArray<SkString> commands;
- SkStrSplit(value.c_str(), "_", &commands);
- if (commands.count() < 1 || commands.count() > 2) {
- return false;
- }
-
- const bool linearGamma = commands[0].equals("f16");
- SkColorSpace::Gamut gamut = SkColorSpace::kSRGB_Gamut;
- SkColorSpace::RenderTargetGamma gamma = linearGamma ? SkColorSpace::kLinear_RenderTargetGamma
- : SkColorSpace::kSRGB_RenderTargetGamma;
- *outColorSpace = SkColorSpace::MakeRGB(gamma, gamut);
-
- if (commands.count() == 2) {
- if (commands[1].equals("srgb")) {
- // sRGB gamut (which is our default)
- } else if (commands[1].equals("wide")) {
- // WideGamut RGB
- const float gWideGamutRGB_toXYZD50[]{
- 0.7161046f, 0.1009296f, 0.1471858f, // -> X
- 0.2581874f, 0.7249378f, 0.0168748f, // -> Y
- 0.0000000f, 0.0517813f, 0.7734287f, // -> Z
- };
- SkMatrix44 wideGamutRGBMatrix(SkMatrix44::kUninitialized_Constructor);
- wideGamutRGBMatrix.set3x3RowMajorf(gWideGamutRGB_toXYZD50);
- *outColorSpace = SkColorSpace::MakeRGB(gamma, wideGamutRGBMatrix);
- } else if (commands[1].equals("narrow")) {
- // NarrowGamut RGB (an artifically smaller than sRGB gamut)
- SkColorSpacePrimaries primaries ={
- 0.54f, 0.33f, // Rx, Ry
- 0.33f, 0.50f, // Gx, Gy
- 0.25f, 0.20f, // Bx, By
- 0.3127f, 0.3290f, // Wx, Wy
- };
- SkMatrix44 narrowGamutRGBMatrix(SkMatrix44::kUninitialized_Constructor);
- primaries.toXYZD50(&narrowGamutRGBMatrix);
- *outColorSpace = SkColorSpace::MakeRGB(gamma, narrowGamutRGBMatrix);
- } else {
- // Unknown color gamut
- return false;
- }
- }
-
- // Now pick a color type
- if (commands[0].equals("f16")) {
- *outColorType = kRGBA_F16_SkColorType;
- return true;
- }
- if (commands[0].equals("srgb") || commands[0].equals("srgbnl")) {
- *outColorType = kRGBA_8888_SkColorType;
- return true;
- }
- return false;
-}
-
-SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
- const SkTArray<SkString>& vias,
- const SkString& options) {
- // Defaults for GPU backend.
- bool seenAPI = false;
- SkCommandLineConfigGpu::ContextType contextType = GrContextFactory::kGL_ContextType;
- bool seenUseNVPR = false;
- bool useNVPR = false;
- bool seenUseInstanced = false;
- bool useInstanced = false;
- bool seenUseDIText =false;
- bool useDIText = false;
- bool seenSamples = false;
- int samples = 0;
- bool seenColor = false;
- SkColorType colorType = kRGBA_8888_SkColorType;
- SkAlphaType alphaType = kPremul_SkAlphaType;
- sk_sp<SkColorSpace> colorSpace = nullptr;
- bool seenUseStencils = false;
- bool useStencils = true;
-
- SkTArray<SkString> optionParts;
- SkStrSplit(options.c_str(), ",", kStrict_SkStrSplitMode, &optionParts);
- for (int i = 0; i < optionParts.count(); ++i) {
- SkTArray<SkString> keyValueParts;
- SkStrSplit(optionParts[i].c_str(), "=", kStrict_SkStrSplitMode, &keyValueParts);
- if (keyValueParts.count() != 2) {
- return nullptr;
- }
- const SkString& key = keyValueParts[0];
- const SkString& value = keyValueParts[1];
- bool valueOk = false;
- if (key.equals("api") && !seenAPI) {
- valueOk = parse_option_gpu_api(value, &contextType);
- seenAPI = true;
- } else if (key.equals("nvpr") && !seenUseNVPR) {
- valueOk = parse_option_bool(value, &useNVPR);
- seenUseNVPR = true;
- } else if (key.equals("inst") && !seenUseInstanced) {
- valueOk = parse_option_bool(value, &useInstanced);
- seenUseInstanced = true;
- } else if (key.equals("dit") && !seenUseDIText) {
- valueOk = parse_option_bool(value, &useDIText);
- seenUseDIText = true;
- } else if (key.equals("samples") && !seenSamples) {
- valueOk = parse_option_int(value, &samples);
- seenSamples = true;
- } else if (key.equals("color") && !seenColor) {
- valueOk = parse_option_gpu_color(value, &colorType, &alphaType, &colorSpace);
- seenColor = true;
- } else if (key.equals("stencils") && !seenUseStencils) {
- valueOk = parse_option_bool(value, &useStencils);
- seenUseStencils = true;
- }
- if (!valueOk) {
- return nullptr;
- }
- }
- if (!seenAPI) {
- return nullptr;
- }
- return new SkCommandLineConfigGpu(tag, vias, contextType, useNVPR, useInstanced, useDIText,
- samples, colorType, alphaType, colorSpace, useStencils);
-}
-#endif
-
-void ParseConfigs(const SkCommandLineFlags::StringArray& configs,
- SkCommandLineConfigArray* outResult) {
- outResult->reset();
- for (int i = 0; i < configs.count(); ++i) {
- SkString extendedBackend;
- SkString extendedOptions;
- SkString simpleBackend;
- SkTArray<SkString> vias;
-
- SkString tag(configs[i]);
- SkTArray<SkString> parts;
- SkStrSplit(tag.c_str(), "[", kStrict_SkStrSplitMode, &parts);
- if (parts.count() == 2) {
- SkTArray<SkString> parts2;
- SkStrSplit(parts[1].c_str(), "]", kStrict_SkStrSplitMode, &parts2);
- if (parts2.count() == 2 && parts2[1].isEmpty()) {
- SkStrSplit(parts[0].c_str(), "-", kStrict_SkStrSplitMode, &vias);
- if (vias.count()) {
- extendedBackend = vias[vias.count() - 1];
- vias.pop_back();
- } else {
- extendedBackend = parts[0];
- }
- extendedOptions = parts2[0];
- simpleBackend.printf("%s[%s]", extendedBackend.c_str(), extendedOptions.c_str());
- }
- }
-
- if (extendedBackend.isEmpty()) {
- simpleBackend = tag;
- SkStrSplit(tag.c_str(), "-", kStrict_SkStrSplitMode, &vias);
- if (vias.count()) {
- simpleBackend = vias[vias.count() - 1];
- vias.pop_back();
- }
- for (auto& predefinedConfig : gPredefinedConfigs) {
- if (simpleBackend.equals(predefinedConfig.predefinedConfig)) {
- extendedBackend = predefinedConfig.backend;
- extendedOptions = predefinedConfig.options;
- break;
- }
- }
- }
- SkCommandLineConfig* parsedConfig = nullptr;
-#if SK_SUPPORT_GPU
- if (extendedBackend.equals("gpu")) {
- parsedConfig = parse_command_line_config_gpu(tag, vias, extendedOptions);
- }
-#endif
- if (!parsedConfig) {
- parsedConfig = new SkCommandLineConfig(tag, simpleBackend, vias);
- }
- outResult->emplace_back(parsedConfig);
- }
-}
diff --git a/src/third_party/skia/tools/flags/SkCommonFlagsConfig.h b/src/third_party/skia/tools/flags/SkCommonFlagsConfig.h
deleted file mode 100644
index 77f31c3..0000000
--- a/src/third_party/skia/tools/flags/SkCommonFlagsConfig.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SK_COMMON_FLAGS_CONFIG_H
-#define SK_COMMON_FLAGS_CONFIG_H
-
-#include "SkCommandLineFlags.h"
-
-#if SK_SUPPORT_GPU
-#include "GrContextFactory.h"
-#endif
-
-DECLARE_string(config);
-
-#if SK_SUPPORT_GPU
-class SkCommandLineConfigGpu;
-#endif
-
-// SkCommandLineConfig represents a Skia rendering configuration string.
-// The string has following form:
-// tag:
-// [via-]*backend
-// where 'backend' consists of chars excluding hyphen
-// and each 'via' consists of chars excluding hyphen.
-class SkCommandLineConfig {
- public:
- SkCommandLineConfig(const SkString& tag, const SkString& backend,
- const SkTArray<SkString>& viaParts);
- virtual ~SkCommandLineConfig();
-#if SK_SUPPORT_GPU
- virtual const SkCommandLineConfigGpu* asConfigGpu() const { return nullptr; }
-#endif
- const SkString& getTag() const { return fTag; }
- const SkString& getBackend() const { return fBackend; }
- const SkTArray<SkString>& getViaParts() const { return fViaParts; }
- private:
- SkString fTag;
- SkString fBackend;
- SkTArray<SkString> fViaParts;
-};
-
-#if SK_SUPPORT_GPU
-// SkCommandLineConfigGpu is a SkCommandLineConfig that extracts information out of the backend
-// part of the tag. It is constructed tags that have:
-// * backends of form "gpu[option=value,option2=value,...]"
-// * backends that represent a shorthand of above (such as "glmsaa16" representing
-// "gpu(api=gl,samples=16)")
-class SkCommandLineConfigGpu : public SkCommandLineConfig {
- public:
- typedef sk_gpu_test::GrContextFactory::ContextType ContextType;
- typedef sk_gpu_test::GrContextFactory::ContextOverrides ContextOverrides;
- SkCommandLineConfigGpu(const SkString& tag, const SkTArray<SkString>& viaParts,
- ContextType contextType, bool useNVPR, bool useInstanced, bool useDIText,
- int samples, SkColorType colorType, SkAlphaType alphaType,
- sk_sp<SkColorSpace> colorSpace, bool useStencilBuffers);
- const SkCommandLineConfigGpu* asConfigGpu() const override { return this; }
- ContextType getContextType() const { return fContextType; }
- ContextOverrides getContextOverrides() const { return fContextOverrides; }
- bool getUseNVPR() const {
- SkASSERT(!(fContextOverrides & ContextOverrides::kRequireNVPRSupport) ||
- !(fContextOverrides & ContextOverrides::kDisableNVPR));
- return fContextOverrides & ContextOverrides::kRequireNVPRSupport;
- }
- bool getUseInstanced() const { return fContextOverrides & ContextOverrides::kUseInstanced; }
- bool getUseDIText() const { return fUseDIText; }
- int getSamples() const { return fSamples; }
- SkColorType getColorType() const { return fColorType; }
- SkAlphaType getAlphaType() const { return fAlphaType; }
- SkColorSpace* getColorSpace() const { return fColorSpace.get(); }
-
- private:
- ContextType fContextType;
- ContextOverrides fContextOverrides;
- bool fUseDIText;
- int fSamples;
- SkColorType fColorType;
- SkAlphaType fAlphaType;
- sk_sp<SkColorSpace> fColorSpace;
-};
-#endif
-
-typedef SkTArray<std::unique_ptr<SkCommandLineConfig>, true> SkCommandLineConfigArray;
-void ParseConfigs(const SkCommandLineFlags::StringArray& configList,
- SkCommandLineConfigArray* outResult);
-
-#endif
diff --git a/src/third_party/skia/tools/flags/SkCommonFlagsPathRenderer.h b/src/third_party/skia/tools/flags/SkCommonFlagsPathRenderer.h
deleted file mode 100644
index ac293a1..0000000
--- a/src/third_party/skia/tools/flags/SkCommonFlagsPathRenderer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SK_COMMON_FLAGS_PATH_RENDERER_H
-#define SK_COMMON_FLAGS_PATH_RENDERER_H
-
-#if SK_SUPPORT_GPU
-
-#include "GrContextOptions.h"
-#include "SkCommandLineFlags.h"
-#include "SkTypes.h"
-
-DECLARE_string(pr);
-
-#define DEFINE_pathrenderer_flag \
- DEFINE_string(pr, "all", \
- "Set of enabled gpu path renderers. Defined as a list of: " \
- "[[~]all [~]dashline [~]nvpr [~]msaa [~]aahairline [~]aaconvex " \
- "[~]aalinearizing [~]small [~]tess [~]grdefault]")
-
-inline GrContextOptions::GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
- using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
- if (!strcmp(name, "all")) {
- return GpuPathRenderers::kAll;
- } else if (!strcmp(name, "dashline")) {
- return GpuPathRenderers::kDashLine;
- } else if (!strcmp(name, "nvpr")) {
- return GpuPathRenderers::kStencilAndCover;
- } else if (!strcmp(name, "msaa")) {
- return GpuPathRenderers::kMSAA;
- } else if (!strcmp(name, "aahairline")) {
- return GpuPathRenderers::kAAHairline;
- } else if (!strcmp(name, "aaconvex")) {
- return GpuPathRenderers::kAAConvex;
- } else if (!strcmp(name, "aalinearizing")) {
- return GpuPathRenderers::kAALinearizing;
- } else if (!strcmp(name, "small")) {
- return GpuPathRenderers::kSmall;
- } else if (!strcmp(name, "ccpr")) {
- return GpuPathRenderers::kCoverageCounting;
- } else if (!strcmp(name, "tess")) {
- return GpuPathRenderers::kTessellating;
- } else if (!strcmp(name, "grdefault")) {
- return GpuPathRenderers::kDefault;
- }
- SK_ABORT(SkStringPrintf("error: unknown named path renderer \"%s\"\n", name).c_str());
- return GpuPathRenderers::kNone;
-}
-
-inline GrContextOptions::GpuPathRenderers CollectGpuPathRenderersFromFlags() {
- using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
- if (FLAGS_pr.isEmpty()) {
- return GpuPathRenderers::kAll;
- }
- GpuPathRenderers gpuPathRenderers = '~' == FLAGS_pr[0][0] ?
- GpuPathRenderers::kAll : GpuPathRenderers::kNone;
- for (int i = 0; i < FLAGS_pr.count(); ++i) {
- const char* name = FLAGS_pr[i];
- if (name[0] == '~') {
- gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]);
- } else {
- gpuPathRenderers |= get_named_pathrenderers_flags(name);
- }
- }
- return gpuPathRenderers;
-}
-
-#endif // SK_SUPPORT_GPU
-
-#endif
diff --git a/src/third_party/skia/tools/fm/fm.cpp b/src/third_party/skia/tools/fm/fm.cpp
new file mode 100644
index 0000000..d89bcac
--- /dev/null
+++ b/src/third_party/skia/tools/fm/fm.cpp
@@ -0,0 +1,596 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "experimental/svg/model/SkSVGDOM.h"
+#include "gm/gm.h"
+#include "include/codec/SkCodec.h"
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkPictureRecorder.h"
+#include "include/docs/SkPDFDocument.h"
+#include "include/gpu/GrContextOptions.h"
+#include "include/private/SkTHash.h"
+#include "src/core/SkColorSpacePriv.h"
+#include "src/core/SkMD5.h"
+#include "src/core/SkOSFile.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/AutoreleasePool.h"
+#include "tools/CrashHandler.h"
+#include "tools/HashAndEncode.h"
+#include "tools/ToolUtils.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/flags/CommonFlags.h"
+#include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/MemoryCache.h"
+#include "tools/trace/EventTracingPriv.h"
+#include <chrono>
+#include <functional>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(SK_ENABLE_SKOTTIE)
+ #include "modules/skottie/include/Skottie.h"
+ #include "modules/skottie/utils/SkottieUtils.h"
+#endif
+
+using sk_gpu_test::GrContextFactory;
+
+static DEFINE_string2(sources, s, "", "Which GMs, .skps, or images to draw.");
+static DEFINE_string2(backend, b, "", "Backend used to create a canvas to draw into.");
+
+static DEFINE_string(ct , "8888", "The color type for any raster backend.");
+static DEFINE_string(at , "premul", "The alpha type for any raster backend.");
+static DEFINE_string(gamut , "srgb", "The color gamut for any raster backend.");
+static DEFINE_string(tf , "srgb", "The transfer function for any raster backend.");
+static DEFINE_bool (legacy, false, "Use a null SkColorSpace instead of --gamut and --tf?");
+
+static DEFINE_int (samples , 0, "Samples per pixel in GPU backends.");
+static DEFINE_bool (stencils, true, "If false, avoid stencil buffers in GPU backends.");
+static DEFINE_bool (dit , false, "Use device-independent text in GPU backends.");
+static DEFINE_string(surf , "default", "Backing store for GPU backend surfaces.");
+
+static DEFINE_bool( preAbandonGpuContext, false, "Abandon the GrContext before drawing.");
+static DEFINE_bool( abandonGpuContext, false, "Abandon the GrContext after drawing.");
+static DEFINE_bool(releaseAndAbandonGpuContext, false,
+ "Release all GPU resources and abandon the GrContext after drawing.");
+
+static DEFINE_bool(decodeToDst, false,
+ "Decode images to destination format rather than suggested natural format.");
+
+static DEFINE_double(rasterDPI, SK_ScalarDefaultRasterDPI,
+ "DPI for rasterized content in vector backends like --backend pdf.");
+static DEFINE_bool(PDFA, false, "Create PDF/A with --backend pdf?");
+
+static DEFINE_bool (cpuDetect, true, "Detect CPU features for runtime optimizations?");
+static DEFINE_string2(writePath, w, "", "Write .pngs to this directory if set.");
+
+static DEFINE_string(writeShaders, "", "Write GLSL shaders to this directory if set.");
+
+static DEFINE_string(key, "", "Metadata passed through to .png encoder and .json output.");
+static DEFINE_string(properties, "", "Metadata passed through to .png encoder and .json output.");
+
+template <typename T>
+struct FlagOption {
+ const char* label;
+ T value;
+};
+
+template <typename T, int N>
+static bool parse_flag(const CommandLineFlags::StringArray& flag,
+ const char* flag_name,
+ const FlagOption<T> (&array)[N],
+ T* value) {
+ for (auto entry : array) {
+ if (flag.contains(entry.label)) {
+ *value = entry.value;
+ return true;
+ }
+ }
+ fprintf(stderr, "Known values for --%s:\n", flag_name);
+ for (auto entry : array) {
+ fprintf(stderr, " --%s %s\n", flag_name, entry.label);
+ }
+ return false;
+}
+
+struct Result {
+ enum { Ok, Skip, Fail} status;
+ SkString failure;
+};
+static const Result ok = {Result::Ok, {}},
+ skip = {Result::Skip, {}};
+
+template <typename... Args>
+static Result fail(const char* why, Args... args) {
+ return { Result::Fail, SkStringPrintf(why, args...) };
+}
+
+
+struct Source {
+ SkString name;
+ SkISize size;
+ std::function<Result(SkCanvas*)> draw;
+ std::function<void(GrContextOptions*)> tweak = [](GrContextOptions*){};
+};
+
+static void init(Source* source, std::shared_ptr<skiagm::GM> gm) {
+ source->size = gm->getISize();
+ source->tweak = [gm](GrContextOptions* options) { gm->modifyGrContextOptions(options); };
+ source->draw = [gm](SkCanvas* canvas) {
+ SkString err;
+ switch (gm->draw(canvas, &err)) {
+ case skiagm::DrawResult::kOk: break;
+ case skiagm::DrawResult::kSkip: return skip;
+ case skiagm::DrawResult::kFail: return fail(err.c_str());
+ }
+ return ok;
+ };
+}
+
+static void init(Source* source, sk_sp<SkPicture> pic) {
+ source->size = pic->cullRect().roundOut().size();
+ source->draw = [pic](SkCanvas* canvas) {
+ canvas->drawPicture(pic);
+ return ok;
+ };
+}
+
+static void init(Source* source, std::shared_ptr<SkCodec> codec) {
+ source->size = codec->dimensions();
+ source->draw = [codec](SkCanvas* canvas) {
+ SkImageInfo info = codec->getInfo();
+ if (FLAGS_decodeToDst) {
+ info = canvas->imageInfo().makeDimensions(info.dimensions());
+ }
+
+ SkBitmap bm;
+ bm.allocPixels(info);
+ switch (SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes())) {
+ case SkCodec::kSuccess:
+ case SkCodec::kErrorInInput:
+ case SkCodec::kIncompleteInput: canvas->drawBitmap(bm, 0,0);
+ break;
+ default: return fail("codec->getPixels() failed: %d\n", result);
+ }
+ return ok;
+ };
+}
+
+static void init(Source* source, sk_sp<SkSVGDOM> svg) {
+ source->size = svg->containerSize().isEmpty() ? SkISize{1000,1000}
+ : svg->containerSize().toCeil();
+ source->draw = [svg](SkCanvas* canvas) {
+ svg->render(canvas);
+ return ok;
+ };
+}
+
+#if defined(SK_ENABLE_SKOTTIE)
+static void init(Source* source, sk_sp<skottie::Animation> animation) {
+ source->size = {1000,1000};
+ source->draw = [animation](SkCanvas* canvas) {
+ canvas->clear(SK_ColorWHITE);
+
+ // Draw frames in a shuffled order to exercise nonlinear frame progression.
+ // The film strip will still be in time order, just drawn out of order.
+ const int order[] = { 4, 0, 3, 1, 2 };
+ const int tiles = SK_ARRAY_COUNT(order);
+ const float dim = 1000.0f / tiles;
+
+ const float dt = 1.0f / (tiles*tiles - 1);
+
+ for (int y : order)
+ for (int x : order) {
+ SkRect dst = {x*dim, y*dim, (x+1)*dim, (y+1)*dim};
+
+ SkAutoCanvasRestore _(canvas, true/*save now*/);
+ canvas->clipRect(dst, /*aa=*/true);
+ canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(animation->size()),
+ dst,
+ SkMatrix::kCenter_ScaleToFit));
+ float t = (y*tiles + x) * dt;
+ animation->seek(t);
+ animation->render(canvas);
+ }
+ return ok;
+ };
+}
+#endif
+
+static sk_sp<SkImage> draw_with_cpu(std::function<bool(SkCanvas*)> draw,
+ SkImageInfo info) {
+ if (sk_sp<SkSurface> surface = SkSurface::MakeRaster(info)) {
+ if (draw(surface->getCanvas())) {
+ return surface->makeImageSnapshot();
+ }
+ }
+ return nullptr;
+}
+
+static sk_sp<SkData> draw_as_skp(std::function<bool(SkCanvas*)> draw,
+ SkImageInfo info) {
+ SkPictureRecorder recorder;
+ if (draw(recorder.beginRecording(info.width(), info.height()))) {
+ return recorder.finishRecordingAsPicture()->serialize();
+ }
+ return nullptr;
+}
+
+static sk_sp<SkData> draw_as_pdf(std::function<bool(SkCanvas*)> draw,
+ SkImageInfo info,
+ SkString name) {
+ SkPDF::Metadata metadata;
+ metadata.fTitle = name;
+ metadata.fCreator = "Skia/FM";
+ metadata.fRasterDPI = FLAGS_rasterDPI;
+ metadata.fPDFA = FLAGS_PDFA;
+
+ SkDynamicMemoryWStream stream;
+ if (sk_sp<SkDocument> doc = SkPDF::MakeDocument(&stream, metadata)) {
+ if (draw(doc->beginPage(info.width(), info.height()))) {
+ doc->endPage();
+ doc->close();
+ return stream.detachAsData();
+ }
+ }
+ return nullptr;
+}
+
+static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
+ SkImageInfo info,
+ GrContextFactory::ContextType api,
+ GrContextFactory* factory) {
+ enum class SurfaceType { kDefault, kBackendTexture, kBackendRenderTarget };
+ const FlagOption<SurfaceType> kSurfaceTypes[] = {
+ { "default", SurfaceType::kDefault },
+ { "betex" , SurfaceType::kBackendTexture },
+ { "bert" , SurfaceType::kBackendRenderTarget },
+ };
+ SurfaceType surfaceType;
+ if (!parse_flag(FLAGS_surf, "surf", kSurfaceTypes, &surfaceType)) {
+ return nullptr;
+ }
+
+ auto overrides = GrContextFactory::ContextOverrides::kNone;
+ if (!FLAGS_stencils) { overrides |= GrContextFactory::ContextOverrides::kAvoidStencilBuffers; }
+
+ GrContext* context = factory->getContextInfo(api, overrides)
+ .grContext();
+
+ uint32_t flags = FLAGS_dit ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag
+ : 0;
+ SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+
+ sk_sp<SkSurface> surface;
+ GrBackendTexture backendTexture;
+ GrBackendRenderTarget backendRT;
+
+ switch (surfaceType) {
+ case SurfaceType::kDefault:
+ surface = SkSurface::MakeRenderTarget(context,
+ SkBudgeted::kNo,
+ info,
+ FLAGS_samples,
+ &props);
+ break;
+
+ case SurfaceType::kBackendTexture:
+ backendTexture = context->createBackendTexture(info.width(),
+ info.height(),
+ info.colorType(),
+ GrMipMapped::kNo,
+ GrRenderable::kYes,
+ GrProtected::kNo);
+ surface = SkSurface::MakeFromBackendTexture(context,
+ backendTexture,
+ kTopLeft_GrSurfaceOrigin,
+ FLAGS_samples,
+ info.colorType(),
+ info.refColorSpace(),
+ &props);
+ break;
+
+ case SurfaceType::kBackendRenderTarget:
+ backendRT = context->priv().getGpu()
+ ->createTestingOnlyBackendRenderTarget(info.width(),
+ info.height(),
+ SkColorTypeToGrColorType(info.colorType()));
+ surface = SkSurface::MakeFromBackendRenderTarget(context,
+ backendRT,
+ kBottomLeft_GrSurfaceOrigin,
+ info.colorType(),
+ info.refColorSpace(),
+ &props);
+ break;
+ }
+
+ if (!surface) {
+ fprintf(stderr, "Could not create GPU surface.\n");
+ return nullptr;
+ }
+
+ if (FLAGS_preAbandonGpuContext) {
+ factory->abandonContexts();
+ }
+
+ sk_sp<SkImage> image;
+ if (draw(surface->getCanvas())) {
+ image = surface->makeImageSnapshot();
+ }
+
+ if (FLAGS_abandonGpuContext) {
+ factory->abandonContexts();
+ } else if (FLAGS_releaseAndAbandonGpuContext) {
+ factory->releaseResourcesAndAbandonContexts();
+ }
+
+ if (!context->abandoned()) {
+ surface.reset();
+ if (backendTexture.isValid()) {
+ context->deleteBackendTexture(backendTexture);
+ }
+ if (backendRT.isValid()) {
+ context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
+ }
+ }
+
+ return image;
+}
+
+int main(int argc, char** argv) {
+ CommandLineFlags::Parse(argc, argv);
+ SetupCrashHandler();
+
+ if (FLAGS_cpuDetect) {
+ SkGraphics::Init();
+ }
+ initializeEventTracingForTools();
+ ToolUtils::SetDefaultFontMgr();
+ SetAnalyticAAFromCommonFlags();
+
+ GrContextOptions baseOptions;
+ SetCtxOptionsFromCommonFlags(&baseOptions);
+
+ sk_gpu_test::MemoryCache memoryCache;
+ if (!FLAGS_writeShaders.isEmpty()) {
+ baseOptions.fPersistentCache = &memoryCache;
+ baseOptions.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kBackendSource;
+ }
+
+ SkTHashMap<SkString, skiagm::GMFactory> gm_factories;
+ for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
+ std::unique_ptr<skiagm::GM> gm{factory()};
+ if (FLAGS_sources.isEmpty()) {
+ fprintf(stdout, "%s\n", gm->getName());
+ } else {
+ gm_factories.set(SkString{gm->getName()}, factory);
+ }
+ }
+ if (FLAGS_sources.isEmpty()) {
+ return 0;
+ }
+
+ SkTArray<Source> sources;
+ for (const SkString& name : FLAGS_sources) {
+ Source* source = &sources.push_back();
+
+ if (skiagm::GMFactory* factory = gm_factories.find(name)) {
+ std::shared_ptr<skiagm::GM> gm{(*factory)()};
+ source->name = name;
+ init(source, std::move(gm));
+ continue;
+ }
+
+ if (sk_sp<SkData> blob = SkData::MakeFromFileName(name.c_str())) {
+ source->name = SkOSPath::Basename(name.c_str());
+
+ if (name.endsWith(".skp")) {
+ if (sk_sp<SkPicture> pic = SkPicture::MakeFromData(blob.get())) {
+ init(source, pic);
+ continue;
+ }
+ } else if (name.endsWith(".svg")) {
+ SkMemoryStream stream{blob};
+ if (sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(stream)) {
+ init(source, svg);
+ continue;
+ }
+ }
+#if defined(SK_ENABLE_SKOTTIE)
+ else if (name.endsWith(".json")) {
+ const SkString dir = SkOSPath::Dirname(name.c_str());
+ if (sk_sp<skottie::Animation> animation = skottie::Animation::Builder()
+ .setResourceProvider(skottie_utils::FileResourceProvider::Make(dir))
+ .make((const char*)blob->data(), blob->size())) {
+ init(source, animation);
+ continue;
+ }
+ }
+#endif
+ else if (std::shared_ptr<SkCodec> codec = SkCodec::MakeFromData(blob)) {
+ init(source, codec);
+ continue;
+ }
+ }
+
+ fprintf(stderr, "Don't understand source '%s'... bailing out.\n", name.c_str());
+ return 1;
+ }
+
+ enum NonGpuBackends {
+ kCPU_Backend = -1,
+ kSKP_Backend = -2,
+ kPDF_Backend = -3,
+ };
+ const FlagOption<int> kBackends[] = {
+ { "cpu" , kCPU_Backend },
+ { "skp" , kSKP_Backend },
+ { "pdf" , kPDF_Backend },
+ { "gl" , GrContextFactory::kGL_ContextType },
+ { "gles" , GrContextFactory::kGLES_ContextType },
+ { "angle_d3d9_es2" , GrContextFactory::kANGLE_D3D9_ES2_ContextType },
+ { "angle_d3d11_es2", GrContextFactory::kANGLE_D3D11_ES2_ContextType },
+ { "angle_d3d11_es3", GrContextFactory::kANGLE_D3D11_ES3_ContextType },
+ { "angle_gl_es2" , GrContextFactory::kANGLE_GL_ES2_ContextType },
+ { "angle_gl_es3" , GrContextFactory::kANGLE_GL_ES3_ContextType },
+ { "commandbuffer" , GrContextFactory::kCommandBuffer_ContextType },
+ { "vk" , GrContextFactory::kVulkan_ContextType },
+ { "mtl" , GrContextFactory::kMetal_ContextType },
+ { "mock" , GrContextFactory::kMock_ContextType },
+ };
+ const FlagOption<SkColorType> kColorTypes[] = {
+ { "a8", kAlpha_8_SkColorType },
+ { "g8", kGray_8_SkColorType },
+ { "565", kRGB_565_SkColorType },
+ { "4444", kARGB_4444_SkColorType },
+ { "8888", kN32_SkColorType },
+ { "888x", kRGB_888x_SkColorType },
+ { "1010102", kRGBA_1010102_SkColorType },
+ { "101010x", kRGB_101010x_SkColorType },
+ { "f16norm", kRGBA_F16Norm_SkColorType },
+ { "f16", kRGBA_F16_SkColorType },
+ { "f32", kRGBA_F32_SkColorType },
+ { "rgba", kRGBA_8888_SkColorType },
+ { "bgra", kBGRA_8888_SkColorType },
+ };
+ const FlagOption<SkAlphaType> kAlphaTypes[] = {
+ { "premul", kPremul_SkAlphaType },
+ { "unpremul", kUnpremul_SkAlphaType },
+ };
+ const FlagOption<skcms_Matrix3x3> kGamuts[] = {
+ { "srgb", SkNamedGamut::kSRGB },
+ { "p3", SkNamedGamut::kDCIP3 },
+ { "rec2020", SkNamedGamut::kRec2020 },
+ { "adobe", SkNamedGamut::kAdobeRGB },
+ { "narrow", gNarrow_toXYZD50},
+ };
+ const FlagOption<skcms_TransferFunction> kTransferFunctions[] = {
+ { "srgb" , SkNamedTransferFn::kSRGB },
+ { "rec2020", SkNamedTransferFn::kRec2020 },
+ { "2.2" , SkNamedTransferFn::k2Dot2 },
+ { "linear" , SkNamedTransferFn::kLinear },
+ };
+
+
+ int backend;
+ SkColorType ct;
+ SkAlphaType at;
+ skcms_Matrix3x3 gamut;
+ skcms_TransferFunction tf;
+
+ if (!parse_flag(FLAGS_backend, "backend", kBackends , &backend) ||
+ !parse_flag(FLAGS_ct , "ct" , kColorTypes , &ct) ||
+ !parse_flag(FLAGS_at , "at" , kAlphaTypes , &at) ||
+ !parse_flag(FLAGS_gamut , "gamut" , kGamuts , &gamut) ||
+ !parse_flag(FLAGS_tf , "tf" , kTransferFunctions, &tf)) {
+ return 1;
+ }
+
+ sk_sp<SkColorSpace> cs = FLAGS_legacy ? nullptr
+ : SkColorSpace::MakeRGB(tf,gamut);
+ const SkImageInfo unsized_info = SkImageInfo::Make(0,0, ct,at,cs);
+
+ AutoreleasePool pool;
+ for (auto source : sources) {
+ const auto start = std::chrono::steady_clock::now();
+ fprintf(stdout, "%50s", source.name.c_str());
+ fflush(stdout);
+
+ const SkImageInfo info = unsized_info.makeDimensions(source.size);
+
+ auto draw = [&source](SkCanvas* canvas) {
+ Result result = source.draw(canvas);
+ switch (result.status) {
+ case Result::Ok: break;
+ case Result::Skip: return false;
+ case Result::Fail:
+ SK_ABORT(result.failure.c_str());
+ }
+ return true;
+ };
+
+ GrContextOptions options = baseOptions;
+ source.tweak(&options);
+ GrContextFactory factory(options); // N.B. factory must outlive image
+
+ sk_sp<SkImage> image;
+ sk_sp<SkData> blob;
+ const char* ext = ".png";
+ switch (backend) {
+ case kCPU_Backend:
+ image = draw_with_cpu(draw, info);
+ break;
+ case kSKP_Backend:
+ blob = draw_as_skp(draw, info);
+ ext = ".skp";
+ break;
+ case kPDF_Backend:
+ blob = draw_as_pdf(draw, info, source.name);
+ ext = ".pdf";
+ break;
+ default:
+ image = draw_with_gpu(draw, info, (GrContextFactory::ContextType)backend, &factory);
+ break;
+ }
+
+ if (!image && !blob) {
+ fprintf(stdout, "\tskipped\n");
+ continue;
+ }
+
+ SkBitmap bitmap;
+ if (image && !image->asLegacyBitmap(&bitmap)) {
+ SK_ABORT("SkImage::asLegacyBitmap() failed.");
+ }
+
+ HashAndEncode hashAndEncode{bitmap};
+ SkString md5;
+ {
+ SkMD5 hash;
+ if (image) {
+ hashAndEncode.write(&hash);
+ } else {
+ hash.write(blob->data(), blob->size());
+ }
+
+ SkMD5::Digest digest = hash.finish();
+ for (int i = 0; i < 16; i++) {
+ md5.appendf("%02x", digest.data[i]);
+ }
+ }
+
+ if (!FLAGS_writePath.isEmpty()) {
+ sk_mkdir(FLAGS_writePath[0]);
+ SkString path = SkStringPrintf("%s/%s%s", FLAGS_writePath[0], source.name.c_str(), ext);
+
+ if (image) {
+ if (!hashAndEncode.writePngTo(path.c_str(), md5.c_str(),
+ FLAGS_key, FLAGS_properties)) {
+ SK_ABORT("Could not write .png.");
+ }
+ } else {
+ SkFILEWStream file(path.c_str());
+ file.write(blob->data(), blob->size());
+ }
+ }
+
+ const auto elapsed = std::chrono::steady_clock::now() - start;
+ fprintf(stdout, "\t%s\t%7dms\n",
+ md5.c_str(),
+ (int)std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
+ pool.drain();
+ }
+
+ if (!FLAGS_writeShaders.isEmpty()) {
+ sk_mkdir(FLAGS_writeShaders[0]);
+ GrBackendApi api =
+ GrContextFactory::ContextTypeBackend((GrContextFactory::ContextType)backend);
+ memoryCache.writeShadersToDisk(FLAGS_writeShaders[0], api);
+
+ }
+
+ return 0;
+}
diff --git a/src/third_party/skia/tools/fm/fm_bot/fm_bot.go b/src/third_party/skia/tools/fm/fm_bot/fm_bot.go
new file mode 100644
index 0000000..ef0efc2
--- /dev/null
+++ b/src/third_party/skia/tools/fm/fm_bot/fm_bot.go
@@ -0,0 +1,281 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "log"
+ "math/rand"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+// Too many GPU processes and we'll start to overwhelm your GPU,
+// even hanging your machine in the worst case. Here's a reasonable default.
+func defaultGpuLimit() int {
+ limit := 8
+ if n := runtime.NumCPU(); n < limit {
+ return n
+ }
+ return limit
+}
+
+var script = flag.String("script", "", "A file with jobs to run, one per line. - for stdin.")
+var random = flag.Bool("random", true, "Assign sources into job batches randomly?")
+var quiet = flag.Bool("quiet", false, "Print only failures?")
+var exact = flag.Bool("exact", false, "Match GM names only exactly.")
+var cpuLimit = flag.Int("cpuLimit", runtime.NumCPU(),
+ "Maximum number of concurrent processes for CPU-bound work.")
+var gpuLimit = flag.Int("gpuLimit", defaultGpuLimit(),
+ "Maximum number of concurrent processes for GPU-bound work.")
+
+func init() {
+ flag.StringVar(script, "s", *script, "Alias for --script.")
+ flag.BoolVar(random, "r", *random, "Alias for --random.")
+ flag.BoolVar(quiet, "q", *quiet, "Alias for --quiet.")
+ flag.BoolVar(exact, "e", *exact, "Alias for --exact.")
+ flag.IntVar(cpuLimit, "c", *cpuLimit, "Alias for --cpuLimit.")
+ flag.IntVar(gpuLimit, "g", *gpuLimit, "Alias for --gpuLimit.")
+}
+
+func listAllGMs(fm string) (gms []string, err error) {
+ // Query fm binary for list of all available GMs by running with no arguments.
+ cmd := exec.Command(fm)
+ stdout, err := cmd.Output()
+ if err != nil {
+ return
+ }
+ // GM names are listed line-by-line.
+ scanner := bufio.NewScanner(bytes.NewReader(stdout))
+ for scanner.Scan() {
+ gms = append(gms, scanner.Text())
+ }
+ err = scanner.Err()
+ return
+}
+
+type work struct {
+ Sources []string
+ Flags []string
+}
+
+func parseWork(args []string, gms []string) (*work, error) {
+ w := &work{}
+ for _, arg := range args {
+ // I wish we could parse flags here too, but it's too late.
+ if strings.HasPrefix(arg, "-") {
+ msg := "Is '%s' an fm flag? If so please pass it using flag=value syntax."
+ if flag.Lookup(arg[1:]) != nil {
+ msg = "Please pass fm_bot flags like '%s' on the command line before the FM binary."
+ }
+ return nil, fmt.Errorf(msg, arg)
+ }
+
+ // Everything after a # is a comment.
+ if strings.HasPrefix(arg, "#") {
+ break
+ }
+
+ // Treat "gm" or "gms" as a shortcut for all known GMs.
+ if arg == "gm" || arg == "gms" {
+ w.Sources = append(w.Sources, gms...)
+ continue
+ }
+
+ // Is this an option to pass through to fm?
+ if parts := strings.Split(arg, "="); len(parts) == 2 {
+ f := "-"
+ if len(parts[0]) > 1 {
+ f += "-"
+ }
+ f += parts[0]
+
+ w.Flags = append(w.Flags, f, parts[1])
+ continue
+ }
+
+ // Is this argument naming a GM?
+ matchedAnyGM := false
+ for _, gm := range gms {
+ if (*exact && gm == arg) || (!*exact && strings.Contains(gm, arg)) {
+ w.Sources = append(w.Sources, gm)
+ matchedAnyGM = true
+ }
+ }
+ if matchedAnyGM {
+ continue
+ }
+
+ // Anything left ought to be on the file system: a file, a directory, or a glob.
+ // Not all shells expand globs, so we'll do it here just in case.
+ matches, err := filepath.Glob(arg)
+ if err != nil {
+ return nil, err
+ }
+ if len(matches) == 0 {
+ return nil, fmt.Errorf("Don't understand '%s'.", arg)
+ }
+
+ for _, match := range matches {
+ err := filepath.Walk(match, func(path string, info os.FileInfo, err error) error {
+ if !info.IsDir() {
+ w.Sources = append(w.Sources, path)
+ }
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return w, nil
+}
+
+func main() {
+ flag.Parse()
+
+ if flag.NArg() < 1 {
+ log.Fatal("Please pass an fm binary as the first argument.")
+ }
+ fm := flag.Args()[0]
+
+ gms, err := listAllGMs(fm)
+ if err != nil {
+ log.Fatalln("Could not query", fm, "for GMs:", err)
+ }
+
+ // One job can comes right on the command line,
+ // and any number can come one per line from -script.
+ jobs := [][]string{flag.Args()[1:]}
+ if *script != "" {
+ file := os.Stdin
+ if *script != "-" {
+ file, err = os.Open(*script)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+ }
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ jobs = append(jobs, strings.Fields(scanner.Text()))
+ }
+ if err = scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ wg := &sync.WaitGroup{}
+ var failures int32 = 0
+
+ worker := func(queue chan work) {
+ for w := range queue {
+ start := time.Now()
+
+ args := w.Flags[:]
+ args = append(args, "-s")
+ args = append(args, w.Sources...)
+
+ cmd := exec.Command(fm, args...)
+ output, err := cmd.CombinedOutput()
+
+ status := "#done"
+ if err != nil {
+ status = fmt.Sprintf("#failed (%v)", err)
+
+ if len(w.Sources) == 1 {
+ // If a source ran alone and failed, that's just a failure.
+ atomic.AddInt32(&failures, 1)
+ } else {
+ // If a batch of sources ran and failed, split them up and try again.
+ for _, source := range w.Sources {
+ wg.Add(1)
+ queue <- work{[]string{source}, w.Flags}
+ }
+ }
+ }
+
+ if !*quiet || (err != nil && len(w.Sources) == 1) {
+ log.Printf("\n%v %v in %v:\n%s",
+ strings.Join(cmd.Args, " "), status, time.Since(start), output)
+ }
+
+ wg.Done()
+ }
+ }
+
+ cpu := make(chan work, 1<<20)
+ for i := 0; i < *cpuLimit; i++ {
+ go worker(cpu)
+ }
+
+ gpu := make(chan work, 1<<20)
+ for i := 0; i < *gpuLimit; i++ {
+ go worker(gpu)
+ }
+
+ for _, job := range jobs {
+ // Skip blank lines, empty command lines.
+ if len(job) == 0 {
+ continue
+ }
+
+ w, err := parseWork(job, gms)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Determine if this is CPU-bound or GPU-bound work, conservatively assuming GPU.
+ queue, limit := gpu, *gpuLimit
+ backend := ""
+ for i, flag := range w.Flags {
+ if flag == "-b" || flag == "--backend" {
+ backend = w.Flags[i+1]
+ }
+ }
+ whitelisted := map[string]bool{
+ "cpu": true,
+ "skp": true,
+ "pdf": true,
+ }
+ if whitelisted[backend] {
+ queue, limit = cpu, *cpuLimit
+ }
+
+ if *random {
+ rand.Shuffle(len(w.Sources), func(i, j int) {
+ w.Sources[i], w.Sources[j] = w.Sources[j], w.Sources[i]
+ })
+ }
+
+ // Round up so there's at least one source per batch.
+ sourcesPerBatch := (len(w.Sources) + limit - 1) / limit
+
+ for i := 0; i < len(w.Sources); i += sourcesPerBatch {
+ end := i + sourcesPerBatch
+ if end > len(w.Sources) {
+ end = len(w.Sources)
+ }
+ batch := w.Sources[i:end]
+
+ wg.Add(1)
+ queue <- work{batch, w.Flags}
+ }
+ }
+
+ wg.Wait()
+
+ if failures > 0 {
+ log.Fatalln(failures, "failures after retries")
+ }
+}
diff --git a/src/third_party/skia/tools/fonts/RandomScalerContext.cpp b/src/third_party/skia/tools/fonts/RandomScalerContext.cpp
new file mode 100644
index 0000000..85430f5
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/RandomScalerContext.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkPath.h"
+#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkGlyph.h"
+#include "src/core/SkMakeUnique.h"
+#include "src/core/SkRectPriv.h"
+#include "tools/fonts/RandomScalerContext.h"
+
+class SkDescriptor;
+
+class RandomScalerContext : public SkScalerContext {
+public:
+ RandomScalerContext(sk_sp<SkRandomTypeface>,
+ const SkScalerContextEffects&,
+ const SkDescriptor*,
+ bool fFakeIt);
+
+protected:
+ unsigned generateGlyphCount() override;
+ bool generateAdvance(SkGlyph*) override;
+ void generateMetrics(SkGlyph*) override;
+ void generateImage(const SkGlyph&) override;
+ bool generatePath(SkGlyphID, SkPath*) override;
+ void generateFontMetrics(SkFontMetrics*) override;
+
+private:
+ SkRandomTypeface* getRandomTypeface() const {
+ return static_cast<SkRandomTypeface*>(this->getTypeface());
+ }
+ std::unique_ptr<SkScalerContext> fProxy;
+ bool fFakeIt;
+};
+
+RandomScalerContext::RandomScalerContext(sk_sp<SkRandomTypeface> face,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc,
+ bool fakeIt)
+ : SkScalerContext(std::move(face), effects, desc)
+ , fProxy(getRandomTypeface()->proxy()->createScalerContext(SkScalerContextEffects(), desc))
+ , fFakeIt(fakeIt) {
+ fProxy->forceGenerateImageFromPath();
+}
+
+unsigned RandomScalerContext::generateGlyphCount() { return fProxy->getGlyphCount(); }
+
+bool RandomScalerContext::generateAdvance(SkGlyph* glyph) { return fProxy->generateAdvance(glyph); }
+
+void RandomScalerContext::generateMetrics(SkGlyph* glyph) {
+ // Here we will change the mask format of the glyph
+ // NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
+ switch (glyph->getGlyphID() % 4) {
+ case 0: glyph->fMaskFormat = SkMask::kLCD16_Format; break;
+ case 1: glyph->fMaskFormat = SkMask::kA8_Format; break;
+ case 2: glyph->fMaskFormat = SkMask::kARGB32_Format; break;
+ case 3: glyph->fMaskFormat = SkMask::kBW_Format; break;
+ }
+
+ fProxy->getMetrics(glyph);
+
+ if (fFakeIt || (glyph->getGlyphID() % 4) != 2) {
+ return;
+ }
+
+ SkPath path;
+ if (!fProxy->getPath(glyph->getPackedID(), &path)) {
+ return;
+ }
+ glyph->fMaskFormat = SkMask::kARGB32_Format;
+
+ SkRect storage;
+ const SkPaint& paint = this->getRandomTypeface()->paint();
+ const SkRect& newBounds =
+ paint.doComputeFastBounds(path.getBounds(), &storage, SkPaint::kFill_Style);
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
+}
+
+void RandomScalerContext::generateImage(const SkGlyph& glyph) {
+ // TODO: can force down but not up
+ /*
+ SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
+ switch (glyph.getGlyphID() % 4) {
+ case 0: format = SkMask::kLCD16_Format; break;
+ case 1: format = SkMask::kA8_Format; break;
+ case 2: format = SkMask::kARGB32_Format; break;
+ case 3: format = SkMask::kBW_Format; break;
+ }
+ const_cast<SkGlyph&>(glyph).fMaskFormat = format;
+ */
+
+ if (fFakeIt) {
+ sk_bzero(glyph.fImage, glyph.imageSize());
+ return;
+ }
+
+ if (SkMask::kARGB32_Format != glyph.fMaskFormat) {
+ fProxy->getImage(glyph);
+ return;
+ }
+
+ // If the format is ARGB, just draw the glyph from path.
+ SkPath path;
+ if (!fProxy->getPath(glyph.getPackedID(), &path)) {
+ fProxy->getImage(glyph);
+ return;
+ }
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage,
+ glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
+ canvas.drawPath(path, this->getRandomTypeface()->paint());
+}
+
+bool RandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
+ return fProxy->generatePath(glyph, path);
+}
+
+void RandomScalerContext::generateFontMetrics(SkFontMetrics* metrics) {
+ fProxy->getFontMetrics(metrics);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
+ : SkTypeface(proxy->fontStyle(), false)
+ , fProxy(std::move(proxy))
+ , fPaint(paint)
+ , fFakeIt(fakeIt) {}
+
+SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const {
+ return new RandomScalerContext(
+ sk_ref_sp(const_cast<SkRandomTypeface*>(this)), effects, desc, fFakeIt);
+}
+
+void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ fProxy->filterRec(rec);
+ rec->setHinting(SkFontHinting::kNone);
+ rec->fMaskFormat = SkMask::kARGB32_Format;
+}
+
+void SkRandomTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
+ fProxy->getGlyphToUnicodeMap(glyphToUnicode);
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
+ return fProxy->getAdvancedMetrics();
+}
+
+std::unique_ptr<SkStreamAsset> SkRandomTypeface::onOpenStream(int* ttcIndex) const {
+ return fProxy->openStream(ttcIndex);
+}
+
+sk_sp<SkTypeface> SkRandomTypeface::onMakeClone(const SkFontArguments& args) const {
+ sk_sp<SkTypeface> proxy = fProxy->makeClone(args);
+ if (!proxy) {
+ return nullptr;
+ }
+ return sk_make_sp<SkRandomTypeface>(proxy, fPaint, fFakeIt);
+}
+
+void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ // TODO: anything that uses this typeface isn't correctly serializable, since this typeface
+ // cannot be deserialized.
+ fProxy->getFontDescriptor(desc, isLocal);
+}
+
+void SkRandomTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
+ fProxy->unicharsToGlyphs(uni, count, glyphs);
+}
+
+int SkRandomTypeface::onCountGlyphs() const { return fProxy->countGlyphs(); }
+
+int SkRandomTypeface::onGetUPEM() const { return fProxy->getUnitsPerEm(); }
+
+void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
+ fProxy->getFamilyName(familyName);
+}
+
+SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
+ return fProxy->createFamilyNameIterator();
+}
+
+void SkRandomTypeface::getPostScriptGlyphNames(SkString* names) const {
+ return fProxy->getPostScriptGlyphNames(names);
+}
+
+int SkRandomTypeface::onGetVariationDesignPosition(
+ SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const {
+ return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
+}
+
+int SkRandomTypeface::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const {
+ return fProxy->onGetVariationDesignParameters(parameters, parameterCount);
+}
+
+int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
+ return fProxy->getTableTags(tags);
+}
+
+size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag,
+ size_t offset,
+ size_t length,
+ void* data) const {
+ return fProxy->getTableData(tag, offset, length, data);
+}
diff --git a/src/third_party/skia/tools/fonts/RandomScalerContext.h b/src/third_party/skia/tools/fonts/RandomScalerContext.h
new file mode 100644
index 0000000..2601fd4
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/RandomScalerContext.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef RandomScalerContext_DEFINED
+#define RandomScalerContext_DEFINED
+
+#include "include/core/SkTypeface.h"
+#include "src/core/SkScalerContext.h"
+
+/*
+ * This scaler context is for debug only purposes. It will 'randomly' but deterministically return
+ * LCD / A8 / BW / RBGA masks based off of the Glyph ID
+ */
+
+class SkRandomTypeface : public SkTypeface {
+public:
+ SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint&, bool fakeit);
+
+ SkTypeface* proxy() const { return fProxy.get(); }
+ const SkPaint& paint() const { return fPaint; }
+
+protected:
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const override;
+ void onFilterRec(SkScalerContextRec*) const override;
+ void getGlyphToUnicodeMap(SkUnichar*) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+ std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
+ sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override;
+ void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override;
+
+ void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
+ int onCountGlyphs() const override;
+ int onGetUPEM() const override;
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ void getPostScriptGlyphNames(SkString*) const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override;
+ int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const override;
+ int onGetTableTags(SkFontTableTag tags[]) const override;
+ size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
+
+private:
+ sk_sp<SkTypeface> fProxy;
+ SkPaint fPaint;
+ bool fFakeIt;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/fonts/TestEmptyTypeface.h b/src/third_party/skia/tools/fonts/TestEmptyTypeface.h
new file mode 100644
index 0000000..3d61762
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestEmptyTypeface.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef TestEmptyTypeface_DEFINED
+#define TestEmptyTypeface_DEFINED
+
+#include "include/core/SkStream.h"
+#include "include/core/SkTypeface.h"
+#include "src/core/SkAdvancedTypefaceMetrics.h"
+
+class TestEmptyTypeface : public SkTypeface {
+public:
+ static sk_sp<SkTypeface> Make() { return sk_sp<SkTypeface>(new TestEmptyTypeface); }
+
+protected:
+ TestEmptyTypeface() : SkTypeface(SkFontStyle(), true) {}
+
+ std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override { return nullptr; }
+ sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
+ return sk_ref_sp(this);
+ }
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const override {
+ return nullptr;
+ }
+ void onFilterRec(SkScalerContextRec*) const override {}
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
+ return nullptr;
+ }
+ void onGetFontDescriptor(SkFontDescriptor*, bool*) const override {}
+ void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override {
+ sk_bzero(glyphs, count * sizeof(glyphs[0]));
+ }
+ int onCountGlyphs() const override { return 0; }
+ void getPostScriptGlyphNames(SkString*) const override {}
+ void getGlyphToUnicodeMap(SkUnichar*) const override {}
+ int onGetUPEM() const override { return 0; }
+ class EmptyLocalizedStrings : public SkTypeface::LocalizedStrings {
+ public:
+ bool next(SkTypeface::LocalizedString*) override { return false; }
+ };
+ void onGetFamilyName(SkString* familyName) const override { familyName->reset(); }
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
+ return new EmptyLocalizedStrings;
+ }
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override {
+ return 0;
+ }
+ int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const override {
+ return 0;
+ }
+ int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
+ size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
+};
+
+#endif // TestEmptyTypeface_DEFINED
diff --git a/src/third_party/skia/tools/fonts/TestFontMgr.cpp b/src/third_party/skia/tools/fonts/TestFontMgr.cpp
new file mode 100644
index 0000000..3b70a0a
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestFontMgr.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/core/SkFontDescriptor.h"
+#include "tools/ToolUtils.h"
+#include "tools/fonts/TestFontMgr.h"
+#include "tools/fonts/TestTypeface.h"
+
+#ifdef SK_XML
+#include "tools/fonts/TestSVGTypeface.h"
+#endif
+
+#include <vector>
+
+namespace {
+
+#include "test_font_monospace.inc"
+#include "test_font_sans_serif.inc"
+#include "test_font_serif.inc"
+
+#include "test_font_index.inc"
+
+class FontStyleSet final : public SkFontStyleSet {
+public:
+ FontStyleSet(const char* familyName) : fFamilyName(familyName) {}
+ struct TypefaceEntry {
+ TypefaceEntry(sk_sp<SkTypeface> typeface, SkFontStyle style, const char* styleName)
+ : fTypeface(std::move(typeface)), fStyle(style), fStyleName(styleName) {}
+ sk_sp<SkTypeface> fTypeface;
+ SkFontStyle fStyle;
+ const char* fStyleName;
+ };
+
+ int count() override { return fTypefaces.size(); }
+
+ void getStyle(int index, SkFontStyle* style, SkString* name) override {
+ if (style) {
+ *style = fTypefaces[index].fStyle;
+ }
+ if (name) {
+ *name = fTypefaces[index].fStyleName;
+ }
+ }
+
+ SkTypeface* createTypeface(int index) override {
+ return SkRef(fTypefaces[index].fTypeface.get());
+ }
+
+ SkTypeface* matchStyle(const SkFontStyle& pattern) override {
+ return this->matchStyleCSS3(pattern);
+ }
+
+ SkString getFamilyName() { return fFamilyName; }
+
+ std::vector<TypefaceEntry> fTypefaces;
+ SkString fFamilyName;
+};
+
+class FontMgr final : public SkFontMgr {
+public:
+ FontMgr() {
+ for (const auto& sub : gSubFonts) {
+ sk_sp<TestTypeface> typeface =
+ sk_make_sp<TestTypeface>(sk_make_sp<SkTestFont>(sub.fFont), sub.fStyle);
+ bool defaultFamily = false;
+ if (&sub - gSubFonts == gDefaultFontIndex) {
+ defaultFamily = true;
+ fDefaultTypeface = typeface;
+ }
+ bool found = false;
+ for (const auto& family : fFamilies) {
+ if (family->getFamilyName().equals(sub.fFamilyName)) {
+ family->fTypefaces.emplace_back(
+ std::move(typeface), sub.fStyle, sub.fStyleName);
+ found = true;
+ if (defaultFamily) {
+ fDefaultFamily = family;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ fFamilies.emplace_back(sk_make_sp<FontStyleSet>(sub.fFamilyName));
+ fFamilies.back()->fTypefaces.emplace_back(
+ // NOLINTNEXTLINE(bugprone-use-after-move)
+ std::move(typeface),
+ sub.fStyle,
+ sub.fStyleName);
+ if (defaultFamily) {
+ fDefaultFamily = fFamilies.back();
+ }
+ }
+ }
+#ifdef SK_XML
+ fFamilies.emplace_back(sk_make_sp<FontStyleSet>("Emoji"));
+ fFamilies.back()->fTypefaces.emplace_back(
+ TestSVGTypeface::Default(), SkFontStyle::Normal(), "Normal");
+
+ fFamilies.emplace_back(sk_make_sp<FontStyleSet>("Planet"));
+ fFamilies.back()->fTypefaces.emplace_back(
+ TestSVGTypeface::Planets(), SkFontStyle::Normal(), "Normal");
+#endif
+ }
+
+ int onCountFamilies() const override { return fFamilies.size(); }
+
+ void onGetFamilyName(int index, SkString* familyName) const override {
+ *familyName = fFamilies[index]->getFamilyName();
+ }
+
+ SkFontStyleSet* onCreateStyleSet(int index) const override {
+ sk_sp<SkFontStyleSet> ref = fFamilies[index];
+ return ref.release();
+ }
+
+ SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
+ if (familyName) {
+ if (strstr(familyName, "ono")) {
+ return this->createStyleSet(0);
+ }
+ if (strstr(familyName, "ans")) {
+ return this->createStyleSet(1);
+ }
+ if (strstr(familyName, "erif")) {
+ return this->createStyleSet(2);
+ }
+#ifdef SK_XML
+ if (strstr(familyName, "oji")) {
+ return this->createStyleSet(6);
+ }
+ if (strstr(familyName, "Planet")) {
+ return this->createStyleSet(7);
+ }
+#endif
+ }
+ return nullptr;
+ }
+
+ SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle& style) const override {
+ sk_sp<SkFontStyleSet> styleSet(this->matchFamily(familyName));
+ return styleSet->matchStyle(style);
+ }
+
+ SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const override {
+ (void)bcp47;
+ (void)bcp47Count;
+ (void)character;
+ return this->matchFamilyStyle(familyName, style);
+ }
+
+ SkTypeface* onMatchFaceStyle(const SkTypeface* tf, const SkFontStyle& style) const override {
+ SkString familyName;
+ tf->getFamilyName(&familyName);
+ return this->matchFamilyStyle(familyName.c_str(), style);
+ }
+
+ sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override { return nullptr; }
+ sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
+ int ttcIndex) const override {
+ return nullptr;
+ }
+ sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
+ const SkFontArguments&) const override {
+ return nullptr;
+ }
+ sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override {
+ return nullptr;
+ }
+ sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
+ return nullptr;
+ }
+
+ sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[],
+ SkFontStyle style) const override {
+ if (familyName == nullptr) {
+ return sk_sp<SkTypeface>(fDefaultFamily->matchStyle(style));
+ }
+ sk_sp<SkTypeface> typeface = sk_sp<SkTypeface>(this->matchFamilyStyle(familyName, style));
+ if (!typeface) {
+ typeface = fDefaultTypeface;
+ }
+ return typeface;
+ }
+
+private:
+ std::vector<sk_sp<FontStyleSet>> fFamilies;
+ sk_sp<FontStyleSet> fDefaultFamily;
+ sk_sp<SkTypeface> fDefaultTypeface;
+};
+} // namespace
+
+namespace ToolUtils {
+sk_sp<SkFontMgr> MakePortableFontMgr() { return sk_make_sp<FontMgr>(); }
+} // namespace ToolUtils
diff --git a/src/third_party/skia/tools/fonts/TestFontMgr.h b/src/third_party/skia/tools/fonts/TestFontMgr.h
new file mode 100644
index 0000000..b3afd2f
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestFontMgr.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TestFontMgr_DEFINED
+#define TestFontMgr_DEFINED
+
+#include "include/core/SkFontMgr.h"
+
+// An SkFontMgr that always uses ToolUtils::create_portable_typeface().
+
+namespace ToolUtils {
+sk_sp<SkFontMgr> MakePortableFontMgr();
+} // namespace ToolUtils
+
+#endif // TestFontMgr_DEFINED
diff --git a/src/third_party/skia/tools/fonts/TestSVGTypeface.cpp b/src/third_party/skia/tools/fonts/TestSVGTypeface.cpp
new file mode 100644
index 0000000..13c4d31
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestSVGTypeface.cpp
@@ -0,0 +1,1442 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/fonts/TestSVGTypeface.h"
+
+#ifdef SK_XML
+
+#include "experimental/svg/model/SkSVGDOM.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkData.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPathEffect.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkRRect.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/pathops/SkPathOps.h"
+#include "include/private/SkTDArray.h"
+#include "include/private/SkTemplates.h"
+#include "include/utils/SkNoDrawCanvas.h"
+#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkFontDescriptor.h"
+#include "src/core/SkFontPriv.h"
+#include "src/core/SkGeometry.h"
+#include "src/core/SkGlyph.h"
+#include "src/core/SkMask.h"
+#include "src/core/SkPaintPriv.h"
+#include "src/core/SkPathPriv.h"
+#include "src/core/SkPointPriv.h"
+#include "src/core/SkScalerContext.h"
+#include "src/core/SkUtils.h"
+#include "src/sfnt/SkOTUtils.h"
+#include "tools/Resources.h"
+
+#include <utility>
+
+class SkDescriptor;
+
+TestSVGTypeface::TestSVGTypeface(const char* name,
+ int upem,
+ const SkFontMetrics& fontMetrics,
+ SkSpan<const SkSVGTestTypefaceGlyphData> data,
+ const SkFontStyle& style)
+ : SkTypeface(style, false)
+ , fName(name)
+ , fUpem(upem)
+ , fFontMetrics(fontMetrics)
+ , fGlyphs(new Glyph[data.size()])
+ , fGlyphCount(data.size()) {
+ for (size_t i = 0; i < data.size(); ++i) {
+ const SkSVGTestTypefaceGlyphData& datum = data[i];
+ fCMap.set(datum.fUnicode, i);
+ fGlyphs[i].fAdvance = datum.fAdvance;
+ fGlyphs[i].fOrigin = datum.fOrigin;
+ fGlyphs[i].fResourcePath = datum.fSvgResourcePath;
+ }
+}
+
+template <typename Fn>
+void TestSVGTypeface::Glyph::withSVG(Fn&& fn) const {
+ SkAutoMutexExclusive lock(fSvgMutex);
+
+ if (!fParsedSvg) {
+ fParsedSvg = true;
+
+ std::unique_ptr<SkStreamAsset> stream = GetResourceAsStream(fResourcePath);
+ if (!stream) {
+ return;
+ }
+
+ sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(*stream.get());
+ if (!svg) {
+ return;
+ }
+
+ if (svg->containerSize().isEmpty()) {
+ return;
+ }
+
+ fSvg = std::move(svg);
+ }
+
+ if (fSvg) {
+ fn(*fSvg);
+ }
+}
+
+SkSize TestSVGTypeface::Glyph::size() const {
+ SkSize size = SkSize::MakeEmpty();
+ this->withSVG([&](const SkSVGDOM& svg){
+ size = svg.containerSize();
+ });
+ return size;
+}
+
+void TestSVGTypeface::Glyph::render(SkCanvas* canvas) const {
+ this->withSVG([&](const SkSVGDOM& svg){
+ svg.render(canvas);
+ });
+}
+
+TestSVGTypeface::~TestSVGTypeface() {}
+
+TestSVGTypeface::Glyph::Glyph() : fOrigin{0, 0}, fAdvance(0) {}
+TestSVGTypeface::Glyph::~Glyph() {}
+
+void TestSVGTypeface::getAdvance(SkGlyph* glyph) const {
+ SkGlyphID glyphID = glyph->getGlyphID();
+ glyphID = glyphID < fGlyphCount ? glyphID : 0;
+
+ glyph->fAdvanceX = fGlyphs[glyphID].fAdvance;
+ glyph->fAdvanceY = 0;
+}
+
+void TestSVGTypeface::getFontMetrics(SkFontMetrics* metrics) const { *metrics = fFontMetrics; }
+
+void TestSVGTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ rec->setHinting(SkFontHinting::kNone);
+}
+
+void TestSVGTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
+ SkDEBUGCODE(unsigned glyphCount = this->countGlyphs());
+ fCMap.foreach ([=](const SkUnichar& c, const SkGlyphID& g) {
+ SkASSERT(g < glyphCount);
+ glyphToUnicode[g] = c;
+ });
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> TestSVGTypeface::onGetAdvancedMetrics() const {
+ std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
+ info->fFontName = fName;
+ return info;
+}
+
+void TestSVGTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ desc->setFamilyName(fName.c_str());
+ desc->setStyle(this->fontStyle());
+ *isLocal = false;
+}
+
+void TestSVGTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
+ for (int i = 0; i < count; i++) {
+ SkGlyphID* g = fCMap.find(uni[i]);
+ glyphs[i] = g ? *g : 0;
+ }
+}
+
+void TestSVGTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fName; }
+
+SkTypeface::LocalizedStrings* TestSVGTypeface::onCreateFamilyNameIterator() const {
+ SkString familyName(fName);
+ SkString language("und"); // undetermined
+ return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+}
+
+class SkTestSVGScalerContext : public SkScalerContext {
+public:
+ SkTestSVGScalerContext(sk_sp<TestSVGTypeface> face,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : SkScalerContext(std::move(face), effects, desc) {
+ fRec.getSingleMatrix(&fMatrix);
+ SkScalar upem = this->getTestSVGTypeface()->fUpem;
+ fMatrix.preScale(1.f / upem, 1.f / upem);
+ }
+
+protected:
+ TestSVGTypeface* getTestSVGTypeface() const {
+ return static_cast<TestSVGTypeface*>(this->getTypeface());
+ }
+
+ unsigned generateGlyphCount() override { return this->getTestSVGTypeface()->countGlyphs(); }
+
+ bool generateAdvance(SkGlyph* glyph) override {
+ this->getTestSVGTypeface()->getAdvance(glyph);
+
+ const SkVector advance =
+ fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
+ glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+ glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ return true;
+ }
+
+ void generateMetrics(SkGlyph* glyph) override {
+ SkGlyphID glyphID = glyph->getGlyphID();
+ glyphID = glyphID < this->getTestSVGTypeface()->fGlyphCount ? glyphID : 0;
+
+ glyph->zeroMetrics();
+ glyph->fMaskFormat = SkMask::kARGB32_Format;
+ this->generateAdvance(glyph);
+
+ TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
+
+ SkSize containerSize = glyphData.size();
+ SkRect newBounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
+ -glyphData.fOrigin.fY,
+ containerSize.fWidth,
+ containerSize.fHeight);
+ fMatrix.mapRect(&newBounds);
+ SkScalar dx = SkFixedToScalar(glyph->getSubXFixed());
+ SkScalar dy = SkFixedToScalar(glyph->getSubYFixed());
+ newBounds.offset(dx, dy);
+
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
+ }
+
+ void generateImage(const SkGlyph& glyph) override {
+ SkGlyphID glyphID = glyph.getGlyphID();
+ glyphID = glyphID < this->getTestSVGTypeface()->fGlyphCount ? glyphID : 0;
+
+ SkBitmap bm;
+ // TODO: this should be SkImageInfo::MakeS32 when that passes all the tests.
+ bm.installPixels(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType),
+ glyph.fImage,
+ glyph.rowBytes());
+ bm.eraseColor(0);
+
+ TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
+
+ SkScalar dx = SkFixedToScalar(glyph.getSubXFixed());
+ SkScalar dy = SkFixedToScalar(glyph.getSubYFixed());
+
+ SkCanvas canvas(bm);
+ canvas.translate(-glyph.fLeft, -glyph.fTop);
+ canvas.translate(dx, dy);
+ canvas.concat(fMatrix);
+ canvas.translate(glyphData.fOrigin.fX, -glyphData.fOrigin.fY);
+
+ glyphData.render(&canvas);
+ }
+
+ bool generatePath(SkGlyphID glyph, SkPath* path) override {
+ path->reset();
+ return false;
+ }
+
+ void generateFontMetrics(SkFontMetrics* metrics) override {
+ this->getTestSVGTypeface()->getFontMetrics(metrics);
+ SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
+ }
+
+private:
+ SkMatrix fMatrix;
+};
+
+SkScalerContext* TestSVGTypeface::onCreateScalerContext(const SkScalerContextEffects& e,
+ const SkDescriptor* desc) const {
+ return new SkTestSVGScalerContext(sk_ref_sp(const_cast<TestSVGTypeface*>(this)), e, desc);
+}
+
+sk_sp<TestSVGTypeface> TestSVGTypeface::Default() {
+ // Recommended that the first four be .notdef, .null, CR, space
+ constexpr const static SkSVGTestTypefaceGlyphData glyphs[] = {
+ {"fonts/svg/notdef.svg", {100, 800}, 800, 0x0}, // .notdef
+ {"fonts/svg/empty.svg", {0, 0}, 800, 0x0020}, // space
+ {"fonts/svg/diamond.svg", {100, 800}, 800, 0x2662}, // ♢
+ {"fonts/svg/smile.svg", {0, 800}, 800, 0x1F600}, // 😀
+ };
+ SkFontMetrics metrics;
+ metrics.fFlags = SkFontMetrics::kUnderlineThicknessIsValid_Flag |
+ SkFontMetrics::kUnderlinePositionIsValid_Flag |
+ SkFontMetrics::kStrikeoutThicknessIsValid_Flag |
+ SkFontMetrics::kStrikeoutPositionIsValid_Flag;
+ metrics.fTop = -800;
+ metrics.fAscent = -800;
+ metrics.fDescent = 200;
+ metrics.fBottom = 200;
+ metrics.fLeading = 100;
+ metrics.fAvgCharWidth = 1000;
+ metrics.fMaxCharWidth = 1000;
+ metrics.fXMin = 0;
+ metrics.fXMax = 1000;
+ metrics.fXHeight = 500;
+ metrics.fCapHeight = 700;
+ metrics.fUnderlineThickness = 40;
+ metrics.fUnderlinePosition = 20;
+ metrics.fStrikeoutThickness = 20;
+ metrics.fStrikeoutPosition = -400;
+
+ class DefaultTypeface : public TestSVGTypeface {
+ using TestSVGTypeface::TestSVGTypeface;
+
+ bool getPathOp(SkColor color, SkPathOp* op) const override {
+ if ((SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color)) / 3 > 0x20) {
+ *op = SkPathOp::kDifference_SkPathOp;
+ } else {
+ *op = SkPathOp::kUnion_SkPathOp;
+ }
+ return true;
+ }
+ };
+ return sk_make_sp<DefaultTypeface>("Emoji",
+ 1000,
+ metrics,
+ SkMakeSpan(glyphs),
+ SkFontStyle::Normal());
+}
+
+sk_sp<TestSVGTypeface> TestSVGTypeface::Planets() {
+ // Recommended that the first four be .notdef, .null, CR, space
+ constexpr const static SkSVGTestTypefaceGlyphData glyphs[] = {
+ {"fonts/svg/planets/pluto.svg", {0, 20}, 60, 0x0}, // .notdef
+ {"fonts/svg/empty.svg", {0, 0}, 400, 0x0020}, // space
+ {"fonts/svg/planets/mercury.svg", {0, 45}, 120, 0x263F}, // ☿
+ {"fonts/svg/planets/venus.svg", {0, 100}, 240, 0x2640}, // ♀
+ {"fonts/svg/planets/earth.svg", {0, 100}, 240, 0x2641}, // ♁
+ {"fonts/svg/planets/mars.svg", {0, 50}, 130, 0x2642}, // ♂
+ {"fonts/svg/planets/jupiter.svg", {0, 1000}, 2200, 0x2643}, // ♃
+ {"fonts/svg/planets/saturn.svg", {-300, 1500}, 2600, 0x2644}, // ♄
+ {"fonts/svg/planets/uranus.svg", {0, 375}, 790, 0x2645}, // ♅
+ {"fonts/svg/planets/neptune.svg", {0, 350}, 740, 0x2646}, // ♆
+ };
+ SkFontMetrics metrics;
+ metrics.fFlags = SkFontMetrics::kUnderlineThicknessIsValid_Flag |
+ SkFontMetrics::kUnderlinePositionIsValid_Flag |
+ SkFontMetrics::kStrikeoutThicknessIsValid_Flag |
+ SkFontMetrics::kStrikeoutPositionIsValid_Flag;
+ metrics.fTop = -1500;
+ metrics.fAscent = -200;
+ metrics.fDescent = 50;
+ metrics.fBottom = 1558;
+ metrics.fLeading = 10;
+ metrics.fAvgCharWidth = 200;
+ metrics.fMaxCharWidth = 200;
+ metrics.fXMin = -300;
+ metrics.fXMax = 2566;
+ metrics.fXHeight = 100;
+ metrics.fCapHeight = 180;
+ metrics.fUnderlineThickness = 8;
+ metrics.fUnderlinePosition = 2;
+ metrics.fStrikeoutThickness = 2;
+ metrics.fStrikeoutPosition = -80;
+
+ class PlanetTypeface : public TestSVGTypeface {
+ using TestSVGTypeface::TestSVGTypeface;
+
+ bool getPathOp(SkColor color, SkPathOp* op) const override {
+ *op = SkPathOp::kUnion_SkPathOp;
+ return true;
+ }
+ };
+ return sk_make_sp<PlanetTypeface>("Planets",
+ 200,
+ metrics,
+ SkMakeSpan(glyphs),
+ SkFontStyle::Normal());
+}
+
+void TestSVGTypeface::exportTtxCommon(SkWStream* out,
+ const char* type,
+ const SkTArray<GlyfInfo>* glyfInfo) const {
+ int totalGlyphs = fGlyphCount;
+ out->writeText(" <GlyphOrder>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ out->writeText(" <GlyphID name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\"/>\n");
+ }
+ if (glyfInfo) {
+ for (int i = 0; i < fGlyphCount; ++i) {
+ for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) {
+ out->writeText(" <GlyphID name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("l");
+ out->writeHexAsText(j, 4);
+ out->writeText("\"/>\n");
+ ++totalGlyphs;
+ }
+ }
+ }
+ out->writeText(" </GlyphOrder>\n");
+
+ out->writeText(" <head>\n");
+ out->writeText(" <tableVersion value=\"1.0\"/>\n");
+ out->writeText(" <fontRevision value=\"1.0\"/>\n");
+ out->writeText(" <checkSumAdjustment value=\"0xa9c3274\"/>\n");
+ out->writeText(" <magicNumber value=\"0x5f0f3cf5\"/>\n");
+ out->writeText(" <flags value=\"00000000 00011011\"/>\n");
+ out->writeText(" <unitsPerEm value=\"");
+ out->writeDecAsText(fUpem);
+ out->writeText("\"/>\n");
+ out->writeText(" <created value=\"Thu Feb 15 12:55:49 2018\"/>\n");
+ out->writeText(" <modified value=\"Thu Feb 15 12:55:49 2018\"/>\n");
+ // TODO: not recalculated for bitmap fonts?
+ out->writeText(" <xMin value=\"");
+ out->writeScalarAsText(fFontMetrics.fXMin);
+ out->writeText("\"/>\n");
+ out->writeText(" <yMin value=\"");
+ out->writeScalarAsText(-fFontMetrics.fBottom);
+ out->writeText("\"/>\n");
+ out->writeText(" <xMax value=\"");
+ out->writeScalarAsText(fFontMetrics.fXMax);
+ out->writeText("\"/>\n");
+ out->writeText(" <yMax value=\"");
+ out->writeScalarAsText(-fFontMetrics.fTop);
+ out->writeText("\"/>\n");
+
+ char macStyle[16] = {
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
+ if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
+ macStyle[0xF - 0x0] = '1'; // Bold
+ }
+ switch (this->fontStyle().slant()) {
+ case SkFontStyle::kUpright_Slant: break;
+ case SkFontStyle::kItalic_Slant:
+ macStyle[0xF - 0x1] = '1'; // Italic
+ break;
+ case SkFontStyle::kOblique_Slant:
+ macStyle[0xF - 0x1] = '1'; // Italic
+ break;
+ default: SK_ABORT("Unknown slant.");
+ }
+ if (this->fontStyle().width() <= SkFontStyle::kCondensed_Width) {
+ macStyle[0xF - 0x5] = '1'; // Condensed
+ } else if (this->fontStyle().width() >= SkFontStyle::kExpanded_Width) {
+ macStyle[0xF - 0x6] = '1'; // Extended
+ }
+ out->writeText(" <macStyle value=\"");
+ out->write(macStyle, 8);
+ out->writeText(" ");
+ out->write(macStyle + 8, 8);
+ out->writeText("\"/>\n");
+ out->writeText(" <lowestRecPPEM value=\"8\"/>\n");
+ out->writeText(" <fontDirectionHint value=\"2\"/>\n");
+ out->writeText(" <indexToLocFormat value=\"0\"/>\n");
+ out->writeText(" <glyphDataFormat value=\"0\"/>\n");
+ out->writeText(" </head>\n");
+
+ out->writeText(" <hhea>\n");
+ out->writeText(" <tableVersion value=\"0x00010000\"/>\n");
+ out->writeText(" <ascent value=\"");
+ out->writeDecAsText(-fFontMetrics.fAscent);
+ out->writeText("\"/>\n");
+ out->writeText(" <descent value=\"");
+ out->writeDecAsText(-fFontMetrics.fDescent);
+ out->writeText("\"/>\n");
+ out->writeText(" <lineGap value=\"");
+ out->writeDecAsText(fFontMetrics.fLeading);
+ out->writeText("\"/>\n");
+ out->writeText(" <advanceWidthMax value=\"0\"/>\n");
+ out->writeText(" <minLeftSideBearing value=\"0\"/>\n");
+ out->writeText(" <minRightSideBearing value=\"0\"/>\n");
+ out->writeText(" <xMaxExtent value=\"");
+ out->writeScalarAsText(fFontMetrics.fXMax - fFontMetrics.fXMin);
+ out->writeText("\"/>\n");
+ out->writeText(" <caretSlopeRise value=\"1\"/>\n");
+ out->writeText(" <caretSlopeRun value=\"0\"/>\n");
+ out->writeText(" <caretOffset value=\"0\"/>\n");
+ out->writeText(" <reserved0 value=\"0\"/>\n");
+ out->writeText(" <reserved1 value=\"0\"/>\n");
+ out->writeText(" <reserved2 value=\"0\"/>\n");
+ out->writeText(" <reserved3 value=\"0\"/>\n");
+ out->writeText(" <metricDataFormat value=\"0\"/>\n");
+ out->writeText(" <numberOfHMetrics value=\"0\"/>\n");
+ out->writeText(" </hhea>\n");
+
+ // Some of this table is going to be re-calculated, but we have to write it out anyway.
+ out->writeText(" <maxp>\n");
+ out->writeText(" <tableVersion value=\"0x10000\"/>\n");
+ out->writeText(" <numGlyphs value=\"");
+ out->writeDecAsText(totalGlyphs);
+ out->writeText("\"/>\n");
+ out->writeText(" <maxPoints value=\"4\"/>\n");
+ out->writeText(" <maxContours value=\"1\"/>\n");
+ out->writeText(" <maxCompositePoints value=\"0\"/>\n");
+ out->writeText(" <maxCompositeContours value=\"0\"/>\n");
+ out->writeText(" <maxZones value=\"1\"/>\n");
+ out->writeText(" <maxTwilightPoints value=\"0\"/>\n");
+ out->writeText(" <maxStorage value=\"0\"/>\n");
+ out->writeText(" <maxFunctionDefs value=\"10\"/>\n");
+ out->writeText(" <maxInstructionDefs value=\"0\"/>\n");
+ out->writeText(" <maxStackElements value=\"512\"/>\n");
+ out->writeText(" <maxSizeOfInstructions value=\"24\"/>\n");
+ out->writeText(" <maxComponentElements value=\"0\"/>\n");
+ out->writeText(" <maxComponentDepth value=\"0\"/>\n");
+ out->writeText(" </maxp>\n");
+
+ out->writeText(" <OS_2>\n");
+ out->writeText(" <version value=\"4\"/>\n");
+ out->writeText(" <xAvgCharWidth value=\"");
+ out->writeScalarAsText(fFontMetrics.fAvgCharWidth);
+ out->writeText("\"/>\n");
+ out->writeText(" <usWeightClass value=\"");
+ out->writeDecAsText(this->fontStyle().weight());
+ out->writeText("\"/>\n");
+ out->writeText(" <usWidthClass value=\"");
+ out->writeDecAsText(this->fontStyle().width());
+ out->writeText("\"/>\n");
+ out->writeText(" <fsType value=\"00000000 00000000\"/>\n");
+ out->writeText(" <ySubscriptXSize value=\"665\"/>\n");
+ out->writeText(" <ySubscriptYSize value=\"716\"/>\n");
+ out->writeText(" <ySubscriptXOffset value=\"0\"/>\n");
+ out->writeText(" <ySubscriptYOffset value=\"143\"/>\n");
+ out->writeText(" <ySuperscriptXSize value=\"665\"/>\n");
+ out->writeText(" <ySuperscriptYSize value=\"716\"/>\n");
+ out->writeText(" <ySuperscriptXOffset value=\"0\"/>\n");
+ out->writeText(" <ySuperscriptYOffset value=\"491\"/>\n");
+ out->writeText(" <yStrikeoutSize value=\"");
+ out->writeScalarAsText(fFontMetrics.fStrikeoutThickness);
+ out->writeText("\"/>\n");
+ out->writeText(" <yStrikeoutPosition value=\"");
+ out->writeScalarAsText(-fFontMetrics.fStrikeoutPosition);
+ out->writeText("\"/>\n");
+ out->writeText(" <sFamilyClass value=\"0\"/>\n");
+ out->writeText(" <panose>\n");
+ out->writeText(" <bFamilyType value=\"0\"/>\n");
+ out->writeText(" <bSerifStyle value=\"0\"/>\n");
+ out->writeText(" <bWeight value=\"0\"/>\n");
+ out->writeText(" <bProportion value=\"0\"/>\n");
+ out->writeText(" <bContrast value=\"0\"/>\n");
+ out->writeText(" <bStrokeVariation value=\"0\"/>\n");
+ out->writeText(" <bArmStyle value=\"0\"/>\n");
+ out->writeText(" <bLetterForm value=\"0\"/>\n");
+ out->writeText(" <bMidline value=\"0\"/>\n");
+ out->writeText(" <bXHeight value=\"0\"/>\n");
+ out->writeText(" </panose>\n");
+ out->writeText(" <ulUnicodeRange1 value=\"00000000 00000000 00000000 00000001\"/>\n");
+ out->writeText(" <ulUnicodeRange2 value=\"00010000 00000000 00000000 00000000\"/>\n");
+ out->writeText(" <ulUnicodeRange3 value=\"00000000 00000000 00000000 00000000\"/>\n");
+ out->writeText(" <ulUnicodeRange4 value=\"00000000 00000000 00000000 00000000\"/>\n");
+ out->writeText(" <achVendID value=\"Skia\"/>\n");
+ char fsSelection[16] = {
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
+ fsSelection[0xF - 0x7] = '1'; // Use typo metrics
+ if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
+ fsSelection[0xF - 0x5] = '1'; // Bold
+ }
+ switch (this->fontStyle().slant()) {
+ case SkFontStyle::kUpright_Slant:
+ if (this->fontStyle().weight() < SkFontStyle::Bold().weight()) {
+ fsSelection[0xF - 0x6] = '1'; // Not bold or italic, is regular
+ }
+ break;
+ case SkFontStyle::kItalic_Slant:
+ fsSelection[0xF - 0x0] = '1'; // Italic
+ break;
+ case SkFontStyle::kOblique_Slant:
+ fsSelection[0xF - 0x0] = '1'; // Italic
+ fsSelection[0xF - 0x9] = '1'; // Oblique
+ break;
+ default: SK_ABORT("Unknown slant.");
+ }
+ out->writeText(" <fsSelection value=\"");
+ out->write(fsSelection, 8);
+ out->writeText(" ");
+ out->write(fsSelection + 8, 8);
+ out->writeText("\"/>\n");
+ out->writeText(" <usFirstCharIndex value=\"0\"/>\n");
+ out->writeText(" <usLastCharIndex value=\"0\"/>\n");
+ out->writeText(" <sTypoAscender value=\"");
+ out->writeScalarAsText(-fFontMetrics.fAscent);
+ out->writeText("\"/>\n");
+ out->writeText(" <sTypoDescender value=\"");
+ out->writeScalarAsText(-fFontMetrics.fDescent);
+ out->writeText("\"/>\n");
+ out->writeText(" <sTypoLineGap value=\"");
+ out->writeScalarAsText(fFontMetrics.fLeading);
+ out->writeText("\"/>\n");
+ out->writeText(" <usWinAscent value=\"");
+ out->writeScalarAsText(-fFontMetrics.fAscent);
+ out->writeText("\"/>\n");
+ out->writeText(" <usWinDescent value=\"");
+ out->writeScalarAsText(fFontMetrics.fDescent);
+ out->writeText("\"/>\n");
+ out->writeText(" <ulCodePageRange1 value=\"00000000 00000000 00000000 00000000\"/>\n");
+ out->writeText(" <ulCodePageRange2 value=\"00000000 00000000 00000000 00000000\"/>\n");
+ out->writeText(" <sxHeight value=\"");
+ out->writeScalarAsText(fFontMetrics.fXHeight);
+ out->writeText("\"/>\n");
+ out->writeText(" <sCapHeight value=\"");
+ out->writeScalarAsText(fFontMetrics.fCapHeight);
+ out->writeText("\"/>\n");
+ out->writeText(" <usDefaultChar value=\"0\"/>\n");
+ out->writeText(" <usBreakChar value=\"32\"/>\n");
+ out->writeText(" <usMaxContext value=\"0\"/>\n");
+ out->writeText(" </OS_2>\n");
+
+ out->writeText(" <hmtx>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ out->writeText(" <mtx name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\" width=\"");
+ out->writeDecAsText(fGlyphs[i].fAdvance);
+ out->writeText("\" lsb=\"");
+ int lsb = fGlyphs[i].fOrigin.fX;
+ if (glyfInfo) {
+ lsb += (*glyfInfo)[i].fBounds.fLeft;
+ }
+ out->writeDecAsText(lsb);
+ out->writeText("\"/>\n");
+ }
+ if (glyfInfo) {
+ for (int i = 0; i < fGlyphCount; ++i) {
+ for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) {
+ out->writeText(" <mtx name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("l");
+ out->writeHexAsText(j, 4);
+ out->writeText("\" width=\"");
+ out->writeDecAsText(fGlyphs[i].fAdvance);
+ out->writeText("\" lsb=\"");
+ int32_t lsb = fGlyphs[i].fOrigin.fX + (*glyfInfo)[i].fLayers[j].fBounds.fLeft;
+ out->writeDecAsText(lsb);
+ out->writeText("\"/>\n");
+ }
+ }
+ }
+ out->writeText(" </hmtx>\n");
+
+ bool hasNonBMP = false;
+ out->writeText(" <cmap>\n");
+ out->writeText(" <tableVersion version=\"0\"/>\n");
+ out->writeText(" <cmap_format_4 platformID=\"3\" platEncID=\"1\" language=\"0\">\n");
+ fCMap.foreach ([&out, &hasNonBMP](const SkUnichar& c, const SkGlyphID& g) {
+ if (0xFFFF < c) {
+ hasNonBMP = true;
+ return;
+ }
+ out->writeText(" <map code=\"0x");
+ out->writeHexAsText(c, 4);
+ out->writeText("\" name=\"glyf");
+ out->writeHexAsText(g, 4);
+ out->writeText("\"/>\n");
+ });
+ out->writeText(" </cmap_format_4>\n");
+ if (hasNonBMP) {
+ out->writeText(
+ " <cmap_format_12 platformID=\"3\" platEncID=\"10\" format=\"12\" "
+ "reserved=\"0\" length=\"1\" language=\"0\" nGroups=\"0\">\n");
+ fCMap.foreach ([&out](const SkUnichar& c, const SkGlyphID& g) {
+ out->writeText(" <map code=\"0x");
+ out->writeHexAsText(c, 6);
+ out->writeText("\" name=\"glyf");
+ out->writeHexAsText(g, 4);
+ out->writeText("\"/>\n");
+ });
+ out->writeText(" </cmap_format_12>\n");
+ }
+ out->writeText(" </cmap>\n");
+
+ out->writeText(" <name>\n");
+ out->writeText(
+ " <namerecord nameID=\"1\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
+ out->writeText(" ");
+ out->writeText(fName.c_str());
+ out->writeText(" ");
+ out->writeText(type);
+ out->writeText("\n");
+ out->writeText(" </namerecord>\n");
+ out->writeText(
+ " <namerecord nameID=\"2\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
+ out->writeText(" Regular\n");
+ out->writeText(" </namerecord>\n");
+ out->writeText(" </name>\n");
+
+ out->writeText(" <post>\n");
+ out->writeText(" <formatType value=\"3.0\"/>\n");
+ out->writeText(" <italicAngle value=\"0.0\"/>\n");
+ out->writeText(" <underlinePosition value=\"");
+ out->writeScalarAsText(fFontMetrics.fUnderlinePosition);
+ out->writeText("\"/>\n");
+ out->writeText(" <underlineThickness value=\"");
+ out->writeScalarAsText(fFontMetrics.fUnderlineThickness);
+ out->writeText("\"/>\n");
+ out->writeText(" <isFixedPitch value=\"0\"/>\n");
+ out->writeText(" <minMemType42 value=\"0\"/>\n");
+ out->writeText(" <maxMemType42 value=\"0\"/>\n");
+ out->writeText(" <minMemType1 value=\"0\"/>\n");
+ out->writeText(" <maxMemType1 value=\"0\"/>\n");
+ out->writeText(" </post>\n");
+}
+
+void TestSVGTypeface::exportTtxCbdt(SkWStream* out, SkSpan<unsigned> strikeSizes) const {
+ SkPaint paint;
+ SkFont font;
+ font.setTypeface(sk_ref_sp(const_cast<TestSVGTypeface*>(this)));
+ SkString name;
+ this->getFamilyName(&name);
+
+ // The CBDT/CBLC format is quite restrictive. Only write strikes which fully fit.
+ SkSTArray<8, int> goodStrikeSizes;
+ for (size_t strikeIndex = 0; strikeIndex < strikeSizes.size(); ++strikeIndex) {
+ font.setSize(strikeSizes[strikeIndex]);
+
+ // CBLC limits
+ SkFontMetrics fm;
+ font.getMetrics(&fm);
+ if (!SkTFitsIn<int8_t>((int)(-fm.fTop)) || !SkTFitsIn<int8_t>((int)(-fm.fBottom)) ||
+ !SkTFitsIn<uint8_t>((int)(fm.fXMax - fm.fXMin))) {
+ SkDebugf("Metrics too big cbdt font size %f for %s.\n", font.getSize(), name.c_str());
+ continue;
+ }
+
+ // CBDT limits
+ auto exceedsCbdtLimits = [&]() {
+ for (int i = 0; i < fGlyphCount; ++i) {
+ SkGlyphID gid = i;
+ SkScalar advance;
+ SkRect bounds;
+ font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
+ SkIRect ibounds = bounds.roundOut();
+ if (!SkTFitsIn<int8_t>(ibounds.fLeft) || !SkTFitsIn<int8_t>(ibounds.fTop) ||
+ !SkTFitsIn<uint8_t>(ibounds.width()) || !SkTFitsIn<uint8_t>(ibounds.height()) ||
+ !SkTFitsIn<uint8_t>((int)advance)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ if (exceedsCbdtLimits()) {
+ SkDebugf("Glyphs too big cbdt font size %f for %s.\n", font.getSize(), name.c_str());
+ continue;
+ }
+
+ goodStrikeSizes.emplace_back(strikeSizes[strikeIndex]);
+ }
+
+ if (goodStrikeSizes.empty()) {
+ SkDebugf("No strike size fit for cbdt font for %s.\n", name.c_str());
+ return;
+ }
+
+ out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
+ this->exportTtxCommon(out, "CBDT");
+
+ out->writeText(" <CBDT>\n");
+ out->writeText(" <header version=\"2.0\"/>\n");
+ for (size_t strikeIndex = 0; strikeIndex < goodStrikeSizes.size(); ++strikeIndex) {
+ font.setSize(goodStrikeSizes[strikeIndex]);
+
+ out->writeText(" <strikedata index=\"");
+ out->writeDecAsText(strikeIndex);
+ out->writeText("\">\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ SkGlyphID gid = i;
+ SkScalar advance;
+ SkRect bounds;
+ font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
+ SkIRect ibounds = bounds.roundOut();
+ if (ibounds.isEmpty()) {
+ continue;
+ }
+ SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height());
+ sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info));
+ SkASSERT(surface);
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->clear(0);
+ SkPixmap pix;
+ surface->peekPixels(&pix);
+ canvas->drawSimpleText(&gid,
+ sizeof(gid),
+ SkTextEncoding::kGlyphID,
+ -bounds.fLeft,
+ -bounds.fTop,
+ font,
+ paint);
+ surface->flush();
+ sk_sp<SkImage> image = surface->makeImageSnapshot();
+ sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
+
+ out->writeText(" <cbdt_bitmap_format_17 name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\">\n");
+ out->writeText(" <SmallGlyphMetrics>\n");
+ out->writeText(" <height value=\"");
+ out->writeDecAsText(image->height());
+ out->writeText("\"/>\n");
+ out->writeText(" <width value=\"");
+ out->writeDecAsText(image->width());
+ out->writeText("\"/>\n");
+ out->writeText(" <BearingX value=\"");
+ out->writeDecAsText(ibounds.fLeft);
+ out->writeText("\"/>\n");
+ out->writeText(" <BearingY value=\"");
+ out->writeDecAsText(-ibounds.fTop);
+ out->writeText("\"/>\n");
+ out->writeText(" <Advance value=\"");
+ out->writeDecAsText((int)advance);
+ out->writeText("\"/>\n");
+ out->writeText(" </SmallGlyphMetrics>\n");
+ out->writeText(" <rawimagedata>");
+ uint8_t const* bytes = data->bytes();
+ for (size_t i = 0; i < data->size(); ++i) {
+ if ((i % 0x10) == 0x0) {
+ out->writeText("\n ");
+ } else if (((i - 1) % 0x4) == 0x3) {
+ out->writeText(" ");
+ }
+ out->writeHexAsText(bytes[i], 2);
+ }
+ out->writeText("\n");
+ out->writeText(" </rawimagedata>\n");
+ out->writeText(" </cbdt_bitmap_format_17>\n");
+ }
+ out->writeText(" </strikedata>\n");
+ }
+ out->writeText(" </CBDT>\n");
+
+ SkFontMetrics fm;
+ out->writeText(" <CBLC>\n");
+ out->writeText(" <header version=\"2.0\"/>\n");
+ for (size_t strikeIndex = 0; strikeIndex < goodStrikeSizes.size(); ++strikeIndex) {
+ font.setSize(goodStrikeSizes[strikeIndex]);
+ font.getMetrics(&fm);
+ out->writeText(" <strike index=\"");
+ out->writeDecAsText(strikeIndex);
+ out->writeText("\">\n");
+ out->writeText(" <bitmapSizeTable>\n");
+ out->writeText(" <sbitLineMetrics direction=\"hori\">\n");
+ out->writeText(" <ascender value=\"");
+ out->writeDecAsText((int)(-fm.fTop));
+ out->writeText("\"/>\n");
+ out->writeText(" <descender value=\"");
+ out->writeDecAsText((int)(-fm.fBottom));
+ out->writeText("\"/>\n");
+ out->writeText(" <widthMax value=\"");
+ out->writeDecAsText((int)(fm.fXMax - fm.fXMin));
+ out->writeText("\"/>\n");
+ out->writeText(" <caretSlopeNumerator value=\"0\"/>\n");
+ out->writeText(" <caretSlopeDenominator value=\"0\"/>\n");
+ out->writeText(" <caretOffset value=\"0\"/>\n");
+ out->writeText(" <minOriginSB value=\"0\"/>\n");
+ out->writeText(" <minAdvanceSB value=\"0\"/>\n");
+ out->writeText(" <maxBeforeBL value=\"0\"/>\n");
+ out->writeText(" <minAfterBL value=\"0\"/>\n");
+ out->writeText(" <pad1 value=\"0\"/>\n");
+ out->writeText(" <pad2 value=\"0\"/>\n");
+ out->writeText(" </sbitLineMetrics>\n");
+ out->writeText(" <sbitLineMetrics direction=\"vert\">\n");
+ out->writeText(" <ascender value=\"");
+ out->writeDecAsText((int)(-fm.fTop));
+ out->writeText("\"/>\n");
+ out->writeText(" <descender value=\"");
+ out->writeDecAsText((int)(-fm.fBottom));
+ out->writeText("\"/>\n");
+ out->writeText(" <widthMax value=\"");
+ out->writeDecAsText((int)(fm.fXMax - fm.fXMin));
+ out->writeText("\"/>\n");
+ out->writeText(" <caretSlopeNumerator value=\"0\"/>\n");
+ out->writeText(" <caretSlopeDenominator value=\"0\"/>\n");
+ out->writeText(" <caretOffset value=\"0\"/>\n");
+ out->writeText(" <minOriginSB value=\"0\"/>\n");
+ out->writeText(" <minAdvanceSB value=\"0\"/>\n");
+ out->writeText(" <maxBeforeBL value=\"0\"/>\n");
+ out->writeText(" <minAfterBL value=\"0\"/>\n");
+ out->writeText(" <pad1 value=\"0\"/>\n");
+ out->writeText(" <pad2 value=\"0\"/>\n");
+ out->writeText(" </sbitLineMetrics>\n");
+ out->writeText(" <colorRef value=\"0\"/>\n");
+ out->writeText(" <startGlyphIndex value=\"1\"/>\n");
+ out->writeText(" <endGlyphIndex value=\"1\"/>\n");
+ out->writeText(" <ppemX value=\"");
+ out->writeDecAsText(goodStrikeSizes[strikeIndex]);
+ out->writeText("\"/>\n");
+ out->writeText(" <ppemY value=\"");
+ out->writeDecAsText(goodStrikeSizes[strikeIndex]);
+ out->writeText("\"/>\n");
+ out->writeText(" <bitDepth value=\"32\"/>\n");
+ out->writeText(" <flags value=\"1\"/>\n");
+ out->writeText(" </bitmapSizeTable>\n");
+ out->writeText(
+ " <eblc_index_sub_table_1 imageFormat=\"17\" firstGlyphIndex=\"1\" "
+ "lastGlyphIndex=\"1\">\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ SkGlyphID gid = i;
+ SkRect bounds;
+ font.getBounds(&gid, 1, &bounds, nullptr);
+ if (bounds.isEmpty()) {
+ continue;
+ }
+ out->writeText(" <glyphLoc name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\"/>\n");
+ }
+ out->writeText(" </eblc_index_sub_table_1>\n");
+ out->writeText(" </strike>\n");
+ }
+ out->writeText(" </CBLC>\n");
+
+ out->writeText("</ttFont>\n");
+}
+
+/**
+ * UnitsPerEm is generally 1000 here. Versions of macOS older than 10.13
+ * have problems in CoreText determining the glyph bounds of bitmap glyphs
+ * with unitsPerEm set to 1024 or numbers not divisible by 100 when the
+ * contour is not closed. The bounds of sbix fonts on macOS appear to be those
+ * of the outline in the 'glyf' table. If this countour is closed it will be
+ * drawn, as the 'glyf' outline is to be drawn on top of any bitmap. (There is
+ * a bit which is supposed to control this, but it cannot be relied on.) So
+ * make the glyph contour a degenerate line with points at the edge of the
+ * bounding box of the glyph.
+ */
+void TestSVGTypeface::exportTtxSbix(SkWStream* out, SkSpan<unsigned> strikeSizes) const {
+ out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
+ this->exportTtxCommon(out, "sbix");
+
+ SkPaint paint;
+ SkFont font;
+ font.setTypeface(sk_ref_sp(const_cast<TestSVGTypeface*>(this)));
+
+ out->writeText(" <glyf>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
+
+ SkSize containerSize = glyphData.size();
+ SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
+ -glyphData.fOrigin.fY,
+ containerSize.fWidth,
+ containerSize.fHeight);
+ SkIRect ibounds = bounds.roundOut();
+ out->writeText(" <TTGlyph name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\" xMin=\"");
+ out->writeDecAsText(ibounds.fLeft);
+ out->writeText("\" yMin=\"");
+ out->writeDecAsText(-ibounds.fBottom);
+ out->writeText("\" xMax=\"");
+ out->writeDecAsText(ibounds.fRight);
+ out->writeText("\" yMax=\"");
+ out->writeDecAsText(-ibounds.fTop);
+ out->writeText("\">\n");
+ out->writeText(" <contour>\n");
+ out->writeText(" <pt x=\"");
+ out->writeDecAsText(ibounds.fLeft);
+ out->writeText("\" y=\"");
+ out->writeDecAsText(-ibounds.fBottom);
+ out->writeText("\" on=\"1\"/>\n");
+ out->writeText(" </contour>\n");
+ out->writeText(" <contour>\n");
+ out->writeText(" <pt x=\"");
+ out->writeDecAsText(ibounds.fRight);
+ out->writeText("\" y=\"");
+ out->writeDecAsText(-ibounds.fTop);
+ out->writeText("\" on=\"1\"/>\n");
+ out->writeText(" </contour>\n");
+ out->writeText(" <instructions/>\n");
+ out->writeText(" </TTGlyph>\n");
+ }
+ out->writeText(" </glyf>\n");
+
+ // The loca table will be re-calculated, but if we don't write one we don't get one.
+ out->writeText(" <loca/>\n");
+
+ out->writeText(" <sbix>\n");
+ out->writeText(" <version value=\"1\"/>\n");
+ out->writeText(" <flags value=\"00000000 00000001\"/>\n");
+ for (size_t strikeIndex = 0; strikeIndex < strikeSizes.size(); ++strikeIndex) {
+ font.setSize(strikeSizes[strikeIndex]);
+ out->writeText(" <strike>\n");
+ out->writeText(" <ppem value=\"");
+ out->writeDecAsText(strikeSizes[strikeIndex]);
+ out->writeText("\"/>\n");
+ out->writeText(" <resolution value=\"72\"/>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ SkGlyphID gid = i;
+ SkScalar advance;
+ SkRect bounds;
+ font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
+ SkIRect ibounds = bounds.roundOut();
+ if (ibounds.isEmpty()) {
+ continue;
+ }
+ SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height());
+ sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info));
+ SkASSERT(surface);
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->clear(0);
+ SkPixmap pix;
+ surface->peekPixels(&pix);
+ canvas->drawSimpleText(&gid,
+ sizeof(gid),
+ SkTextEncoding::kGlyphID,
+ -bounds.fLeft,
+ -bounds.fTop,
+ font,
+ paint);
+ surface->flush();
+ sk_sp<SkImage> image = surface->makeImageSnapshot();
+ sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
+
+ // The originOffset values are difficult to use as DirectWrite and FreeType interpret
+ // the origin to be the initial glyph position on the baseline, but CoreGraphics
+ // interprets the origin to be the lower left of the cbox of the outline in the 'glyf'
+ // table.
+ //#define SK_SBIX_LIKE_FT
+ //#define SK_SBIX_LIKE_DW
+ out->writeText(" <glyph name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\" graphicType=\"png \" originOffsetX=\"");
+#if defined(SK_SBIX_LIKE_FT) || defined(SK_SBIX_LIKE_DW)
+ out->writeDecAsText(bounds.fLeft);
+#else
+ out->writeDecAsText(0);
+#endif
+ // DirectWrite and CoreGraphics use positive values of originOffsetY to push the
+ // image visually up (but from different origins).
+ // FreeType uses positive values to push the image down.
+ out->writeText("\" originOffsetY=\"");
+#if defined(SK_SBIX_LIKE_FT)
+ out->writeScalarAsText(bounds.fBottom);
+#elif defined(SK_SBIX_LIKE_DW)
+ out->writeScalarAsText(-bounds.fBottom);
+#else
+ out->writeDecAsText(0);
+#endif
+ out->writeText("\">\n");
+
+ out->writeText(" <hexdata>");
+ uint8_t const* bytes = data->bytes();
+ for (size_t i = 0; i < data->size(); ++i) {
+ if ((i % 0x10) == 0x0) {
+ out->writeText("\n ");
+ } else if (((i - 1) % 0x4) == 0x3) {
+ out->writeText(" ");
+ }
+ out->writeHexAsText(bytes[i], 2);
+ }
+ out->writeText("\n");
+ out->writeText(" </hexdata>\n");
+ out->writeText(" </glyph>\n");
+ }
+ out->writeText(" </strike>\n");
+ }
+ out->writeText(" </sbix>\n");
+ out->writeText("</ttFont>\n");
+}
+
+namespace {
+
+void convert_noninflect_cubic_to_quads(const SkPoint p[4],
+ SkScalar toleranceSqd,
+ SkTArray<SkPoint, true>* quads,
+ int sublevel = 0) {
+ // Notation: Point a is always p[0]. Point b is p[1] unless p[1] == p[0], in which case it is
+ // p[2]. Point d is always p[3]. Point c is p[2] unless p[2] == p[3], in which case it is p[1].
+
+ SkVector ab = p[1] - p[0];
+ SkVector dc = p[2] - p[3];
+
+ if (SkPointPriv::LengthSqd(ab) < SK_ScalarNearlyZero) {
+ if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) {
+ SkPoint* degQuad = quads->push_back_n(3);
+ degQuad[0] = p[0];
+ degQuad[1] = p[0];
+ degQuad[2] = p[3];
+ return;
+ }
+ ab = p[2] - p[0];
+ }
+ if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) {
+ dc = p[1] - p[3];
+ }
+
+ static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2;
+ static const int kMaxSubdivs = 10;
+
+ ab.scale(kLengthScale);
+ dc.scale(kLengthScale);
+
+ // e0 and e1 are extrapolations along vectors ab and dc.
+ SkVector c0 = p[0];
+ c0 += ab;
+ SkVector c1 = p[3];
+ c1 += dc;
+
+ SkScalar dSqd = sublevel > kMaxSubdivs ? 0 : SkPointPriv::DistanceToSqd(c0, c1);
+ if (dSqd < toleranceSqd) {
+ SkPoint cAvg = c0;
+ cAvg += c1;
+ cAvg.scale(SK_ScalarHalf);
+
+ SkPoint* pts = quads->push_back_n(3);
+ pts[0] = p[0];
+ pts[1] = cAvg;
+ pts[2] = p[3];
+ return;
+ }
+ SkPoint choppedPts[7];
+ SkChopCubicAtHalf(p, choppedPts);
+ convert_noninflect_cubic_to_quads(choppedPts + 0, toleranceSqd, quads, sublevel + 1);
+ convert_noninflect_cubic_to_quads(choppedPts + 3, toleranceSqd, quads, sublevel + 1);
+}
+
+void convertCubicToQuads(const SkPoint p[4], SkScalar tolScale, SkTArray<SkPoint, true>* quads) {
+ if (!p[0].isFinite() || !p[1].isFinite() || !p[2].isFinite() || !p[3].isFinite()) {
+ return;
+ }
+ SkPoint chopped[10];
+ int count = SkChopCubicAtInflections(p, chopped);
+
+ const SkScalar tolSqd = SkScalarSquare(tolScale);
+
+ for (int i = 0; i < count; ++i) {
+ SkPoint* cubic = chopped + 3 * i;
+ convert_noninflect_cubic_to_quads(cubic, tolSqd, quads);
+ }
+}
+
+void path_to_quads(const SkPath& path, SkPath* quadPath) {
+ quadPath->reset();
+ SkTArray<SkPoint, true> qPts;
+ SkAutoConicToQuads converter;
+ const SkPoint* quadPts;
+ SkPath::RawIter iter(path);
+ uint8_t verb;
+ SkPoint pts[4];
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb: quadPath->moveTo(pts[0].fX, pts[0].fY); break;
+ case SkPath::kLine_Verb: quadPath->lineTo(pts[1].fX, pts[1].fY); break;
+ case SkPath::kQuad_Verb:
+ quadPath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
+ break;
+ case SkPath::kCubic_Verb:
+ qPts.reset();
+ convertCubicToQuads(pts, SK_Scalar1, &qPts);
+ for (int i = 0; i < qPts.count(); i += 3) {
+ quadPath->quadTo(
+ qPts[i + 1].fX, qPts[i + 1].fY, qPts[i + 2].fX, qPts[i + 2].fY);
+ }
+ break;
+ case SkPath::kConic_Verb:
+ quadPts = converter.computeQuads(pts, iter.conicWeight(), SK_Scalar1);
+ for (int i = 0; i < converter.countQuads(); ++i) {
+ quadPath->quadTo(quadPts[i * 2 + 1].fX,
+ quadPts[i * 2 + 1].fY,
+ quadPts[i * 2 + 2].fX,
+ quadPts[i * 2 + 2].fY);
+ }
+ break;
+ case SkPath::kClose_Verb: quadPath->close(); break;
+ default: SkDEBUGFAIL("bad verb"); return;
+ }
+ }
+}
+
+class SkCOLRCanvas : public SkNoDrawCanvas {
+public:
+ SkCOLRCanvas(SkRect glyphBounds,
+ const TestSVGTypeface& typeface,
+ SkGlyphID glyphId,
+ TestSVGTypeface::GlyfInfo* glyf,
+ SkTHashMap<SkColor, int>* colors,
+ SkWStream* out)
+ : SkNoDrawCanvas(glyphBounds.roundOut().width(), glyphBounds.roundOut().height())
+ , fBaselineOffset(glyphBounds.top())
+ , fTypeface(typeface)
+ , fGlyphId(glyphId)
+ , fGlyf(glyf)
+ , fColors(colors)
+ , fOut(out)
+ , fLayerId(0) {}
+
+ void writePoint(SkScalar x, SkScalar y, bool on) {
+ fOut->writeText(" <pt x=\"");
+ fOut->writeDecAsText(SkScalarRoundToInt(x));
+ fOut->writeText("\" y=\"");
+ fOut->writeDecAsText(SkScalarRoundToInt(y));
+ fOut->writeText("\" on=\"");
+ fOut->write8(on ? '1' : '0');
+ fOut->writeText("\"/>\n");
+ }
+ SkIRect writePath(const SkPath& path, bool layer) {
+ // Convert to quads.
+ SkPath quads;
+ path_to_quads(path, &quads);
+
+ SkRect bounds = quads.computeTightBounds();
+ SkIRect ibounds = bounds.roundOut();
+ // The bounds will be re-calculated anyway.
+ fOut->writeText(" <TTGlyph name=\"glyf");
+ fOut->writeHexAsText(fGlyphId, 4);
+ if (layer) {
+ fOut->writeText("l");
+ fOut->writeHexAsText(fLayerId, 4);
+ }
+ fOut->writeText("\" xMin=\"");
+ fOut->writeDecAsText(ibounds.fLeft);
+ fOut->writeText("\" yMin=\"");
+ fOut->writeDecAsText(ibounds.fTop);
+ fOut->writeText("\" xMax=\"");
+ fOut->writeDecAsText(ibounds.fRight);
+ fOut->writeText("\" yMax=\"");
+ fOut->writeDecAsText(ibounds.fBottom);
+ fOut->writeText("\">\n");
+
+ SkPath::RawIter iter(quads);
+ uint8_t verb;
+ SkPoint pts[4];
+ bool contourOpen = false;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ if (contourOpen) {
+ fOut->writeText(" </contour>\n");
+ contourOpen = false;
+ }
+ break;
+ case SkPath::kLine_Verb:
+ if (!contourOpen) {
+ fOut->writeText(" <contour>\n");
+ this->writePoint(pts[0].fX, pts[0].fY, true);
+ contourOpen = true;
+ }
+ this->writePoint(pts[1].fX, pts[1].fY, true);
+ break;
+ case SkPath::kQuad_Verb:
+ if (!contourOpen) {
+ fOut->writeText(" <contour>\n");
+ this->writePoint(pts[0].fX, pts[0].fY, true);
+ contourOpen = true;
+ }
+ this->writePoint(pts[1].fX, pts[1].fY, false);
+ this->writePoint(pts[2].fX, pts[2].fY, true);
+ break;
+ case SkPath::kClose_Verb:
+ if (contourOpen) {
+ fOut->writeText(" </contour>\n");
+ contourOpen = false;
+ }
+ break;
+ default: SkDEBUGFAIL("bad verb"); return ibounds;
+ }
+ }
+ if (contourOpen) {
+ fOut->writeText(" </contour>\n");
+ }
+
+ // Required to write out an instructions tag.
+ fOut->writeText(" <instructions/>\n");
+ fOut->writeText(" </TTGlyph>\n");
+ return ibounds;
+ }
+
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ SkPath path;
+ path.addRect(rect);
+ this->drawPath(path, paint);
+ }
+
+ void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
+ SkPath path;
+ path.addOval(oval);
+ this->drawPath(path, paint);
+ }
+
+ void onDrawArc(const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const SkPaint& paint) override {
+ SkPath path;
+ bool fillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect();
+ SkPathPriv::CreateDrawArcPath(
+ &path, oval, startAngle, sweepAngle, useCenter, fillNoPathEffect);
+ this->drawPath(path, paint);
+ }
+
+ void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
+ SkPath path;
+ path.addRRect(rrect);
+ this->drawPath(path, paint);
+ }
+
+ void onDrawPath(const SkPath& platonicPath, const SkPaint& originalPaint) override {
+ SkPaint paint = originalPaint;
+ SkPath path = platonicPath;
+
+ // Apply the path effect.
+ if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
+ bool fill = paint.getFillPath(path, &path);
+
+ paint.setPathEffect(nullptr);
+ if (fill) {
+ paint.setStyle(SkPaint::kFill_Style);
+ } else {
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(0);
+ }
+ }
+
+ // Apply the matrix.
+ SkMatrix m = this->getTotalMatrix();
+ // If done to the canvas then everything would get clipped out.
+ m.postTranslate(0, fBaselineOffset); // put the baseline at 0
+ m.postScale(1, -1); // and flip it since OpenType is y-up.
+ path.transform(m);
+
+ // While creating the default glyf, union with dark colors and intersect with bright colors.
+ SkColor color = paint.getColor();
+ SkPathOp op;
+ if (fTypeface.getPathOp(color, &op)) {
+ fBasePath.add(path, op);
+ }
+ SkIRect bounds = this->writePath(path, true);
+
+ // The CPAL table has the concept of a 'current color' which is index 0xFFFF.
+ // Mark any layer drawn in 'currentColor' as having this special index.
+ // The value of 'currentColor' here should a color which causes this layer to union into the
+ // default glyf.
+ constexpr SkColor currentColor = 0xFF2B0000;
+
+ int colorIndex;
+ if (color == currentColor) {
+ colorIndex = 0xFFFF;
+ } else {
+ int* colorIndexPtr = fColors->find(color);
+ if (colorIndexPtr) {
+ colorIndex = *colorIndexPtr;
+ } else {
+ colorIndex = fColors->count();
+ fColors->set(color, colorIndex);
+ }
+ }
+ fGlyf->fLayers.emplace_back(colorIndex, bounds);
+
+ ++fLayerId;
+ }
+
+ void finishGlyph() {
+ SkPath baseGlyph;
+ fBasePath.resolve(&baseGlyph);
+ fGlyf->fBounds = this->writePath(baseGlyph, false);
+ }
+
+private:
+ SkScalar fBaselineOffset;
+ const TestSVGTypeface& fTypeface;
+ SkGlyphID fGlyphId;
+ TestSVGTypeface::GlyfInfo* fGlyf;
+ SkTHashMap<SkColor, int>* fColors;
+ SkWStream* const fOut;
+ SkOpBuilder fBasePath;
+ int fLayerId;
+};
+
+} // namespace
+
+void TestSVGTypeface::exportTtxColr(SkWStream* out) const {
+ out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
+
+ SkTHashMap<SkColor, int> colors;
+ SkTArray<GlyfInfo> glyfInfos(fGlyphCount);
+
+ // Need to know all the glyphs up front for the common tables.
+ SkDynamicMemoryWStream glyfOut;
+ glyfOut.writeText(" <glyf>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
+
+ SkSize containerSize = glyphData.size();
+ SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
+ -glyphData.fOrigin.fY,
+ containerSize.fWidth,
+ containerSize.fHeight);
+ SkCOLRCanvas canvas(bounds, *this, i, &glyfInfos.emplace_back(), &colors, &glyfOut);
+ glyphData.render(&canvas);
+ canvas.finishGlyph();
+ }
+ glyfOut.writeText(" </glyf>\n");
+
+ this->exportTtxCommon(out, "COLR", &glyfInfos);
+
+ // The loca table will be re-calculated, but if we don't write one we don't get one.
+ out->writeText(" <loca/>\n");
+
+ std::unique_ptr<SkStreamAsset> glyfStream = glyfOut.detachAsStream();
+ out->writeStream(glyfStream.get(), glyfStream->getLength());
+
+ out->writeText(" <COLR>\n");
+ out->writeText(" <version value=\"0\"/>\n");
+ for (int i = 0; i < fGlyphCount; ++i) {
+ if (glyfInfos[i].fLayers.empty()) {
+ continue;
+ }
+ if (glyfInfos[i].fBounds.isEmpty()) {
+ SkDebugf("Glyph %d is empty but has layers.\n", i);
+ }
+ out->writeText(" <ColorGlyph name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("\">\n");
+ for (int j = 0; j < glyfInfos[i].fLayers.count(); ++j) {
+ const int colorIndex = glyfInfos[i].fLayers[j].fLayerColorIndex;
+ out->writeText(" <layer colorID=\"");
+ out->writeDecAsText(colorIndex);
+ out->writeText("\" name=\"glyf");
+ out->writeHexAsText(i, 4);
+ out->writeText("l");
+ out->writeHexAsText(j, 4);
+ out->writeText("\"/>\n");
+ }
+ out->writeText(" </ColorGlyph>\n");
+ }
+ out->writeText(" </COLR>\n");
+
+ // The colors must be written in order, the 'index' is ignored by ttx.
+ SkAutoTMalloc<SkColor> colorsInOrder(colors.count());
+ colors.foreach ([&colorsInOrder](const SkColor& c, const int* i) { colorsInOrder[*i] = c; });
+ out->writeText(" <CPAL>\n");
+ out->writeText(" <version value=\"0\"/>\n");
+ out->writeText(" <numPaletteEntries value=\"");
+ out->writeDecAsText(colors.count());
+ out->writeText("\"/>\n");
+ out->writeText(" <palette index=\"0\">\n");
+ for (int i = 0; i < colors.count(); ++i) {
+ SkColor c = colorsInOrder[i];
+ out->writeText(" <color index=\"");
+ out->writeDecAsText(i);
+ out->writeText("\" value=\"#");
+ out->writeHexAsText(SkColorGetR(c), 2);
+ out->writeHexAsText(SkColorGetG(c), 2);
+ out->writeHexAsText(SkColorGetB(c), 2);
+ out->writeHexAsText(SkColorGetA(c), 2);
+ out->writeText("\"/>\n");
+ }
+ out->writeText(" </palette>\n");
+ out->writeText(" </CPAL>\n");
+
+ out->writeText("</ttFont>\n");
+}
+#endif // SK_XML
diff --git a/src/third_party/skia/tools/fonts/TestSVGTypeface.h b/src/third_party/skia/tools/fonts/TestSVGTypeface.h
new file mode 100644
index 0000000..44d3af2
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestSVGTypeface.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TestSVGTypeface_DEFINED
+#define TestSVGTypeface_DEFINED
+
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypeface.h"
+#include "include/core/SkTypes.h"
+#include "include/pathops/SkPathOps.h"
+#include "include/private/SkMutex.h"
+#include "include/private/SkTArray.h"
+#include "include/private/SkTHash.h"
+#include "src/core/SkSpan.h"
+
+#include <memory>
+
+class SkCanvas;
+class SkDescriptor;
+class SkFontDescriptor;
+class SkFontStyle;
+class SkGlyph;
+class SkPath;
+class SkScalerContext;
+class SkSVGDOM;
+class SkWStream;
+struct SkAdvancedTypefaceMetrics;
+struct SkScalerContextEffects;
+struct SkScalerContextRec;
+
+struct SkSVGTestTypefaceGlyphData {
+ const char* fSvgResourcePath;
+ SkPoint fOrigin; // y-down
+ SkScalar fAdvance;
+ SkUnichar fUnicode; // TODO: this limits to 1:1
+};
+
+class TestSVGTypeface : public SkTypeface {
+public:
+ TestSVGTypeface(const char* name,
+ int upem,
+ const SkFontMetrics& metrics,
+ SkSpan<const SkSVGTestTypefaceGlyphData> data,
+ const SkFontStyle& style);
+ ~TestSVGTypeface() override;
+ void getAdvance(SkGlyph* glyph) const;
+ void getFontMetrics(SkFontMetrics* metrics) const;
+
+ static sk_sp<TestSVGTypeface> Default();
+ static sk_sp<TestSVGTypeface> Planets();
+ void exportTtxCbdt(SkWStream*, SkSpan<unsigned> strikeSizes) const;
+ void exportTtxSbix(SkWStream*, SkSpan<unsigned> strikeSizes) const;
+ void exportTtxColr(SkWStream*) const;
+ virtual bool getPathOp(SkColor, SkPathOp*) const = 0;
+
+ struct GlyfLayerInfo {
+ GlyfLayerInfo(int layerColorIndex, SkIRect bounds)
+ : fLayerColorIndex(layerColorIndex), fBounds(bounds) {}
+ int fLayerColorIndex;
+ SkIRect fBounds;
+ };
+ struct GlyfInfo {
+ GlyfInfo() : fBounds(SkIRect::MakeEmpty()) {}
+ SkIRect fBounds;
+ SkTArray<GlyfLayerInfo> fLayers;
+ };
+
+protected:
+ void exportTtxCommon(SkWStream*, const char* type, const SkTArray<GlyfInfo>* = nullptr) const;
+
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor* desc) const override;
+ void onFilterRec(SkScalerContextRec* rec) const override;
+ void getGlyphToUnicodeMap(SkUnichar*) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+
+ std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override { return nullptr; }
+
+ sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
+ return sk_ref_sp(this);
+ }
+
+ void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
+
+ void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
+
+ void getPostScriptGlyphNames(SkString*) const override {}
+
+ int onCountGlyphs() const override { return fGlyphCount; }
+
+ int onGetUPEM() const override { return fUpem; }
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override {
+ return 0;
+ }
+
+ int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const override {
+ return 0;
+ }
+
+ int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
+
+ size_t onGetTableData(SkFontTableTag tag,
+ size_t offset,
+ size_t length,
+ void* data) const override {
+ return 0;
+ }
+
+private:
+ struct Glyph {
+ Glyph();
+ ~Glyph();
+ SkPoint fOrigin;
+ SkScalar fAdvance;
+ const char* fResourcePath;
+
+ SkSize size() const;
+ void render(SkCanvas*) const;
+
+ private:
+ // Lazily parses the SVG from fResourcePath, and manages mutex locking.
+ template <typename Fn> void withSVG(Fn&&) const;
+
+ // The mutex guards lazy parsing of the SVG, but also predates that.
+ // Must be SkSVGDOM::render() is not thread safe?
+ // If not, an SkOnce is enough here.
+ mutable SkMutex fSvgMutex;
+ mutable bool fParsedSvg = false;
+ mutable sk_sp<SkSVGDOM> fSvg;
+ };
+
+ SkString fName;
+ int fUpem;
+ const SkFontMetrics fFontMetrics;
+ std::unique_ptr<Glyph[]> fGlyphs;
+ int fGlyphCount;
+ SkTHashMap<SkUnichar, SkGlyphID> fCMap;
+ friend class SkTestSVGScalerContext;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/fonts/TestTypeface.cpp b/src/third_party/skia/tools/fonts/TestTypeface.cpp
new file mode 100644
index 0000000..7f30f01
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestTypeface.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkString.h"
+#include "include/private/SkTDArray.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkFontDescriptor.h"
+#include "src/core/SkFontPriv.h"
+#include "src/core/SkGlyph.h"
+#include "src/core/SkPaintPriv.h"
+#include "src/core/SkScalerContext.h"
+#include "src/core/SkUtils.h"
+#include "src/sfnt/SkOTUtils.h"
+#include "tools/fonts/TestTypeface.h"
+
+#include <utility>
+
+class SkDescriptor;
+
+SkTestFont::SkTestFont(const SkTestFontData& fontData)
+ : INHERITED()
+ , fCharCodes(fontData.fCharCodes)
+ , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
+ , fWidths(fontData.fWidths)
+ , fMetrics(fontData.fMetrics)
+ , fName(fontData.fName)
+ , fPaths(nullptr) {
+ init(fontData.fPoints, fontData.fVerbs);
+}
+
+SkTestFont::~SkTestFont() {
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ delete fPaths[index];
+ }
+ delete[] fPaths;
+}
+
+SkGlyphID SkTestFont::glyphForUnichar(SkUnichar charCode) const {
+ for (size_t index = 0; index < fCharCodesCount; ++index) {
+ if (fCharCodes[index] == charCode) {
+ return SkTo<SkGlyphID>(index);
+ }
+ }
+ return 0;
+}
+
+void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
+ fPaths = new SkPath*[fCharCodesCount];
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ SkPath* path = new SkPath;
+ SkPath::Verb verb;
+ while ((verb = (SkPath::Verb)*verbs++) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ path->moveTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kLine_Verb:
+ path->lineTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(pts[0], pts[1], pts[2], pts[3]);
+ pts += 4;
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
+ pts += 6;
+ break;
+ case SkPath::kClose_Verb: path->close(); break;
+ default: SkDEBUGFAIL("bad verb"); return;
+ }
+ }
+ // This should make SkPath::getBounds() queries threadsafe.
+ path->updateBoundsCache();
+ fPaths[index] = path;
+ }
+}
+
+TestTypeface::TestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
+ : SkTypeface(style, false), fTestFont(std::move(testFont)) {}
+
+void TestTypeface::getAdvance(SkGlyph* glyph) {
+ SkGlyphID glyphID = glyph->getGlyphID();
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+
+ // TODO(benjaminwagner): Update users to use floats.
+ glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
+ glyph->fAdvanceY = 0;
+}
+
+void TestTypeface::getFontMetrics(SkFontMetrics* metrics) { *metrics = fTestFont->fMetrics; }
+
+void TestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+ *path = *fTestFont->fPaths[glyphID];
+}
+
+void TestTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ rec->setHinting(SkFontHinting::kNone);
+}
+
+void TestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
+ unsigned glyphCount = fTestFont->fCharCodesCount;
+ for (unsigned gid = 0; gid < glyphCount; ++gid) {
+ glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]);
+ }
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> TestTypeface::onGetAdvancedMetrics() const { // pdf only
+ std::unique_ptr<SkAdvancedTypefaceMetrics>info(new SkAdvancedTypefaceMetrics);
+ info->fFontName.set(fTestFont->fName);
+ return info;
+}
+
+void TestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ desc->setFamilyName(fTestFont->fName);
+ desc->setStyle(this->fontStyle());
+ *isLocal = false;
+}
+
+void TestTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
+ for (int i = 0; i < count; ++i) {
+ glyphs[i] = fTestFont->glyphForUnichar(uni[i]);
+ }
+}
+
+void TestTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fTestFont->fName; }
+
+SkTypeface::LocalizedStrings* TestTypeface::onCreateFamilyNameIterator() const {
+ SkString familyName(fTestFont->fName);
+ SkString language("und"); // undetermined
+ return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+}
+
+class SkTestScalerContext : public SkScalerContext {
+public:
+ SkTestScalerContext(sk_sp<TestTypeface> face,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : SkScalerContext(std::move(face), effects, desc) {
+ fRec.getSingleMatrix(&fMatrix);
+ this->forceGenerateImageFromPath();
+ }
+
+protected:
+ TestTypeface* getTestTypeface() const {
+ return static_cast<TestTypeface*>(this->getTypeface());
+ }
+
+ unsigned generateGlyphCount() override { return this->getTestTypeface()->onCountGlyphs(); }
+
+ bool generateAdvance(SkGlyph* glyph) override {
+ this->getTestTypeface()->getAdvance(glyph);
+
+ const SkVector advance =
+ fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
+ glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+ glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ return true;
+ }
+
+ void generateMetrics(SkGlyph* glyph) override {
+ glyph->zeroMetrics();
+ this->generateAdvance(glyph);
+ // Always generates from paths, so SkScalerContext::getMetrics will figure the bounds.
+ }
+
+ void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }
+
+ bool generatePath(SkGlyphID glyph, SkPath* path) override {
+ this->getTestTypeface()->getPath(glyph, path);
+ path->transform(fMatrix);
+ return true;
+ }
+
+ void generateFontMetrics(SkFontMetrics* metrics) override {
+ this->getTestTypeface()->getFontMetrics(metrics);
+ SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
+ }
+
+private:
+ SkMatrix fMatrix;
+};
+
+SkScalerContext* TestTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const {
+ return new SkTestScalerContext(sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
+}
diff --git a/src/third_party/skia/tools/fonts/TestTypeface.h b/src/third_party/skia/tools/fonts/TestTypeface.h
new file mode 100644
index 0000000..0d43d09
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/TestTypeface.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TestTypeface_DEFINED
+#define TestTypeface_DEFINED
+
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypeface.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkFixed.h"
+
+#include <memory>
+
+class SkDescriptor;
+class SkFontDescriptor;
+class SkGlyph;
+class SkPath;
+class SkScalerContext;
+class SkStreamAsset;
+class SkString;
+class SkTestFont;
+struct SkAdvancedTypefaceMetrics;
+struct SkScalerContextEffects;
+struct SkScalerContextRec;
+
+struct SkTestFontData {
+ const SkScalar* fPoints;
+ const unsigned char* fVerbs;
+ const SkUnichar* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkFontMetrics& fMetrics;
+ const char* fName;
+ SkFontStyle fStyle;
+};
+
+class SkTestFont : public SkRefCnt {
+public:
+ SkTestFont(const SkTestFontData&);
+ virtual ~SkTestFont();
+ SkGlyphID glyphForUnichar(SkUnichar charCode) const;
+ void init(const SkScalar* pts, const unsigned char* verbs);
+
+private:
+ const SkUnichar* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkFontMetrics& fMetrics;
+ const char* fName;
+ SkPath** fPaths;
+ friend class TestTypeface;
+ typedef SkRefCnt INHERITED;
+};
+
+class TestTypeface : public SkTypeface {
+public:
+ TestTypeface(sk_sp<SkTestFont>, const SkFontStyle& style);
+ void getAdvance(SkGlyph* glyph);
+ void getFontMetrics(SkFontMetrics* metrics);
+ void getPath(SkGlyphID glyph, SkPath* path);
+
+protected:
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor* desc) const override;
+ void onFilterRec(SkScalerContextRec* rec) const override;
+ void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+
+ std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override { return nullptr; }
+
+ sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
+ return sk_ref_sp(this);
+ }
+
+ void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
+
+ void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
+
+ int onCountGlyphs() const override { return (int)fTestFont->fCharCodesCount; }
+
+ void getPostScriptGlyphNames(SkString*) const override {}
+
+ int onGetUPEM() const override { return 2048; }
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override {
+ return 0;
+ }
+
+ int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const override {
+ return 0;
+ }
+
+ int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
+
+ size_t onGetTableData(SkFontTableTag tag,
+ size_t offset,
+ size_t length,
+ void* data) const override {
+ return 0;
+ }
+
+private:
+ sk_sp<SkTestFont> fTestFont;
+ friend class SkTestScalerContext;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/fonts/ToolUtilsFont.cpp b/src/third_party/skia/tools/fonts/ToolUtilsFont.cpp
new file mode 100644
index 0000000..ad68785
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/ToolUtilsFont.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/ToolUtils.h"
+
+#include "include/core/SkFontMgr.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkTypeface.h"
+#include "include/private/SkMutex.h"
+#include "src/core/SkOSFile.h"
+#include "src/utils/SkUTF.h"
+#include "tools/Resources.h"
+#include "tools/fonts/TestFontMgr.h"
+
+namespace ToolUtils {
+
+sk_sp<SkTypeface> planet_typeface() {
+ static const sk_sp<SkTypeface> planetTypeface = []() {
+ const char* filename;
+#if defined(SK_BUILD_FOR_WIN)
+ filename = "fonts/planetcolr.ttf";
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ filename = "fonts/planetsbix.ttf";
+#else
+ filename = "fonts/planetcbdt.ttf";
+#endif
+ sk_sp<SkTypeface> typeface = MakeResourceAsTypeface(filename);
+ if (typeface) {
+ return typeface;
+ }
+ return SkTypeface::MakeFromName("Planet", SkFontStyle());
+ }();
+ return planetTypeface;
+}
+
+sk_sp<SkTypeface> emoji_typeface() {
+ static const sk_sp<SkTypeface> emojiTypeface = []() {
+ const char* filename;
+#if defined(SK_BUILD_FOR_WIN)
+ filename = "fonts/colr.ttf";
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ filename = "fonts/sbix.ttf";
+#else
+ filename = "fonts/cbdt.ttf";
+#endif
+ sk_sp<SkTypeface> typeface = MakeResourceAsTypeface(filename);
+ if (typeface) {
+ return typeface;
+ }
+ return SkTypeface::MakeFromName("Emoji", SkFontStyle());
+ }();
+ return emojiTypeface;
+}
+
+const char* emoji_sample_text() {
+ return "\xF0\x9F\x98\x80"
+ " "
+ "\xE2\x99\xA2"; // 😀 ♢
+}
+static sk_sp<SkTypeface> create_font(const char* name, SkFontStyle style) {
+ static sk_sp<SkFontMgr> portableFontMgr = MakePortableFontMgr();
+ return portableFontMgr->legacyMakeTypeface(name, style);
+}
+
+sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style) {
+ return create_font(name, style);
+}
+} // namespace ToolUtils
diff --git a/src/third_party/skia/tools/fonts/create_test_font.cpp b/src/third_party/skia/tools/fonts/create_test_font.cpp
new file mode 100644
index 0000000..c303024
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/create_test_font.cpp
@@ -0,0 +1,423 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// Running create_test_font generates ./tools/fonts/test_font_index.inc
+// and ./tools/fonts/test_font_<generic name>.inc which are read by
+// ./tools/fonts/TestFontMgr.cpp
+
+#include "include/core/SkFont.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypeface.h"
+#include "include/private/SkTArray.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkSpan.h"
+#include "src/core/SkTSort.h"
+#include "src/utils/SkOSPath.h"
+#include "src/utils/SkUTF.h"
+
+#include <stdio.h>
+
+namespace {
+
+struct NamedFontStyle {
+ char const * const fName;
+ char const * const fIdentifierName;
+ SkFontStyle const fStyle;
+};
+
+struct FontDesc {
+ NamedFontStyle const fNamedStyle;
+ char const * const fFile;
+};
+
+struct FontFamilyDesc {
+ char const * const fGenericName;
+ char const * const fFamilyName;
+ char const * const fIdentifierName;
+ SkSpan<const FontDesc> const fFonts;
+};
+
+} // namespace
+
+static FILE* font_header(const char* family) {
+ SkString outPath(SkOSPath::Join(".", "tools"));
+ outPath = SkOSPath::Join(outPath.c_str(), "fonts");
+ outPath = SkOSPath::Join(outPath.c_str(), "test_font_");
+ SkString fam(family);
+ do {
+ int dashIndex = fam.find("-");
+ if (dashIndex < 0) {
+ break;
+ }
+ fam.writable_str()[dashIndex] = '_';
+ } while (true);
+ outPath.append(fam);
+ outPath.append(".inc");
+ FILE* out = fopen(outPath.c_str(), "w");
+
+ static const char kHeader[] =
+ "/*\n"
+ " * Copyright 2015 Google Inc.\n"
+ " *\n"
+ " * Use of this source code is governed by a BSD-style license that can be\n"
+ " * found in the LICENSE file.\n"
+ " */\n"
+ "\n"
+ "// Auto-generated by ";
+ fprintf(out, "%s%s\n\n", kHeader, SkOSPath::Basename(__FILE__).c_str());
+ return out;
+}
+
+enum {
+ kMaxLineLength = 80,
+};
+
+static ptrdiff_t last_line_length(const SkString& str) {
+ const char* first = str.c_str();
+ const char* last = first + str.size();
+ const char* ptr = last;
+ while (ptr > first && *--ptr != '\n')
+ ;
+ return last - ptr - 1;
+}
+
+static void output_fixed(SkScalar num, int emSize, SkString* out) {
+ int hex = (int) (num * 65536 / emSize);
+ out->appendf("0x%08x,", hex);
+ *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
+}
+
+static void output_scalar(SkScalar num, int emSize, SkString* out) {
+ num /= emSize;
+ if (num == (int) num) {
+ out->appendS32((int) num);
+ } else {
+ SkString str;
+ str.printf("%1.6g", num);
+ int width = (int) str.size();
+ const char* cStr = str.c_str();
+ while (cStr[width - 1] == '0') {
+ --width;
+ }
+ str.remove(width, str.size() - width);
+ out->appendf("%sf", str.c_str());
+ }
+ *out += ',';
+ *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
+}
+
+static int output_points(const SkPoint* pts, int emSize, int count, SkString* ptsOut) {
+ for (int index = 0; index < count; ++index) {
+ output_scalar(pts[index].fX, emSize, ptsOut);
+ output_scalar(pts[index].fY, emSize, ptsOut);
+ }
+ return count;
+}
+
+static void output_path_data(const SkFont& font,
+ int emSize, SkString* ptsOut, SkTDArray<SkPath::Verb>* verbs,
+ SkTDArray<unsigned>* charCodes, SkTDArray<SkScalar>* widths) {
+ for (SkUnichar index = 0x00; index < 0x7f; ++index) {
+ uint16_t glyphID = font.unicharToGlyph(index);
+ SkPath path;
+ font.getPath(glyphID, &path);
+ SkPath::RawIter iter(path);
+ SkPath::Verb verb;
+ SkPoint pts[4];
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ *verbs->append() = verb;
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ output_points(&pts[0], emSize, 1, ptsOut);
+ break;
+ case SkPath::kLine_Verb:
+ output_points(&pts[1], emSize, 1, ptsOut);
+ break;
+ case SkPath::kQuad_Verb:
+ output_points(&pts[1], emSize, 2, ptsOut);
+ break;
+ case SkPath::kCubic_Verb:
+ output_points(&pts[1], emSize, 3, ptsOut);
+ break;
+ case SkPath::kClose_Verb:
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ SkASSERT(0);
+ }
+ }
+ *verbs->append() = SkPath::kDone_Verb;
+ *charCodes->append() = index;
+ SkScalar width;
+ font.getWidths(&glyphID, 1, &width);
+ // SkASSERT(floor(width) == width); // not true for Hiragino Maru Gothic Pro
+ *widths->append() = width;
+ if (0 == index) {
+ index = 0x1f; // skip the rest of the control codes
+ }
+ }
+}
+
+static int offset_str_len(unsigned num) {
+ if (num == (unsigned) -1) {
+ return 10;
+ }
+ unsigned result = 1;
+ unsigned ref = 10;
+ while (ref <= num) {
+ ++result;
+ ref *= 10;
+ }
+ return result;
+}
+
+static SkString strip_final(const SkString& str) {
+ SkString result(str);
+ if (result.endsWith("\n")) {
+ result.remove(result.size() - 1, 1);
+ }
+ if (result.endsWith(" ")) {
+ result.remove(result.size() - 1, 1);
+ }
+ if (result.endsWith(",")) {
+ result.remove(result.size() - 1, 1);
+ }
+ return result;
+}
+
+static void output_font(sk_sp<SkTypeface> face, const char* identifier, FILE* out) {
+ const int emSize = face->getUnitsPerEm() * 2;
+ SkFont font;
+ font.setEdging(SkFont::Edging::kAntiAlias);
+ font.setSize(emSize);
+ font.setTypeface(std::move(face));
+
+ SkTDArray<SkPath::Verb> verbs;
+ SkTDArray<unsigned> charCodes;
+ SkTDArray<SkScalar> widths;
+ SkString ptsOut;
+ output_path_data(font, emSize, &ptsOut, &verbs, &charCodes, &widths);
+ fprintf(out, "const SkScalar %sPoints[] = {\n", identifier);
+ ptsOut = strip_final(ptsOut);
+ fprintf(out, "%s", ptsOut.c_str());
+ fprintf(out, "\n};\n\n");
+ fprintf(out, "const unsigned char %sVerbs[] = {\n", identifier);
+ int verbCount = verbs.count();
+ int outChCount = 0;
+ for (int index = 0; index < verbCount;) {
+ SkPath::Verb verb = verbs[index];
+ SkASSERT(verb >= SkPath::kMove_Verb && verb <= SkPath::kDone_Verb);
+ SkASSERT(SkTFitsIn<uint8_t>(verb));
+ fprintf(out, "%u", verb);
+ if (++index < verbCount) {
+ outChCount += 3;
+ fprintf(out, "%c", ',');
+ if (outChCount >= kMaxLineLength) {
+ outChCount = 0;
+ fprintf(out, "%c", '\n');
+ } else {
+ fprintf(out, "%c", ' ');
+ }
+ }
+ }
+ fprintf(out, "\n};\n\n");
+
+ // all fonts are now 0x00, 0x20 - 0xFE
+ // don't need to generate or output character codes?
+ fprintf(out, "const SkUnichar %sCharCodes[] = {\n", identifier);
+ int offsetCount = charCodes.count();
+ for (int index = 0; index < offsetCount;) {
+ unsigned offset = charCodes[index];
+ fprintf(out, "%u", offset);
+ if (++index < offsetCount) {
+ outChCount += offset_str_len(offset) + 2;
+ fprintf(out, "%c", ',');
+ if (outChCount >= kMaxLineLength) {
+ outChCount = 0;
+ fprintf(out, "%c", '\n');
+ } else {
+ fprintf(out, "%c", ' ');
+ }
+ }
+ }
+ fprintf(out, "\n};\n\n");
+
+ SkString widthsStr;
+ fprintf(out, "const SkFixed %sWidths[] = {\n", identifier);
+ for (int index = 0; index < offsetCount; ++index) {
+ output_fixed(widths[index], emSize, &widthsStr);
+ }
+ widthsStr = strip_final(widthsStr);
+ fprintf(out, "%s\n};\n\n", widthsStr.c_str());
+
+ fprintf(out, "const size_t %sCharCodesCount = SK_ARRAY_COUNT(%sCharCodes);\n\n",
+ identifier, identifier);
+
+ SkFontMetrics metrics;
+ font.getMetrics(&metrics);
+ fprintf(out, "const SkFontMetrics %sMetrics = {\n", identifier);
+ SkString metricsStr;
+ metricsStr.printf("0x%08x, ", metrics.fFlags);
+ output_scalar(metrics.fTop, emSize, &metricsStr);
+ output_scalar(metrics.fAscent, emSize, &metricsStr);
+ output_scalar(metrics.fDescent, emSize, &metricsStr);
+ output_scalar(metrics.fBottom, emSize, &metricsStr);
+ output_scalar(metrics.fLeading, emSize, &metricsStr);
+ output_scalar(metrics.fAvgCharWidth, emSize, &metricsStr);
+ output_scalar(metrics.fMaxCharWidth, emSize, &metricsStr);
+ output_scalar(metrics.fXMin, emSize, &metricsStr);
+ output_scalar(metrics.fXMax, emSize, &metricsStr);
+ output_scalar(metrics.fXHeight, emSize, &metricsStr);
+ output_scalar(metrics.fCapHeight, emSize, &metricsStr);
+ output_scalar(metrics.fUnderlineThickness, emSize, &metricsStr);
+ output_scalar(metrics.fUnderlinePosition, emSize, &metricsStr);
+ output_scalar(metrics.fStrikeoutThickness, emSize, &metricsStr);
+ output_scalar(metrics.fStrikeoutPosition, emSize, &metricsStr);
+ metricsStr = strip_final(metricsStr);
+ fprintf(out, "%s\n};\n\n", metricsStr.c_str());
+}
+
+static SkString identifier(const FontFamilyDesc& family, const FontDesc& font) {
+ SkString id(family.fIdentifierName);
+ id.append(font.fNamedStyle.fIdentifierName);
+ return id;
+}
+
+static void generate_fonts(const char* basepath, const SkSpan<const FontFamilyDesc>& families) {
+ FILE* out = nullptr;
+ for (const FontFamilyDesc& family : families) {
+ out = font_header(family.fGenericName);
+ for (const FontDesc& font : family.fFonts) {
+ SkString filepath(SkOSPath::Join(basepath, font.fFile));
+ SkASSERTF(sk_exists(filepath.c_str()), "The file %s does not exist.", filepath.c_str());
+ sk_sp<SkTypeface> resourceTypeface = SkTypeface::MakeFromFile(filepath.c_str());
+ SkASSERTF(resourceTypeface, "The file %s is not a font.", filepath.c_str());
+ output_font(std::move(resourceTypeface), identifier(family, font).c_str(), out);
+ }
+ fclose(out);
+ }
+}
+
+static const char* slant_to_string(SkFontStyle::Slant slant) {
+ switch (slant) {
+ case SkFontStyle::kUpright_Slant: return "SkFontStyle::kUpright_Slant";
+ case SkFontStyle::kItalic_Slant : return "SkFontStyle::kItalic_Slant" ;
+ case SkFontStyle::kOblique_Slant: return "SkFontStyle::kOblique_Slant";
+ default: SK_ABORT("Unknown slant");
+ }
+}
+
+static void generate_index(const SkSpan<const FontFamilyDesc>& families,
+ const FontDesc* defaultFont)
+{
+ FILE* out = font_header("index");
+ fprintf(out, "static SkTestFontData gTestFonts[] = {\n");
+ for (const FontFamilyDesc& family : families) {
+ for (const FontDesc& font : family.fFonts) {
+ SkString identifierStr = identifier(family, font);
+ const char* identifier = identifierStr.c_str();
+ const SkFontStyle& style = font.fNamedStyle.fStyle;
+ fprintf(out,
+ " { %sPoints, %sVerbs,\n"
+ " %sCharCodes, %sCharCodesCount, %sWidths,\n"
+ " %sMetrics, \"Toy %s\", SkFontStyle(%d,%d,%s)\n"
+ " },\n",
+ identifier, identifier,
+ identifier, identifier, identifier,
+ identifier, family.fFamilyName,
+ style.weight(), style.width(), slant_to_string(style.slant()));
+ }
+ }
+ fprintf(out, "};\n\n");
+ fprintf(out,
+ "struct SubFont {\n"
+ " const char* fFamilyName;\n"
+ " const char* fStyleName;\n"
+ " SkFontStyle fStyle;\n"
+ " SkTestFontData& fFont;\n"
+ " const char* fFile;\n"
+ "};\n\n"
+ "const SubFont gSubFonts[] = {\n");
+ int defaultIndex = -1;
+ int testFontsIndex = 0;
+ for (const FontFamilyDesc& family : families) {
+ for (const FontDesc& font : family.fFonts) {
+ if (&font == defaultFont) {
+ defaultIndex = testFontsIndex;
+ }
+ const SkFontStyle& style = font.fNamedStyle.fStyle;
+ fprintf(out,
+ " { \"%s\", \"%s\", SkFontStyle(%d,%d,%s), gTestFonts[%d], \"%s\" },\n",
+ family.fGenericName, font.fNamedStyle.fName,
+ style.weight(), style.width(), slant_to_string(style.slant()),
+ testFontsIndex, font.fFile);
+ testFontsIndex++;
+ }
+ }
+ testFontsIndex = 0;
+ for (const FontFamilyDesc& family : families) {
+ for (const FontDesc& font : family.fFonts) {
+ fprintf(out,
+ " { \"Toy %s\", \"%s\", SkFontStyle(%d,%d,%s), gTestFonts[%d], \"%s\" },\n",
+ family.fFamilyName, font.fNamedStyle.fName,
+ font.fNamedStyle.fStyle.weight(), font.fNamedStyle.fStyle.width(),
+ slant_to_string(font.fNamedStyle.fStyle.slant()), testFontsIndex, font.fFile);
+ testFontsIndex++;
+ }
+ }
+ fprintf(out, "};\n\n");
+ SkASSERT(defaultIndex >= 0);
+ fprintf(out, "const size_t gDefaultFontIndex = %d;\n", defaultIndex);
+ fclose(out);
+}
+
+int main(int , char * const []) {
+ constexpr NamedFontStyle normal = {"Normal", "Normal", SkFontStyle::Normal() };
+ constexpr NamedFontStyle bold = {"Bold", "Bold", SkFontStyle::Bold() };
+ constexpr NamedFontStyle italic = {"Italic", "Italic", SkFontStyle::Italic() };
+ constexpr NamedFontStyle bolditalic = {"Bold Italic", "BoldItalic", SkFontStyle::BoldItalic()};
+
+ static constexpr FontDesc kMonoFonts[] = {
+ {normal, "LiberationMono-Regular.ttf"},
+ {bold, "LiberationMono-Bold.ttf"},
+ {italic, "LiberationMono-Italic.ttf"},
+ {bolditalic, "LiberationMono-BoldItalic.ttf"},
+ };
+
+ static constexpr FontDesc kSansFonts[] = {
+ {normal, "LiberationSans-Regular.ttf"},
+ {bold, "LiberationSans-Bold.ttf"},
+ {italic, "LiberationSans-Italic.ttf"},
+ {bolditalic, "LiberationSans-BoldItalic.ttf"},
+ };
+
+ static constexpr FontDesc kSerifFonts[] = {
+ {normal, "LiberationSerif-Regular.ttf"},
+ {bold, "LiberationSerif-Bold.ttf"},
+ {italic, "LiberationSerif-Italic.ttf"},
+ {bolditalic, "LiberationSerif-BoldItalic.ttf"},
+ };
+
+ static constexpr FontFamilyDesc kFamiliesData[] = {
+ {"monospace", "Liberation Mono", "LiberationMono", SkMakeSpan(kMonoFonts)},
+ {"sans-serif", "Liberation Sans", "LiberationSans", SkMakeSpan(kSansFonts)},
+ {"serif", "Liberation Serif", "LiberationSerif", SkMakeSpan(kSerifFonts)},
+ };
+
+ static constexpr SkSpan<const FontFamilyDesc> kFamilies(SkMakeSpan(kFamiliesData));
+
+#ifdef SK_BUILD_FOR_UNIX
+ generate_fonts("/usr/share/fonts/truetype/liberation/", kFamilies);
+#else
+ generate_fonts("/Library/Fonts/", kFamilies);
+#endif
+ generate_index(kFamilies, &kFamilies[1].fFonts[0]);
+ return 0;
+}
diff --git a/src/third_party/skia/tools/fonts/create_test_font_color.cpp b/src/third_party/skia/tools/fonts/create_test_font_color.cpp
new file mode 100644
index 0000000..06d7431
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/create_test_font_color.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// running create_test_font_color generates ./<cbdt|sbix|cpal>.ttx
+// which are read by fonttools ttx to produce native fonts.
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/fonts/TestSVGTypeface.h"
+
+static void export_ttx(sk_sp<TestSVGTypeface> typeface,
+ SkString prefix,
+ SkSpan<unsigned> cbdtStrikeSizes,
+ SkSpan<unsigned> sbixStrikeSizes) {
+ SkFILEWStream cbdt((SkString(prefix) += "cbdt.ttx").c_str());
+ typeface->exportTtxCbdt(&cbdt, cbdtStrikeSizes);
+ cbdt.flush();
+ cbdt.fsync();
+
+ SkFILEWStream sbix((SkString(prefix) += "sbix.ttx").c_str());
+ typeface->exportTtxSbix(&sbix, sbixStrikeSizes);
+ sbix.flush();
+ sbix.fsync();
+
+ SkFILEWStream colr((SkString(prefix) += "colr.ttx").c_str());
+ typeface->exportTtxColr(&colr);
+ colr.flush();
+ colr.fsync();
+}
+
+int main(int argc, char** argv) {
+ CommandLineFlags::Parse(argc, argv);
+
+ // Most of the time use these sizes.
+ unsigned usual[] = { 16, 64, 128 };
+
+ // But the planet font cannot get very big in the size limited cbdt format.
+ unsigned small[] = { 8, 16 };
+
+ export_ttx(TestSVGTypeface::Default(), SkString(), SkMakeSpan(usual), SkMakeSpan(usual));
+ export_ttx(
+ TestSVGTypeface::Planets(), SkString("planet"), SkMakeSpan(small), SkMakeSpan(usual));
+
+ return 0;
+}
diff --git a/src/third_party/skia/tools/generate_fir_coeff.py b/src/third_party/skia/tools/fonts/generate_fir_coeff.py
similarity index 67%
rename from src/third_party/skia/tools/generate_fir_coeff.py
rename to src/third_party/skia/tools/fonts/generate_fir_coeff.py
index 70f521f..f5cc5e5 100644
--- a/src/third_party/skia/tools/generate_fir_coeff.py
+++ b/src/third_party/skia/tools/fonts/generate_fir_coeff.py
@@ -28,18 +28,26 @@
return (withinStdDev(b) - withinStdDev(a)) / 2;
-#We have a bunch of smudged samples which represent the average coverage of a range.
-#We have a 'center' which may not line up with those samples.
-#From the 'center' we want to make a normal approximation where '5' sample width out we're at '3' std deviations.
-#The first and last samples may not be fully covered.
+# We have some smudged samples which represent the average coverage of a range.
+# We have a 'center' which may not line up with those samples.
+# From center make a normal where 5 sample widths out is at 3 std deviations.
+# The first and last samples may not be fully covered.
-#This is the sub-sample shift for each set of FIR coefficients (the centers of the lcds in the samples)
-#Each subpxl takes up 1/3 of a pixel, so they are centered at x=(i/n+1/2n), or 1/6, 3/6, 5/6 of a pixel.
-#Each sample takes up 1/4 of a pixel, so the results fall at (x*4)%1, or 2/3, 0, 1/3 of a sample.
+# This is the sub-sample shift for each set of FIR coefficients
+# (the centers of the lcds in the samples)
+# Each subpxl takes up 1/3 of a pixel,
+# so they are centered at x=(i/n+1/2n), or 1/6, 3/6, 5/6 of a pixel.
+# Each sample takes up 1/4 of a pixel,
+# so the results fall at (x*4)%1, or 2/3, 0, 1/3 of a sample.
samples_per_pixel = 4
subpxls_per_pixel = 3
#sample_offsets is (frac, int) in sample units.
-sample_offsets = [math.modf((float(subpxl_index)/subpxls_per_pixel + 1.0/(2.0*subpxls_per_pixel))*samples_per_pixel) for subpxl_index in range(subpxls_per_pixel)]
+sample_offsets = [
+ math.modf(
+ (float(subpxl_index)/subpxls_per_pixel + 1.0/(2.0*subpxls_per_pixel))
+ * samples_per_pixel
+ ) for subpxl_index in range(subpxls_per_pixel)
+]
#How many samples to consider to the left and right of the subpxl center.
sample_units_width = 5
@@ -65,7 +73,9 @@
if current_sample_right > sample_offset + sample_units_width:
done = True
current_sample_right = sample_offset + sample_units_width
- current_std_dev_right = current_std_dev_left + ((current_sample_right - current_sample_left) / sample_units_width) * std_dev_max
+ current_std_dev_right = current_std_dev_left + (
+ (current_sample_right - current_sample_left) / sample_units_width
+ ) * std_dev_max
coverage = withinStdDevRange(current_std_dev_left, current_std_dev_right)
coeffs.append(coverage * target_sum)
@@ -74,15 +84,17 @@
current_sample_left = current_sample_right
current_std_dev_left = current_std_dev_right
- # Now we have the numbers we want, but our rounding needs to add up to target_sum.
+ # Have the numbers, but rounding needs to add up to target_sum.
delta = 0
coeffs_rounded_sum = sum(coeffs_rounded)
if coeffs_rounded_sum > target_sum:
- # The coeffs add up to too much. Subtract 1 from the ones which were rounded up the most.
+ # The coeffs add up to too much.
+ # Subtract 1 from the ones which were rounded up the most.
delta = -1
if coeffs_rounded_sum < target_sum:
- # The coeffs add up to too little. Add 1 to the ones which were rounded down the most.
+ # The coeffs add up to too little.
+ # Add 1 to the ones which were rounded down the most.
delta = 1
if delta:
@@ -102,18 +114,20 @@
coeff_pkg = [IndexTracker(i, diff) for i, diff in enumerate(coeff_diff)]
coeff_pkg.sort()
- # num_elements_to_force_round had better be < (2 * sample_units_width + 1) or
+ # num_elements_to_force_round better be < (2 * sample_units_width + 1) or
# * our math was wildy wrong
# * an awful lot of the curve is out side our sample
# either is pretty bad, and probably means the results will not be useful.
num_elements_to_force_round = abs(coeffs_rounded_sum - target_sum)
for i in xrange(num_elements_to_force_round):
- print "Adding %d to index %d to force round %f." % (delta, coeff_pkg[i].index, coeffs[coeff_pkg[i].index])
+ print "Adding %d to index %d to force round %f." % (
+ delta, coeff_pkg[i].index, coeffs[coeff_pkg[i].index])
coeffs_rounded[coeff_pkg[i].index] += delta
print "Prepending %d 0x00 for allignment." % (sample_align,)
coeffs_rounded_aligned = ([0] * int(sample_align)) + coeffs_rounded
- print ', '.join(["0x%0.2X" % coeff_rounded for coeff_rounded in coeffs_rounded_aligned])
+ print ', '.join(["0x%0.2X" % coeff_rounded
+ for coeff_rounded in coeffs_rounded_aligned])
print sum(coeffs), hex(sum(coeffs_rounded))
print
diff --git a/src/third_party/skia/tools/fonts/test_font_index.inc b/src/third_party/skia/tools/fonts/test_font_index.inc
new file mode 100644
index 0000000..0a3a979
--- /dev/null
+++ b/src/third_party/skia/tools/fonts/test_font_index.inc
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// Auto-generated by create_test_font.cpp
+
+static SkTestFontData gTestFonts[] = {
+ { LiberationMonoNormalPoints, LiberationMonoNormalVerbs,
+ LiberationMonoNormalCharCodes, LiberationMonoNormalCharCodesCount, LiberationMonoNormalWidths,
+ LiberationMonoNormalMetrics, "Toy Liberation Mono", SkFontStyle(400,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationMonoBoldPoints, LiberationMonoBoldVerbs,
+ LiberationMonoBoldCharCodes, LiberationMonoBoldCharCodesCount, LiberationMonoBoldWidths,
+ LiberationMonoBoldMetrics, "Toy Liberation Mono", SkFontStyle(700,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationMonoItalicPoints, LiberationMonoItalicVerbs,
+ LiberationMonoItalicCharCodes, LiberationMonoItalicCharCodesCount, LiberationMonoItalicWidths,
+ LiberationMonoItalicMetrics, "Toy Liberation Mono", SkFontStyle(400,5,SkFontStyle::kItalic_Slant)
+ },
+ { LiberationMonoBoldItalicPoints, LiberationMonoBoldItalicVerbs,
+ LiberationMonoBoldItalicCharCodes, LiberationMonoBoldItalicCharCodesCount, LiberationMonoBoldItalicWidths,
+ LiberationMonoBoldItalicMetrics, "Toy Liberation Mono", SkFontStyle(700,5,SkFontStyle::kItalic_Slant)
+ },
+ { LiberationSansNormalPoints, LiberationSansNormalVerbs,
+ LiberationSansNormalCharCodes, LiberationSansNormalCharCodesCount, LiberationSansNormalWidths,
+ LiberationSansNormalMetrics, "Toy Liberation Sans", SkFontStyle(400,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationSansBoldPoints, LiberationSansBoldVerbs,
+ LiberationSansBoldCharCodes, LiberationSansBoldCharCodesCount, LiberationSansBoldWidths,
+ LiberationSansBoldMetrics, "Toy Liberation Sans", SkFontStyle(700,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationSansItalicPoints, LiberationSansItalicVerbs,
+ LiberationSansItalicCharCodes, LiberationSansItalicCharCodesCount, LiberationSansItalicWidths,
+ LiberationSansItalicMetrics, "Toy Liberation Sans", SkFontStyle(400,5,SkFontStyle::kItalic_Slant)
+ },
+ { LiberationSansBoldItalicPoints, LiberationSansBoldItalicVerbs,
+ LiberationSansBoldItalicCharCodes, LiberationSansBoldItalicCharCodesCount, LiberationSansBoldItalicWidths,
+ LiberationSansBoldItalicMetrics, "Toy Liberation Sans", SkFontStyle(700,5,SkFontStyle::kItalic_Slant)
+ },
+ { LiberationSerifNormalPoints, LiberationSerifNormalVerbs,
+ LiberationSerifNormalCharCodes, LiberationSerifNormalCharCodesCount, LiberationSerifNormalWidths,
+ LiberationSerifNormalMetrics, "Toy Liberation Serif", SkFontStyle(400,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationSerifBoldPoints, LiberationSerifBoldVerbs,
+ LiberationSerifBoldCharCodes, LiberationSerifBoldCharCodesCount, LiberationSerifBoldWidths,
+ LiberationSerifBoldMetrics, "Toy Liberation Serif", SkFontStyle(700,5,SkFontStyle::kUpright_Slant)
+ },
+ { LiberationSerifItalicPoints, LiberationSerifItalicVerbs,
+ LiberationSerifItalicCharCodes, LiberationSerifItalicCharCodesCount, LiberationSerifItalicWidths,
+ LiberationSerifItalicMetrics, "Toy Liberation Serif", SkFontStyle(400,5,SkFontStyle::kItalic_Slant)
+ },
+ { LiberationSerifBoldItalicPoints, LiberationSerifBoldItalicVerbs,
+ LiberationSerifBoldItalicCharCodes, LiberationSerifBoldItalicCharCodesCount, LiberationSerifBoldItalicWidths,
+ LiberationSerifBoldItalicMetrics, "Toy Liberation Serif", SkFontStyle(700,5,SkFontStyle::kItalic_Slant)
+ },
+};
+
+struct SubFont {
+ const char* fFamilyName;
+ const char* fStyleName;
+ SkFontStyle fStyle;
+ SkTestFontData& fFont;
+ const char* fFile;
+};
+
+const SubFont gSubFonts[] = {
+ { "monospace", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[0], "LiberationMono-Regular.ttf" },
+ { "monospace", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[1], "LiberationMono-Bold.ttf" },
+ { "monospace", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[2], "LiberationMono-Italic.ttf" },
+ { "monospace", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[3], "LiberationMono-BoldItalic.ttf" },
+ { "sans-serif", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[4], "LiberationSans-Regular.ttf" },
+ { "sans-serif", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[5], "LiberationSans-Bold.ttf" },
+ { "sans-serif", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[6], "LiberationSans-Italic.ttf" },
+ { "sans-serif", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[7], "LiberationSans-BoldItalic.ttf" },
+ { "serif", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[8], "LiberationSerif-Regular.ttf" },
+ { "serif", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[9], "LiberationSerif-Bold.ttf" },
+ { "serif", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[10], "LiberationSerif-Italic.ttf" },
+ { "serif", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[11], "LiberationSerif-BoldItalic.ttf" },
+ { "Toy Liberation Mono", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[0], "LiberationMono-Regular.ttf" },
+ { "Toy Liberation Mono", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[1], "LiberationMono-Bold.ttf" },
+ { "Toy Liberation Mono", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[2], "LiberationMono-Italic.ttf" },
+ { "Toy Liberation Mono", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[3], "LiberationMono-BoldItalic.ttf" },
+ { "Toy Liberation Sans", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[4], "LiberationSans-Regular.ttf" },
+ { "Toy Liberation Sans", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[5], "LiberationSans-Bold.ttf" },
+ { "Toy Liberation Sans", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[6], "LiberationSans-Italic.ttf" },
+ { "Toy Liberation Sans", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[7], "LiberationSans-BoldItalic.ttf" },
+ { "Toy Liberation Serif", "Normal", SkFontStyle(400,5,SkFontStyle::kUpright_Slant), gTestFonts[8], "LiberationSerif-Regular.ttf" },
+ { "Toy Liberation Serif", "Bold", SkFontStyle(700,5,SkFontStyle::kUpright_Slant), gTestFonts[9], "LiberationSerif-Bold.ttf" },
+ { "Toy Liberation Serif", "Italic", SkFontStyle(400,5,SkFontStyle::kItalic_Slant), gTestFonts[10], "LiberationSerif-Italic.ttf" },
+ { "Toy Liberation Serif", "Bold Italic", SkFontStyle(700,5,SkFontStyle::kItalic_Slant), gTestFonts[11], "LiberationSerif-BoldItalic.ttf" },
+};
+
+const size_t gDefaultFontIndex = 4;
diff --git a/src/third_party/skia/tools/test_font_monospace.inc b/src/third_party/skia/tools/fonts/test_font_monospace.inc
similarity index 99%
rename from src/third_party/skia/tools/test_font_monospace.inc
rename to src/third_party/skia/tools/fonts/test_font_monospace.inc
index 4b14dc6..bb87f93 100644
--- a/src/third_party/skia/tools/test_font_monospace.inc
+++ b/src/third_party/skia/tools/fonts/test_font_monospace.inc
@@ -1164,7 +1164,7 @@
2, 1, 2, 2, 5, 6
};
-const unsigned LiberationMonoNormalCharCodes[] = {
+const SkUnichar LiberationMonoNormalCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
@@ -1190,11 +1190,11 @@
0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
};
-const int LiberationMonoNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoNormalCharCodes);
+const size_t LiberationMonoNormalCharCodesCount = SK_ARRAY_COUNT(LiberationMonoNormalCharCodes);
-const SkPaint::FontMetrics LiberationMonoNormalMetrics = {
-0x30307833, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.633301f, 0.00989532f,
--0.0244141f, 0.608887f, 0.538086f, 0.0104446f, 0.0410156f, 0.23291f
+const SkFontMetrics LiberationMonoNormalMetrics = {
+0x0000000f, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.600098f, 0.633301f, -0.0244141f,
+0.608887f, 0.52832f, 0.658691f, 0.0410156f, 0.23291f, 0.0498047f, -0.258789f
};
const SkScalar LiberationMonoBoldPoints[] = {
@@ -2314,7 +2314,7 @@
2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationMonoBoldCharCodes[] = {
+const SkUnichar LiberationMonoBoldCharCodes[] = {
0, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
@@ -2340,11 +2340,11 @@
0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
};
-const int LiberationMonoBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoBoldCharCodes);
+const size_t LiberationMonoBoldCharCodesCount = SK_ARRAY_COUNT(LiberationMonoBoldCharCodes);
-const SkPaint::FontMetrics LiberationMonoBoldMetrics = {
-0x30307833, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.641602f, 0.010025f, -0.0268555f,
-0.614746f, 0.538086f, 0.0104446f, 0.100098f, 0.23291f
+const SkFontMetrics LiberationMonoBoldMetrics = {
+0x0000000f, -0.833496f, -0.833496f, 0.300293f, 0.300293f, 0, 0.600098f, 0.641602f, -0.0268555f,
+0.614746f, 0.52832f, 0.658691f, 0.100098f, 0.23291f, 0.0498047f, -0.258789f
};
const SkScalar LiberationMonoItalicPoints[] = {
@@ -3580,7 +3580,7 @@
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 5, 6
};
-const unsigned LiberationMonoItalicCharCodes[] = {
+const SkUnichar LiberationMonoItalicCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
@@ -3606,11 +3606,11 @@
0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
};
-const int LiberationMonoItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoItalicCharCodes);
+const size_t LiberationMonoItalicCharCodesCount = SK_ARRAY_COUNT(LiberationMonoItalicCharCodes);
-const SkPaint::FontMetrics LiberationMonoItalicMetrics = {
-0x30307833, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.798828f, 0.0124817f,
--0.0942383f, 0.70459f, 0.538086f, 0.0104446f, 0.0410156f, 0.23291f
+const SkFontMetrics LiberationMonoItalicMetrics = {
+0x0000000f, -0.833496f, -0.833496f, 0.300293f, 0.300293f, 0, 0.600098f, 0.798828f, -0.0942383f,
+0.70459f, 0.52832f, 0.658691f, 0.0410156f, 0.23291f, 0.0498047f, -0.258789f
};
const SkScalar LiberationMonoBoldItalicPoints[] = {
@@ -4813,7 +4813,7 @@
2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationMonoBoldItalicCharCodes[] = {
+const SkUnichar LiberationMonoBoldItalicCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
@@ -4839,9 +4839,10 @@
0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
};
-const int LiberationMonoBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoBoldItalicCharCodes);
+const size_t LiberationMonoBoldItalicCharCodesCount = SK_ARRAY_COUNT(LiberationMonoBoldItalicCharCodes);
-const SkPaint::FontMetrics LiberationMonoBoldItalicMetrics = {
-0x30307833, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.791992f, 0.0123749f,
--0.0942383f, 0.697754f, 0.538086f, 0.0104446f, 0.100098f, 0.23291f
+const SkFontMetrics LiberationMonoBoldItalicMetrics = {
+0x0000000f, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.600098f, 0.791992f, -0.0942383f,
+0.697754f, 0.52832f, 0.658691f, 0.100098f, 0.23291f, 0.0498047f, -0.258789f
};
+
diff --git a/src/third_party/skia/tools/test_font_sans_serif.inc b/src/third_party/skia/tools/fonts/test_font_sans_serif.inc
similarity index 99%
rename from src/third_party/skia/tools/test_font_sans_serif.inc
rename to src/third_party/skia/tools/fonts/test_font_sans_serif.inc
index b0d433d..b53da19 100644
--- a/src/third_party/skia/tools/test_font_sans_serif.inc
+++ b/src/third_party/skia/tools/fonts/test_font_sans_serif.inc
@@ -1158,7 +1158,7 @@
2, 2, 2, 5, 6
};
-const unsigned LiberationSansNormalCharCodes[] = {
+const SkUnichar LiberationSansNormalCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
@@ -1184,11 +1184,11 @@
0x00008000, 0x00005580, 0x00004280, 0x00005580, 0x00009580
};
-const int LiberationSansNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansNormalCharCodes);
+const size_t LiberationSansNormalCharCodesCount = SK_ARRAY_COUNT(LiberationSansNormalCharCodes);
-const SkPaint::FontMetrics LiberationSansNormalMetrics = {
-0x30307833, -0.910156f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.25342f, 0.0195847f,
--0.203125f, 1.05029f, 0.538086f, 0.0109024f, 0.0732422f, 0.105957f
+const SkFontMetrics LiberationSansNormalMetrics = {
+0x0000000f, -0.910156f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.589355f, 1.25342f,
+-0.203125f, 1.05029f, 0.52832f, 0.687988f, 0.0732422f, 0.105957f, 0.0498047f, -0.258789f
};
const SkScalar LiberationSansBoldPoints[] = {
@@ -2321,7 +2321,7 @@
0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSansBoldCharCodes[] = {
+const SkUnichar LiberationSansBoldCharCodes[] = {
0,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
@@ -2348,11 +2348,11 @@
0x00008000, 0x000063a0, 0x000047a0, 0x000063a0, 0x00009580
};
-const int LiberationSansBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansBoldCharCodes);
+const size_t LiberationSansBoldCharCodesCount = SK_ARRAY_COUNT(LiberationSansBoldCharCodes);
-const SkPaint::FontMetrics LiberationSansBoldMetrics = {
-0x30307833, -1.0332f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.24609f, 0.0194702f,
--0.184082f, 1.06201f, 0.538086f, 0.0109024f, 0.10498f, 0.105957f
+const SkFontMetrics LiberationSansBoldMetrics = {
+0x0000000f, -1.0332f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.612305f, 1.24609f,
+-0.184082f, 1.06201f, 0.52832f, 0.687988f, 0.10498f, 0.105957f, 0.0498047f, -0.258789f
};
const SkScalar LiberationSansItalicPoints[] = {
@@ -3563,7 +3563,7 @@
2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSansItalicCharCodes[] = {
+const SkUnichar LiberationSansItalicCharCodes[] = {
0, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
@@ -3589,11 +3589,11 @@
0x00008000, 0x00005580, 0x00004280, 0x00005580, 0x00009580
};
-const int LiberationSansItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansItalicCharCodes);
+const size_t LiberationSansItalicCharCodesCount = SK_ARRAY_COUNT(LiberationSansItalicCharCodes);
-const SkPaint::FontMetrics LiberationSansItalicMetrics = {
-0x30307833, -1.01416f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.33447f, 0.0208511f,
--0.271973f, 1.0625f, 0.537598f, 0.0109024f, 0.0732422f, 0.105957f
+const SkFontMetrics LiberationSansItalicMetrics = {
+0x0000000f, -1.01416f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.590332f, 1.33447f,
+-0.271973f, 1.0625f, 0.52832f, 0.687988f, 0.0732422f, 0.105957f, 0.0498047f, -0.258789f
};
const SkScalar LiberationSansBoldItalicPoints[] = {
@@ -4823,7 +4823,7 @@
2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSansBoldItalicCharCodes[] = {
+const SkUnichar LiberationSansBoldItalicCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
@@ -4849,9 +4849,10 @@
0x00008000, 0x000063a0, 0x000047a0, 0x000063a0, 0x00009580
};
-const int LiberationSansBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansBoldItalicCharCodes);
+const size_t LiberationSansBoldItalicCharCodesCount = SK_ARRAY_COUNT(LiberationSansBoldItalicCharCodes);
-const SkPaint::FontMetrics LiberationSansBoldItalicMetrics = {
-0x30307833, -1.02979f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.3374f, 0.0208969f,
--0.208984f, 1.12842f, 0.537598f, 0.0109024f, 0.10498f, 0.105957f
+const SkFontMetrics LiberationSansBoldItalicMetrics = {
+0x0000000f, -1.02979f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.61377f, 1.3374f,
+-0.208984f, 1.12842f, 0.52832f, 0.687988f, 0.10498f, 0.105957f, 0.0498047f, -0.258789f
};
+
diff --git a/src/third_party/skia/tools/test_font_serif.inc b/src/third_party/skia/tools/fonts/test_font_serif.inc
similarity index 99%
rename from src/third_party/skia/tools/test_font_serif.inc
rename to src/third_party/skia/tools/fonts/test_font_serif.inc
index 49279ce..816e094 100644
--- a/src/third_party/skia/tools/test_font_serif.inc
+++ b/src/third_party/skia/tools/fonts/test_font_serif.inc
@@ -1235,7 +1235,7 @@
2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSerifNormalCharCodes[] = {
+const SkUnichar LiberationSerifNormalCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
@@ -1261,11 +1261,11 @@
0x000071a0, 0x00007ae0, 0x00003340, 0x00007ae0, 0x00008a80
};
-const int LiberationSerifNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifNormalCharCodes);
+const size_t LiberationSerifNormalCharCodesCount = SK_ARRAY_COUNT(LiberationSerifNormalCharCodes);
-const SkPaint::FontMetrics LiberationSerifNormalMetrics = {
-0x30307833, -0.981445f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 1.18359f, 0.0184937f,
--0.176758f, 1.00684f, 0.469727f, 0.0103607f, 0.0488281f, 0.108887f
+const SkFontMetrics LiberationSerifNormalMetrics = {
+0x0000000f, -0.981445f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.567383f, 1.18359f,
+-0.176758f, 1.00684f, 0.458984f, 0.654785f, 0.0488281f, 0.108887f, 0.0488281f, -0.205078f
};
const SkScalar LiberationSerifBoldPoints[] = {
@@ -2485,7 +2485,7 @@
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSerifBoldCharCodes[] = {
+const SkUnichar LiberationSerifBoldCharCodes[] = {
0, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
@@ -2511,11 +2511,11 @@
0x000071a0, 0x000064e0, 0x00003860, 0x000064e0, 0x00008520
};
-const int LiberationSerifBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifBoldCharCodes);
+const size_t LiberationSerifBoldCharCodesCount = SK_ARRAY_COUNT(LiberationSerifBoldCharCodes);
-const SkPaint::FontMetrics LiberationSerifBoldMetrics = {
-0x30307833, -1.00781f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 1.26709f, 0.0197983f,
--0.182129f, 1.08496f, 0.469727f, 0.0103607f, 0.0952148f, 0.108887f
+const SkFontMetrics LiberationSerifBoldMetrics = {
+0x0000000f, -1.00781f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.59375f, 1.26709f,
+-0.182129f, 1.08496f, 0.458984f, 0.654785f, 0.0952148f, 0.108887f, 0.0498047f, -0.258789f
};
const SkScalar LiberationSerifItalicPoints[] = {
@@ -3803,7 +3803,7 @@
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSerifItalicCharCodes[] = {
+const SkUnichar LiberationSerifItalicCharCodes[] = {
0, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
@@ -3829,11 +3829,11 @@
0x000063a0, 0x00006660, 0x00004660, 0x00006660, 0x00008a80
};
-const int LiberationSerifItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifItalicCharCodes);
+const size_t LiberationSerifItalicCharCodesCount = SK_ARRAY_COUNT(LiberationSerifItalicCharCodes);
-const SkPaint::FontMetrics LiberationSerifItalicMetrics = {
-0x30307833, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 1.26465f, 0.0197601f,
--0.176758f, 1.08789f, 0.469727f, 0.0103607f, 0.0488281f, 0.108887f
+const SkFontMetrics LiberationSerifItalicMetrics = {
+0x0000000f, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.559082f, 1.26465f,
+-0.176758f, 1.08789f, 0.458984f, 0.654785f, 0.0488281f, 0.108887f, 0.0498047f, -0.258789f
};
const SkScalar LiberationSerifBoldItalicPoints[] = {
@@ -5115,7 +5115,7 @@
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6
};
-const unsigned LiberationSerifBoldItalicCharCodes[] = {
+const SkUnichar LiberationSerifBoldItalicCharCodes[] = {
0, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
@@ -5141,9 +5141,10 @@
0x000063a0, 0x00005920, 0x00003860, 0x00005920, 0x000091e0
};
-const int LiberationSerifBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifBoldItalicCharCodes);
+const size_t LiberationSerifBoldItalicCharCodesCount = SK_ARRAY_COUNT(LiberationSerifBoldItalicCharCodes);
-const SkPaint::FontMetrics LiberationSerifBoldItalicMetrics = {
-0x30307833, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 1.32861f, 0.0207596f,
--0.178223f, 1.15039f, 0.469727f, 0.0103607f, 0.0952148f, 0.108887f
+const SkFontMetrics LiberationSerifBoldItalicMetrics = {
+0x0000000f, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.578125f, 1.32861f,
+-0.178223f, 1.15039f, 0.458984f, 0.654785f, 0.0952148f, 0.108887f, 0.0498047f, -0.258789f
};
+
diff --git a/src/third_party/skia/tools/force_older_glibc_math.h b/src/third_party/skia/tools/force_older_glibc_math.h
new file mode 100644
index 0000000..bf8b778
--- /dev/null
+++ b/src/third_party/skia/tools/force_older_glibc_math.h
@@ -0,0 +1,10 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#pragma once
+
+// GLIBC_2.27 has new implementations of expf, powf, log2f, exp2f that are pretty nifty,
+// but that's not very helpful if you're using an older glibc that doesn't ship those.
+__asm__(".symver expf,expf@GLIBC_2.4");
+__asm__(".symver powf,powf@GLIBC_2.4");
+__asm__(".symver log2f,log2f@GLIBC_2.4");
+__asm__(".symver exp2f,exp2f@GLIBC_2.4");
diff --git a/src/third_party/skia/tools/gdb/bitmap.py b/src/third_party/skia/tools/gdb/bitmap.py
new file mode 100644
index 0000000..3df079d
--- /dev/null
+++ b/src/third_party/skia/tools/gdb/bitmap.py
@@ -0,0 +1,88 @@
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Visualize bitmaps in gdb.
+
+(gdb) source <path to this file>
+(gdb) sk_bitmap <symbol>
+
+This should pop up a window with the bitmap displayed.
+Right clicking should bring up a menu, allowing the
+bitmap to be saved to a file.
+"""
+
+import gdb
+from enum import Enum
+try:
+ from PIL import Image
+except ImportError:
+ import Image
+
+class ColorType(Enum):
+ unknown = 0
+ alpha_8 = 1
+ rgb_565 = 2
+ argb_4444 = 3
+ rgba_8888 = 4
+ rgbx_8888 = 5
+ bgra_8888 = 6
+ rgba_1010102 = 7
+ rgb_101010x = 8
+ gray_8 = 9
+ rgba_F16 = 10
+
+class AlphaType(Enum):
+ unknown = 0
+ opaque = 1
+ premul = 2
+ unpremul = 3
+
+class sk_bitmap(gdb.Command):
+ """Displays the content of an SkBitmap image."""
+
+ def __init__(self):
+ super(sk_bitmap, self).__init__('sk_bitmap',
+ gdb.COMMAND_SUPPORT,
+ gdb.COMPLETE_FILENAME)
+
+ def invoke(self, arg, from_tty):
+ frame = gdb.selected_frame()
+ val = frame.read_var(arg)
+ if str(val.type.strip_typedefs()) == 'SkBitmap':
+ pixmap = val['fPixmap']
+ pixels = pixmap['fPixels']
+ row_bytes = pixmap['fRowBytes']
+ info = pixmap['fInfo']
+ dimensions = info['fDimensions']
+ width = dimensions['fWidth']
+ height = dimensions['fHeight']
+ color_type = info['fColorType']
+ alpha_type = info['fAlphaType']
+
+ process = gdb.selected_inferior()
+ memory_data = process.read_memory(pixels, row_bytes * height)
+ size = (width, height)
+ image = None
+ # See Unpack.c for the values understood after the "raw" parameter.
+ if color_type == ColorType.bgra_8888.value:
+ if alpha_type == AlphaType.unpremul.value:
+ image = Image.frombytes("RGBA", size, memory_data,
+ "raw", "BGRA", row_bytes, 1)
+ elif alpha_type == AlphaType.premul.value:
+ # RGBA instead of RGBa, because Image.show() doesn't work with RGBa.
+ image = Image.frombytes("RGBA", size, memory_data,
+ "raw", "BGRa", row_bytes, 1)
+
+ if image:
+ # Fails on premultiplied alpha, it cannot convert to RGB.
+ image.show()
+ else:
+ print ("Need to add support for %s %s." % (
+ str(ColorType(int(color_type))),
+ str(AlphaType(int(alpha_type)))
+ ))
+
+sk_bitmap()
diff --git a/src/third_party/skia/tools/generate_vk_interface.sh b/src/third_party/skia/tools/generate_vk_interface.sh
deleted file mode 100644
index 84eaee3..0000000
--- a/src/third_party/skia/tools/generate_vk_interface.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2015 Google Inc. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-headerLoc=../third_party/vulkan/vulkan.h
-outFile=tempVkInterface
-
-if [ ! -e "$outFile" ] ; then
- echo 'I AM HERE'
- touch "$outFile"
-fi
-
-chmod 700 $outFile
-
-echo '// *******************************************' > $outFile
-echo '// Place these lines into GrVkInterface.cpp::validate' >> $outFile
-echo '// *******************************************' >> $outFile
-sed -n 's/^VKAPI_ATTR \(VkResult\|void\) VKAPI_CALL vk\([a-zA-Z]*\).*/NULL == fFunctions.f\2 ||/p' $headerLoc >> $outFile
-sed -i '1,/NULL/ s/^NULL/if (NULL/' $outFile
-sed -i '5,$ s/^/ /' $outFile
-sed -i '$ s/ ||/) {/' $outFile
-
-echo '' >> $outFile
-echo '// *******************************************' >> $outFile
-echo '// Place these lines into GrVkInterface.h' >> $outFile
-echo '// *******************************************' >> $outFile
-sed -n 's/^VKAPI_ATTR \(VkResult\|void\) VKAPI_CALL vk\([a-zA-Z]*\).*/VkPtr<PFN_vk\2> f\2;/p' $headerLoc >> $outFile
-
-echo '' >> $outFile
-echo '// *******************************************' >> $outFile
-echo '// Place these lines into GrVkInterface.cpp::GrVKCreateInterface' >> $outFile
-echo '// *******************************************' >> $outFile
-sed -n 's/^VKAPI_ATTR \(VkResult\|void\) VKAPI_CALL vk\([a-zA-Z]*\).*/GET_PROC(\2);/p' $headerLoc >> $outFile
-
diff --git a/src/third_party/skia/tools/get_current_monitor_profile.cpp b/src/third_party/skia/tools/get_current_monitor_profile.cpp
index 55a96d5..9f2bd3c 100644
--- a/src/third_party/skia/tools/get_current_monitor_profile.cpp
+++ b/src/third_party/skia/tools/get_current_monitor_profile.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "SkStream.h"
+#include "include/core/SkStream.h"
#if defined(SK_BUILD_FOR_MAC)
#include <ApplicationServices/ApplicationServices.h>
@@ -19,10 +19,10 @@
CFDataRef dataRef = CGColorSpaceCopyICCProfile(cs);
const uint8_t* data = CFDataGetBytePtr(dataRef);
size_t size = CFDataGetLength(dataRef);
-
+
SkFILEWStream file("monitor_0.icc");
file.write(data, size);
-
+
CFRelease(cs);
CFRelease(dataRef);
return 0;
diff --git a/src/third_party/skia/tools/get_images_from_skps.cpp b/src/third_party/skia/tools/get_images_from_skps.cpp
index 0debe36..a75d47f 100644
--- a/src/third_party/skia/tools/get_images_from_skps.cpp
+++ b/src/third_party/skia/tools/get_images_from_skps.cpp
@@ -5,32 +5,32 @@
* found in the LICENSE file.
*/
-#include "SkBitmap.h"
-#include "SkCodec.h"
-#include "SkColorSpace.h"
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkJSONCPP.h"
-#include "SkMD5.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkPicture.h"
-#include "SkPixelSerializer.h"
-#include "SkStream.h"
-#include "SkTHash.h"
-
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkData.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkSerialProcs.h"
+#include "include/core/SkStream.h"
+#include "include/private/SkTHash.h"
+#include "src/core/SkMD5.h"
+#include "src/core/SkOSFile.h"
+#include "src/utils/SkJSONWriter.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/flags/CommandLineFlags.h"
#include <iostream>
#include <map>
-DEFINE_string2(skps, s, "skps", "A path to a directory of skps or a single skp.");
-DEFINE_string2(out, o, "img-out", "A path to an output directory.");
-DEFINE_bool(testDecode, false, "Indicates if we want to test that the images decode successfully.");
-DEFINE_bool(writeImages, true,
- "Indicates if we want to write out supported/decoded images.");
-DEFINE_bool(writeFailedImages, false,
- "Indicates if we want to write out unsupported/failed to decode images.");
-DEFINE_string2(failuresJsonPath, j, "",
+static DEFINE_string2(skps, s, "skps", "A path to a directory of skps or a single skp.");
+static DEFINE_string2(out, o, "img-out", "A path to an output directory.");
+static DEFINE_bool(testDecode, false,
+ "Indicates if we want to test that the images decode successfully.");
+static DEFINE_bool(writeImages, true,
+ "Indicates if we want to write out supported/decoded images.");
+static DEFINE_bool(writeFailedImages, false,
+ "Indicates if we want to write out unsupported/failed to decode images.");
+static DEFINE_string2(failuresJsonPath, j, "",
"Dump SKP and count of unknown images to the specified JSON file. Will not be "
"written anywhere if empty.");
@@ -41,7 +41,7 @@
static SkTHashSet<SkMD5::Digest> gSeen;
-struct Sniffer : public SkPixelSerializer {
+struct Sniffer {
std::string skpName;
@@ -52,8 +52,7 @@
void sniff(const void* ptr, size_t len) {
SkMD5 md5;
md5.write(ptr, len);
- SkMD5::Digest digest;
- md5.finish(digest);
+ SkMD5::Digest digest = md5.finish();
if (gSeen.contains(digest)) {
return;
@@ -61,7 +60,7 @@
gSeen.add(digest);
sk_sp<SkData> data(SkData::MakeWithoutCopy(ptr, len));
- std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
+ std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
if (!codec) {
// FIXME: This code is currently unreachable because we create an empty generator when
// we fail to create a codec.
@@ -122,38 +121,32 @@
gKnown++;
}
-
- bool onUseEncodedData(const void* ptr, size_t len) override {
- this->sniff(ptr, len);
- return true;
- }
- SkData* onEncode(const SkPixmap&) override { return nullptr; }
};
static bool get_images_from_file(const SkString& file) {
- auto stream = SkStream::MakeFromFile(file.c_str());
- sk_sp<SkPicture> picture(SkPicture::MakeFromStream(stream.get()));
- if (!picture) {
- return false;
- }
-
- SkDynamicMemoryWStream scratch;
Sniffer sniff(file.c_str());
- picture->serialize(&scratch, &sniff);
- return true;
+ auto stream = SkStream::MakeFromFile(file.c_str());
+
+ SkDeserialProcs procs;
+ procs.fImageProc = [](const void* data, size_t size, void* ctx) -> sk_sp<SkImage> {
+ ((Sniffer*)ctx)->sniff(data, size);
+ return nullptr;
+ };
+ procs.fImageCtx = &sniff;
+ return SkPicture::MakeFromStream(stream.get(), &procs) != nullptr;
}
int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage(
+ CommandLineFlags::SetUsage(
"Usage: get_images_from_skps -s <dir of skps> -o <dir for output images> --testDecode "
"-j <output JSON path> --writeImages, --writeFailedImages\n");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::Parse(argc, argv);
const char* inputs = FLAGS_skps[0];
gOutputDir = FLAGS_out[0];
if (!sk_isdir(gOutputDir)) {
- SkCommandLineFlags::PrintUsage();
+ CommandLineFlags::PrintUsage();
return 1;
}
@@ -187,34 +180,53 @@
"totalSuccesses": 21,
}
*/
- Json::Value fRoot;
- int totalFailures = 0;
- for(auto it = gSkpToUnknownCount.cbegin(); it != gSkpToUnknownCount.cend(); ++it)
+
+ unsigned int totalFailures = 0,
+ totalUnsupported = 0;
+ SkDynamicMemoryWStream memStream;
+ SkJSONWriter writer(&memStream, SkJSONWriter::Mode::kPretty);
+ writer.beginObject();
{
- SkDebugf("%s %d\n", it->first.c_str(), it->second);
- totalFailures += it->second;
- fRoot["failures"][it->first.c_str()] = it->second;
- }
- fRoot["totalFailures"] = totalFailures;
- int totalUnsupported = 0;
+ writer.beginObject("failures");
+ {
+ for(const auto& failure : gSkpToUnknownCount) {
+ SkDebugf("%s %d\n", failure.first.c_str(), failure.second);
+ totalFailures += failure.second;
+ writer.appendU32(failure.first.c_str(), failure.second);
+ }
+ }
+ writer.endObject();
+ writer.appendU32("totalFailures", totalFailures);
+
#ifdef SK_DEBUG
- for (const auto& unsupported : gSkpToUnsupportedCount) {
- SkDebugf("%s %d\n", unsupported.first.c_str(), unsupported.second);
- totalUnsupported += unsupported.second;
- fRoot["unsupported"][unsupported.first] = unsupported.second;
- }
- fRoot["totalUnsupported"] = totalUnsupported;
+ writer.beginObject("unsupported");
+ {
+ for (const auto& unsupported : gSkpToUnsupportedCount) {
+ SkDebugf("%s %d\n", unsupported.first.c_str(), unsupported.second);
+ totalUnsupported += unsupported.second;
+ writer.appendHexU32(unsupported.first.c_str(), unsupported.second);
+ }
+
+ }
+ writer.endObject();
+ writer.appendU32("totalUnsupported", totalUnsupported);
#endif
- fRoot["totalSuccesses"] = gKnown;
- SkDebugf("%d known, %d failures, %d unsupported\n", gKnown, totalFailures, totalUnsupported);
+
+ writer.appendS32("totalSuccesses", gKnown);
+ SkDebugf("%d known, %d failures, %d unsupported\n",
+ gKnown, totalFailures, totalUnsupported);
+ }
+ writer.endObject();
+ writer.flush();
+
if (totalFailures > 0 || totalUnsupported > 0) {
if (!FLAGS_failuresJsonPath.isEmpty()) {
SkDebugf("Writing failures to %s\n", FLAGS_failuresJsonPath[0]);
SkFILEWStream stream(FLAGS_failuresJsonPath[0]);
- stream.writeText(Json::StyledWriter().write(fRoot).c_str());
- stream.flush();
+ auto jsonStream = memStream.detachAsStream();
+ stream.writeStream(jsonStream.get(), jsonStream->getLength());
}
- return -1;
}
+
return 0;
}
diff --git a/src/third_party/skia/tools/git-sync-deps b/src/third_party/skia/tools/git-sync-deps
index 78449d9..c7379c0 100755
--- a/src/third_party/skia/tools/git-sync-deps
+++ b/src/third_party/skia/tools/git-sync-deps
@@ -11,8 +11,8 @@
An optional list of deps_os values.
Environment Variables:
- GIT_EXECUTABLE: path to "git" binary; if unset, will look for one of
- ['git', 'git.exe', 'git.bat'] in your default path.
+ GIT_EXECUTABLE: path to "git" binary; if unset, will look for git in
+ your default path.
GIT_SYNC_DEPS_PATH: file to get the dependency list from; if unset,
will use the file ../DEPS relative to this script's directory.
@@ -43,7 +43,7 @@
A string suitable for passing to subprocess functions, or None.
"""
envgit = os.environ.get('GIT_EXECUTABLE')
- searchlist = ['git', 'git.exe', 'git.bat']
+ searchlist = ['git']
if envgit:
searchlist.insert(0, envgit)
with open(os.devnull, 'w') as devnull:
@@ -204,6 +204,10 @@
raise Exception('%r is parent of %r' % (other_dir, directory))
list_of_arg_lists = []
for directory in sorted(dependencies):
+ if not isinstance(dependencies[directory], basestring):
+ if verbose:
+ print 'Skipping "%s".' % directory
+ continue
if '@' in dependencies[directory]:
repo, checkoutable = dependencies[directory].split('@', 1)
else:
@@ -216,10 +220,6 @@
multithread(git_checkout_to_directory, list_of_arg_lists)
- for directory in deps_file.get('recursedeps', []):
- recursive_path = os.path.join(deps_file_directory, directory, 'DEPS')
- git_sync_deps(recursive_path, command_line_os_requests, verbose)
-
def multithread(function, list_of_arg_lists):
# for args in list_of_arg_lists:
diff --git a/src/third_party/skia/tools/gpu/FenceSync.h b/src/third_party/skia/tools/gpu/FenceSync.h
index b430f5d..146b3a2 100644
--- a/src/third_party/skia/tools/gpu/FenceSync.h
+++ b/src/third_party/skia/tools/gpu/FenceSync.h
@@ -8,7 +8,7 @@
#ifndef FenceSync_DEFINED
#define FenceSync_DEFINED
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
namespace sk_gpu_test {
@@ -26,6 +26,8 @@
virtual bool waitFence(PlatformFence) const = 0;
virtual void deleteFence(PlatformFence) const = 0;
+ virtual bool validate() const { return true; }
+
virtual ~FenceSync() {}
};
diff --git a/src/third_party/skia/tools/gpu/GpuTimer.h b/src/third_party/skia/tools/gpu/GpuTimer.h
index 7678421..048dec7 100644
--- a/src/third_party/skia/tools/gpu/GpuTimer.h
+++ b/src/third_party/skia/tools/gpu/GpuTimer.h
@@ -8,8 +8,9 @@
#ifndef GpuTimer_DEFINED
#define GpuTimer_DEFINED
-#include "SkTypes.h"
-#include "SkExchange.h"
+#include "include/core/SkTypes.h"
+#include "src/core/SkExchange.h"
+
#include <chrono>
namespace sk_gpu_test {
diff --git a/src/third_party/skia/tools/gpu/GrContextFactory.cpp b/src/third_party/skia/tools/gpu/GrContextFactory.cpp
index 0686b79..d0defdc 100644
--- a/src/third_party/skia/tools/gpu/GrContextFactory.cpp
+++ b/src/third_party/skia/tools/gpu/GrContextFactory.cpp
@@ -6,29 +6,28 @@
* found in the LICENSE file.
*/
-#include "GrContextFactory.h"
-#include "gl/GLTestContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/gl/GLTestContext.h"
#if SK_ANGLE
- #include "gl/angle/GLTestContext_angle.h"
+ #include "tools/gpu/gl/angle/GLTestContext_angle.h"
#endif
-#include "gl/command_buffer/GLTestContext_command_buffer.h"
-#include "gl/debug/DebugGLTestContext.h"
-#if SK_MESA
- #include "gl/mesa/GLTestContext_mesa.h"
-#endif
+#include "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h"
#ifdef SK_VULKAN
-#include "vk/VkTestContext.h"
+#include "tools/gpu/vk/VkTestContext.h"
#endif
#ifdef SK_METAL
-#include "mtl/MtlTestContext.h"
+#include "tools/gpu/mtl/MtlTestContext.h"
#endif
-#include "gl/null/NullGLTestContext.h"
-#include "gl/GrGLGpu.h"
-#include "mock/MockTestContext.h"
-#include "GrCaps.h"
+#ifdef SK_DAWN
+#include "tools/gpu/dawn/DawnTestContext.h"
+#endif
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/gl/GrGLGpu.h"
+#include "tools/gpu/mock/MockTestContext.h"
-#if defined(SK_BUILD_FOR_WIN32) && defined(SK_ENABLE_DISCRETE_GPU)
+#if defined(SK_BUILD_FOR_WIN) && defined(SK_ENABLE_DISCRETE_GPU)
extern "C" {
// NVIDIA documents that the presence and value of this symbol programmatically enable the high
// performance GPU in laptops with switchable graphics.
@@ -54,9 +53,15 @@
}
void GrContextFactory::destroyContexts() {
- for (Context& context : fContexts) {
+ // We must delete the test contexts in reverse order so that any child context is finished and
+ // deleted before a parent context. This relies on the fact that when we make a new context we
+ // append it to the end of fContexts array.
+ // TODO: Look into keeping a dependency dag for contexts and deletion order
+ for (int i = fContexts.count() - 1; i >= 0; --i) {
+ Context& context = fContexts[i];
+ SkScopeExit restore(nullptr);
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ restore = context.fTestContext->makeCurrentAndAutoRestore();
}
if (!context.fGrContext->unique()) {
context.fGrContext->releaseResourcesAndAbandonContext();
@@ -69,10 +74,15 @@
}
void GrContextFactory::abandonContexts() {
- for (Context& context : fContexts) {
+ // We must abandon the test contexts in reverse order so that any child context is finished and
+ // abandoned before a parent context. This relies on the fact that when we make a new context we
+ // append it to the end of fContexts array.
+ // TODO: Look into keeping a dependency dag for contexts and deletion order
+ for (int i = fContexts.count() - 1; i >= 0; --i) {
+ Context& context = fContexts[i];
if (!context.fAbandoned) {
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ auto restore = context.fTestContext->makeCurrentAndAutoRestore();
context.fTestContext->testAbandon();
delete(context.fTestContext);
context.fTestContext = nullptr;
@@ -84,10 +94,16 @@
}
void GrContextFactory::releaseResourcesAndAbandonContexts() {
- for (Context& context : fContexts) {
+ // We must abandon the test contexts in reverse order so that any child context is finished and
+ // abandoned before a parent context. This relies on the fact that when we make a new context we
+ // append it to the end of fContexts array.
+ // TODO: Look into keeping a dependency dag for contexts and deletion order
+ for (int i = fContexts.count() - 1; i >= 0; --i) {
+ Context& context = fContexts[i];
+ SkScopeExit restore(nullptr);
if (!context.fAbandoned) {
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ restore = context.fTestContext->makeCurrentAndAutoRestore();
}
context.fGrContext->releaseResourcesAndAbandonContext();
context.fAbandoned = true;
@@ -116,7 +132,8 @@
context.fShareIndex == shareIndex &&
!context.fAbandoned) {
context.fTestContext->makeCurrent();
- return ContextInfo(context.fType, context.fTestContext, context.fGrContext);
+ return ContextInfo(context.fType, context.fTestContext, context.fGrContext,
+ context.fOptions);
}
}
@@ -133,11 +150,9 @@
}
std::unique_ptr<TestContext> testCtx;
- GrBackendContext backendContext = 0;
- sk_sp<const GrGLInterface> glInterface;
- GrBackend backend = ContextTypeBackend(type);
+ GrBackendApi backend = ContextTypeBackend(type);
switch (backend) {
- case kOpenGL_GrBackend: {
+ case GrBackendApi::kOpenGL: {
GLTestContext* glShareContext = masterContext
? static_cast<GLTestContext*>(masterContext->fTestContext) : nullptr;
GLTestContext* glCtx;
@@ -175,18 +190,6 @@
glCtx = CommandBufferGLTestContext::Create(glShareContext);
break;
#endif
-#if SK_MESA
- case kMESA_ContextType:
- glCtx = CreateMesaGLTestContext(glShareContext);
- break;
-#endif
- case kNullGL_ContextType:
- glCtx = CreateNullGLTestContext(
- ContextOverrides::kRequireNVPRSupport & overrides, glShareContext);
- break;
- case kDebugGL_ContextType:
- glCtx = CreateDebugGLTestContext(glShareContext);
- break;
default:
return ContextInfo();
}
@@ -194,18 +197,13 @@
return ContextInfo();
}
testCtx.reset(glCtx);
- glInterface.reset(SkRef(glCtx->gl()));
- backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
break;
}
#ifdef SK_VULKAN
- case kVulkan_GrBackend: {
+ case GrBackendApi::kVulkan: {
VkTestContext* vkSharedContext = masterContext
? static_cast<VkTestContext*>(masterContext->fTestContext) : nullptr;
SkASSERT(kVulkan_ContextType == type);
- if (ContextOverrides::kRequireNVPRSupport & overrides) {
- return ContextInfo();
- }
testCtx.reset(CreatePlatformVkTestContext(vkSharedContext));
if (!testCtx) {
return ContextInfo();
@@ -220,74 +218,61 @@
fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
}
}
- backendContext = testCtx->backendContext();
break;
}
#endif
#ifdef SK_METAL
- case kMetal_GrBackend: {
- SkASSERT(!masterContext);
- testCtx.reset(CreatePlatformMtlTestContext(nullptr));
+ case GrBackendApi::kMetal: {
+ MtlTestContext* mtlSharedContext = masterContext
+ ? static_cast<MtlTestContext*>(masterContext->fTestContext) : nullptr;
+ SkASSERT(kMetal_ContextType == type);
+ testCtx.reset(CreatePlatformMtlTestContext(mtlSharedContext));
if (!testCtx) {
return ContextInfo();
}
break;
}
#endif
- case kMock_GrBackend: {
- TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
- SkASSERT(kMock_ContextType == type);
- if (ContextOverrides::kRequireNVPRSupport & overrides) {
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn: {
+ DawnTestContext* dawnSharedContext = masterContext
+ ? static_cast<DawnTestContext*>(masterContext->fTestContext) : nullptr;
+ testCtx.reset(CreatePlatformDawnTestContext(dawnSharedContext));
+ if (!testCtx) {
return ContextInfo();
}
+ break;
+ }
+#endif
+ case GrBackendApi::kMock: {
+ TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
+ SkASSERT(kMock_ContextType == type);
testCtx.reset(CreateMockTestContext(sharedContext));
if (!testCtx) {
return ContextInfo();
}
- backendContext = testCtx->backendContext();
break;
}
default:
return ContextInfo();
}
- testCtx->makeCurrent();
+
SkASSERT(testCtx && testCtx->backend() == backend);
GrContextOptions grOptions = fGlobalOptions;
- if (ContextOverrides::kDisableNVPR & overrides) {
- grOptions.fSuppressPathRendering = true;
- }
- if (ContextOverrides::kUseInstanced & overrides) {
- grOptions.fEnableInstancedRendering = true;
- }
- if (ContextOverrides::kAllowSRGBWithoutDecodeControl & overrides) {
- grOptions.fRequireDecodeDisableForSRGB = false;
- }
if (ContextOverrides::kAvoidStencilBuffers & overrides) {
grOptions.fAvoidStencilBuffers = true;
}
- sk_sp<GrContext> grCtx = testCtx->makeGrContext(grOptions);
- if (!grCtx.get() && kMetal_GrBackend != backend) {
- grCtx.reset(GrContext::Create(backend, backendContext, grOptions));
+ sk_sp<GrContext> grCtx;
+ {
+ auto restore = testCtx->makeCurrentAndAutoRestore();
+ grCtx = testCtx->makeGrContext(grOptions);
}
if (!grCtx.get()) {
return ContextInfo();
}
- if (ContextOverrides::kRequireNVPRSupport & overrides) {
- if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
- return ContextInfo();
- }
- }
- if (ContextOverrides::kUseInstanced & overrides) {
- if (GrCaps::InstancedSupport::kNone == grCtx->caps()->instancedSupport()) {
- return ContextInfo();
- }
- }
- if (ContextOverrides::kRequireSRGBSupport & overrides) {
- if (!grCtx->caps()->srgbSupport()) {
- return ContextInfo();
- }
- }
+ // We must always add new contexts by pushing to the back so that when we delete them we delete
+ // them in reverse order in which they were made.
Context& context = fContexts.push_back();
context.fBackend = backend;
context.fTestContext = testCtx.release();
@@ -297,7 +282,9 @@
context.fAbandoned = false;
context.fShareContext = shareContext;
context.fShareIndex = shareIndex;
- return ContextInfo(context.fType, context.fTestContext, context.fGrContext);
+ context.fOptions = grOptions;
+ context.fTestContext->makeCurrent();
+ return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
}
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
diff --git a/src/third_party/skia/tools/gpu/GrContextFactory.h b/src/third_party/skia/tools/gpu/GrContextFactory.h
index a13aeb7..d1b7fd5 100644
--- a/src/third_party/skia/tools/gpu/GrContextFactory.h
+++ b/src/third_party/skia/tools/gpu/GrContextFactory.h
@@ -8,11 +8,11 @@
#ifndef GrContextFactory_DEFINED
#define GrContextFactory_DEFINED
-#include "GrContext.h"
-#include "GrContextOptions.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/GrContextOptions.h"
-#include "gl/GLTestContext.h"
-#include "SkTArray.h"
+#include "include/private/SkTArray.h"
+#include "tools/gpu/gl/GLTestContext.h"
struct GrVkBackendContext;
@@ -39,11 +39,9 @@
kANGLE_GL_ES2_ContextType, //! ANGLE on OpenGL OpenGL ES 2 context.
kANGLE_GL_ES3_ContextType, //! ANGLE on OpenGL OpenGL ES 3 context.
kCommandBuffer_ContextType, //! Chromium command buffer OpenGL ES context.
- kMESA_ContextType, //! MESA OpenGL context
- kNullGL_ContextType, //! Non-rendering OpenGL mock context.
- kDebugGL_ContextType, //! Non-rendering, state verifying OpenGL context.
kVulkan_ContextType, //! Vulkan
kMetal_ContextType, //! Metal
+ kDawn_ContextType, //! Dawn
kMock_ContextType, //! Mock context that does not draw.
kLastContextType = kMock_ContextType
};
@@ -56,19 +54,11 @@
*/
enum class ContextOverrides {
kNone = 0x0,
- kDisableNVPR = 0x1,
- kUseInstanced = 0x2,
- kAllowSRGBWithoutDecodeControl = 0x4,
- kAvoidStencilBuffers = 0x8,
-
- kRequireNVPRSupport = 0x10,
- kRequireSRGBSupport = 0x20,
+ kAvoidStencilBuffers = 0x1,
};
static bool IsRenderingContext(ContextType type) {
switch (type) {
- case kNullGL_ContextType:
- case kDebugGL_ContextType:
case kMock_ContextType:
return false;
default:
@@ -76,16 +66,18 @@
}
}
- static GrBackend ContextTypeBackend(ContextType type) {
+ static GrBackendApi ContextTypeBackend(ContextType type) {
switch (type) {
case kVulkan_ContextType:
- return kVulkan_GrBackend;
+ return GrBackendApi::kVulkan;
case kMetal_ContextType:
- return kMetal_GrBackend;
+ return GrBackendApi::kMetal;
+ case kDawn_ContextType:
+ return GrBackendApi::kDawn;
case kMock_ContextType:
- return kMock_GrBackend;
+ return GrBackendApi::kMock;
default:
- return kOpenGL_GrBackend;
+ return GrBackendApi::kOpenGL;
}
}
@@ -107,21 +99,16 @@
return "ANGLE GL ES3";
case kCommandBuffer_ContextType:
return "Command Buffer";
- case kMESA_ContextType:
- return "Mesa";
- case kNullGL_ContextType:
- return "Null GL";
- case kDebugGL_ContextType:
- return "Debug GL";
case kVulkan_ContextType:
return "Vulkan";
case kMetal_ContextType:
return "Metal";
+ case kDawn_ContextType:
+ return "Dawn";
case kMock_ContextType:
return "Mock";
}
- SkFAIL("Unreachable");
- return "Unknown";
+ SK_ABORT("Unreachable");
}
explicit GrContextFactory(const GrContextOptions& opts);
@@ -136,8 +123,7 @@
/**
* Get a context initialized with a type of GL context. It also makes the GL context current.
*/
- ContextInfo getContextInfo(ContextType type,
- ContextOverrides overrides = ContextOverrides::kNone);
+ ContextInfo getContextInfo(ContextType type, ContextOverrides = ContextOverrides::kNone);
/**
* Get a context in the same share group as the passed in GrContext, with the same type and
@@ -159,13 +145,14 @@
struct Context {
ContextType fType;
ContextOverrides fOverrides;
- GrBackend fBackend;
+ GrContextOptions fOptions;
+ GrBackendApi fBackend;
TestContext* fTestContext;
GrContext* fGrContext;
GrContext* fShareContext;
uint32_t fShareIndex;
- bool fAbandoned;
+ bool fAbandoned;
};
SkTArray<Context, true> fContexts;
std::unique_ptr<GLTestContext> fSentinelGLContext;
@@ -178,30 +165,29 @@
ContextInfo& operator=(const ContextInfo&) = default;
GrContextFactory::ContextType type() const { return fType; }
- GrBackend backend() const { return GrContextFactory::ContextTypeBackend(fType); }
+ GrBackendApi backend() const { return GrContextFactory::ContextTypeBackend(fType); }
GrContext* grContext() const { return fGrContext; }
TestContext* testContext() const { return fTestContext; }
GLTestContext* glContext() const {
- SkASSERT(kOpenGL_GrBackend == this->backend());
+ SkASSERT(GrBackendApi::kOpenGL == this->backend());
return static_cast<GLTestContext*>(fTestContext);
}
+ const GrContextOptions& options() const { return fOptions; }
+
private:
- ContextInfo(GrContextFactory::ContextType type,
- TestContext* testContext,
- GrContext* grContext)
- : fType(type)
- , fTestContext(testContext)
- , fGrContext(grContext) {
- }
+ ContextInfo(GrContextFactory::ContextType type, TestContext* testContext, GrContext* grContext,
+ const GrContextOptions& options)
+ : fType(type), fTestContext(testContext), fGrContext(grContext), fOptions(options) {}
GrContextFactory::ContextType fType = GrContextFactory::kGL_ContextType;
// Valid until the factory destroys it via abandonContexts() or destroyContexts().
- TestContext* fTestContext = nullptr;
- GrContext* fGrContext = nullptr;
+ TestContext* fTestContext = nullptr;
+ GrContext* fGrContext = nullptr;
+ GrContextOptions fOptions;
friend class GrContextFactory;
};
diff --git a/src/third_party/skia/tools/gpu/GrTest.cpp b/src/third_party/skia/tools/gpu/GrTest.cpp
index c5af01e..70d8692 100644
--- a/src/third_party/skia/tools/gpu/GrTest.cpp
+++ b/src/third_party/skia/tools/gpu/GrTest.cpp
@@ -5,233 +5,36 @@
* found in the LICENSE file.
*/
-#include "GrTest.h"
+#include "include/core/SkString.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContextOptions.h"
+#include "include/gpu/GrTexture.h"
+#include "include/private/GrRecordingContext.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkMathPriv.h"
+#include "src/gpu/GrClip.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrDrawOpAtlas.h"
+#include "src/gpu/GrDrawingManager.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrGpuResourceCacheAccess.h"
+#include "src/gpu/GrMemoryPool.h"
+#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
+#include "src/gpu/GrRenderTargetProxy.h"
+#include "src/gpu/GrResourceCache.h"
+#include "src/gpu/GrSemaphore.h"
+#include "src/gpu/GrSurfaceContextPriv.h"
+#include "src/gpu/SkGr.h"
+#include "src/gpu/ccpr/GrCCPathCache.h"
+#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
+#include "src/gpu/ops/GrMeshDrawOp.h"
+#include "src/gpu/text/GrStrikeCache.h"
+#include "src/gpu/text/GrTextBlobCache.h"
+#include "src/image/SkImage_Gpu.h"
+
#include <algorithm>
-#include "GrBackendSurface.h"
-#include "GrContextOptions.h"
-#include "GrContextPriv.h"
-#include "GrDrawOpAtlas.h"
-#include "GrDrawingManager.h"
-#include "GrGpu.h"
-#include "GrGpuResourceCacheAccess.h"
-#include "GrRenderTargetContext.h"
-#include "GrRenderTargetContextPriv.h"
-#include "GrRenderTargetProxy.h"
-#include "GrResourceCache.h"
-#include "GrSemaphore.h"
-#include "GrSurfaceContextPriv.h"
-#include "GrTexture.h"
-#include "SkGr.h"
-#include "SkImage_Gpu.h"
-#include "SkMathPriv.h"
-#include "SkString.h"
-#include "ops/GrMeshDrawOp.h"
-#include "text/GrAtlasGlyphCache.h"
-#include "text/GrTextBlobCache.h"
-
-namespace GrTest {
-
-void SetupAlwaysEvictAtlas(GrContext* context) {
- // These sizes were selected because they allow each atlas to hold a single plot and will thus
- // stress the atlas
- int dim = GrDrawOpAtlas::kGlyphMaxDim;
- GrDrawOpAtlasConfig configs[3];
- configs[kA8_GrMaskFormat].fWidth = dim;
- configs[kA8_GrMaskFormat].fHeight = dim;
- configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
- configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
- configs[kA8_GrMaskFormat].fPlotWidth = dim;
- configs[kA8_GrMaskFormat].fPlotHeight = dim;
-
- configs[kA565_GrMaskFormat].fWidth = dim;
- configs[kA565_GrMaskFormat].fHeight = dim;
- configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
- configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
- configs[kA565_GrMaskFormat].fPlotWidth = dim;
- configs[kA565_GrMaskFormat].fPlotHeight = dim;
-
- configs[kARGB_GrMaskFormat].fWidth = dim;
- configs[kARGB_GrMaskFormat].fHeight = dim;
- configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
- configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
- configs[kARGB_GrMaskFormat].fPlotWidth = dim;
- configs[kARGB_GrMaskFormat].fPlotHeight = dim;
-
- context->setTextContextAtlasSizes_ForTesting(configs);
-}
-
-GrBackendTexture CreateBackendTexture(GrBackend backend, int width, int height,
- GrPixelConfig config, GrBackendObject handle) {
- switch (backend) {
-#ifdef SK_VULKAN
- case kVulkan_GrBackend: {
- GrVkImageInfo* vkInfo = (GrVkImageInfo*)(handle);
- return GrBackendTexture(width, height, *vkInfo);
- }
-#endif
- case kOpenGL_GrBackend: {
- GrGLTextureInfo* glInfo = (GrGLTextureInfo*)(handle);
- return GrBackendTexture(width, height, config, *glInfo);
- }
- case kMock_GrBackend: {
- GrMockTextureInfo* mockInfo = (GrMockTextureInfo*)(handle);
- return GrBackendTexture(width, height, config, *mockInfo);
- }
- default:
- return GrBackendTexture();
- }
-}
-
-} // namespace GrTest
-
-bool GrSurfaceProxy::isWrapped_ForTesting() const {
- return SkToBool(fTarget);
-}
-
-bool GrRenderTargetContext::isWrapped_ForTesting() const {
- return fRenderTargetProxy->isWrapped_ForTesting();
-}
-
-void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
- fTextBlobCache->setBudget(bytes);
-}
-
-void GrContext::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) {
- fAtlasGlyphCache->setAtlasSizes_ForTesting(configs);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrContext::purgeAllUnlockedResources() {
- fResourceCache->purgeAllUnlocked();
-}
-
-void GrContext::resetGpuStats() const {
-#if GR_GPU_STATS
- fGpu->stats()->reset();
-#endif
-}
-
-void GrContext::dumpCacheStats(SkString* out) const {
-#if GR_CACHE_STATS
- fResourceCache->dumpStats(out);
-#endif
-}
-
-void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
- SkTArray<double>* values) const {
-#if GR_CACHE_STATS
- fResourceCache->dumpStatsKeyValuePairs(keys, values);
-#endif
-}
-
-void GrContext::printCacheStats() const {
- SkString out;
- this->dumpCacheStats(&out);
- SkDebugf("%s", out.c_str());
-}
-
-void GrContext::dumpGpuStats(SkString* out) const {
-#if GR_GPU_STATS
- return fGpu->stats()->dump(out);
-#endif
-}
-
-void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
- SkTArray<double>* values) const {
-#if GR_GPU_STATS
- return fGpu->stats()->dumpKeyValuePairs(keys, values);
-#endif
-}
-
-void GrContext::printGpuStats() const {
- SkString out;
- this->dumpGpuStats(&out);
- SkDebugf("%s", out.c_str());
-}
-
-sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format) {
- GrAtlasGlyphCache* cache = this->getAtlasGlyphCache();
-
- sk_sp<GrTextureProxy> proxy = cache->getProxy(format);
- if (!proxy) {
- return nullptr;
- }
-
- SkASSERT(proxy->priv().isExact());
- sk_sp<SkImage> image(new SkImage_Gpu(this, kNeedNewImageUniqueID, kPremul_SkAlphaType,
- std::move(proxy), nullptr, SkBudgeted::kNo));
- return image;
-}
-
-#if GR_GPU_STATS
-void GrGpu::Stats::dump(SkString* out) {
- out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
- out->appendf("Shader Compilations: %d\n", fShaderCompilations);
- out->appendf("Textures Created: %d\n", fTextureCreates);
- out->appendf("Texture Uploads: %d\n", fTextureUploads);
- out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
- out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
- out->appendf("Number of draws: %d\n", fNumDraws);
-}
-
-void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
- keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
- keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
- keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
- keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
- keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
-}
-
-#endif
-
-#if GR_CACHE_STATS
-void GrResourceCache::getStats(Stats* stats) const {
- stats->reset();
-
- stats->fTotal = this->getResourceCount();
- stats->fNumNonPurgeable = fNonpurgeableResources.count();
- stats->fNumPurgeable = fPurgeableQueue.count();
-
- for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
- stats->update(fNonpurgeableResources[i]);
- }
- for (int i = 0; i < fPurgeableQueue.count(); ++i) {
- stats->update(fPurgeableQueue.at(i));
- }
-}
-
-void GrResourceCache::dumpStats(SkString* out) const {
- this->validate();
-
- Stats stats;
-
- this->getStats(&stats);
-
- float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
- float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
-
- out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
- out->appendf("\t\tEntry Count: current %d"
- " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
- stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
- stats.fScratch, countUtilization, fHighWaterCount);
- out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
- SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
- SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
-}
-
-void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
- SkTArray<double>* values) const {
- this->validate();
-
- Stats stats;
- this->getStats(&stats);
-
- keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
-}
-
-#endif
///////////////////////////////////////////////////////////////////////////////
@@ -256,47 +59,98 @@
#define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
-uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
+
+uint32_t GrRenderTargetContextPriv::testingOnly_getOpsTaskID() {
+ return fRenderTargetContext->getOpsTask()->uniqueID();
+}
+
+void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
+ this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
+}
+
+void GrRenderTargetContextPriv::testingOnly_addDrawOp(
+ const GrClip& clip,
+ std::unique_ptr<GrDrawOp> op,
+ const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) {
ASSERT_SINGLE_OWNER
- if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
- return SK_InvalidUniqueID;
+ if (fRenderTargetContext->fContext->priv().abandoned()) {
+ fRenderTargetContext->fContext->priv().opMemoryPool()->release(std::move(op));
+ return;
}
SkDEBUGCODE(fRenderTargetContext->validate());
- GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
+ GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->auditTrail(),
"GrRenderTargetContext::testingOnly_addDrawOp");
- return fRenderTargetContext->addDrawOp(GrNoClip(), std::move(op));
+ fRenderTargetContext->addDrawOp(clip, std::move(op), willAddFn);
}
#undef ASSERT_SINGLE_OWNER
-///////////////////////////////////////////////////////////////////////////////
-
-GrRenderTargetFlags GrRenderTargetProxy::testingOnly_getFlags() const {
- return fRenderTargetFlags;
-}
-
//////////////////////////////////////////////////////////////////////////////
-void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
- fContext->flush();
- fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
+void GrCoverageCountingPathRenderer::testingOnly_drawPathDirectly(const DrawPathArgs& args) {
+ // Call onDrawPath() directly: We want to test paths that might fail onCanDrawPath() simply for
+ // performance reasons, and GrPathRenderer::drawPath() assert that this call returns true.
+ // The test is responsible to not draw any paths that CCPR is not actually capable of.
+ this->onDrawPath(args);
}
-void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
- int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
- fOnFlushCBObjects.begin();
- SkASSERT(n < fOnFlushCBObjects.count());
- fOnFlushCBObjects.removeShuffle(n);
+const GrCCPerFlushResources*
+GrCoverageCountingPathRenderer::testingOnly_getCurrentFlushResources() {
+ SkASSERT(fFlushing);
+ if (fFlushingPaths.empty()) {
+ return nullptr;
+ }
+ // All pending paths should share the same resources.
+ const GrCCPerFlushResources* resources = fFlushingPaths.front()->fFlushResources.get();
+#ifdef SK_DEBUG
+ for (const auto& flushingPaths : fFlushingPaths) {
+ SkASSERT(flushingPaths->fFlushResources.get() == resources);
+ }
+#endif
+ return resources;
}
+const GrCCPathCache* GrCoverageCountingPathRenderer::testingOnly_getPathCache() const {
+ return fPathCache.get();
+}
+
+const GrTexture* GrCCPerFlushResources::testingOnly_frontCopyAtlasTexture() const {
+ if (fCopyAtlasStack.empty()) {
+ return nullptr;
+ }
+ const GrTextureProxy* proxy = fCopyAtlasStack.front().textureProxy();
+ return (proxy) ? proxy->peekTexture() : nullptr;
+}
+
+const GrTexture* GrCCPerFlushResources::testingOnly_frontRenderedAtlasTexture() const {
+ if (fRenderedAtlasStack.empty()) {
+ return nullptr;
+ }
+ const GrTextureProxy* proxy = fRenderedAtlasStack.front().textureProxy();
+ return (proxy) ? proxy->peekTexture() : nullptr;
+}
+
+const SkTHashTable<GrCCPathCache::HashNode, const GrCCPathCache::Key&>&
+GrCCPathCache::testingOnly_getHashTable() const {
+ return fHashTable;
+}
+
+const SkTInternalLList<GrCCPathCacheEntry>& GrCCPathCache::testingOnly_getLRU() const {
+ return fLRU;
+}
+
+int GrCCPathCacheEntry::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; }
+
+int GrCCCachedAtlas::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; }
+
//////////////////////////////////////////////////////////////////////////////
#define DRAW_OP_TEST_EXTERN(Op) \
- extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType)
+ extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, \
+ GrRecordingContext*, int numSamples)
#define DRAW_OP_TEST_ENTRY(Op) Op##__Test
DRAW_OP_TEST_EXTERN(AAConvexPathOp);
-DRAW_OP_TEST_EXTERN(AAFillRectOp);
DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp);
DRAW_OP_TEST_EXTERN(AAHairlineOp);
DRAW_OP_TEST_EXTERN(AAStrokeRectOp);
@@ -305,10 +159,10 @@
DRAW_OP_TEST_EXTERN(DefaultPathOp);
DRAW_OP_TEST_EXTERN(DIEllipseOp);
DRAW_OP_TEST_EXTERN(EllipseOp);
+DRAW_OP_TEST_EXTERN(FillRectOp);
DRAW_OP_TEST_EXTERN(GrAtlasTextOp);
-DRAW_OP_TEST_EXTERN(GrDrawAtlasOp);
-DRAW_OP_TEST_EXTERN(GrDrawVerticesOp);
-DRAW_OP_TEST_EXTERN(NonAAFillRectOp);
+DRAW_OP_TEST_EXTERN(DrawAtlasOp);
+DRAW_OP_TEST_EXTERN(DrawVerticesOp);
DRAW_OP_TEST_EXTERN(NonAALatticeOp);
DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp);
DRAW_OP_TEST_EXTERN(ShadowRRectOp);
@@ -316,38 +170,40 @@
DRAW_OP_TEST_EXTERN(RegionOp);
DRAW_OP_TEST_EXTERN(RRectOp);
DRAW_OP_TEST_EXTERN(TesselatingPathOp);
+DRAW_OP_TEST_EXTERN(TextureOp);
void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext, GrPaint&& paint) {
- GrContext* context = renderTargetContext->surfPriv().getContext();
- using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*, GrContext*, GrFSAAType);
+ auto context = renderTargetContext->surfPriv().getContext();
+ using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*,
+ GrRecordingContext*, int numSamples);
static constexpr MakeDrawOpFn* gFactories[] = {
- DRAW_OP_TEST_ENTRY(AAConvexPathOp),
- DRAW_OP_TEST_ENTRY(AAFillRectOp),
- DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
- DRAW_OP_TEST_ENTRY(AAHairlineOp),
- DRAW_OP_TEST_ENTRY(AAStrokeRectOp),
- DRAW_OP_TEST_ENTRY(CircleOp),
- DRAW_OP_TEST_ENTRY(DashOp),
- DRAW_OP_TEST_ENTRY(DefaultPathOp),
- DRAW_OP_TEST_ENTRY(DIEllipseOp),
- DRAW_OP_TEST_ENTRY(EllipseOp),
- DRAW_OP_TEST_ENTRY(GrAtlasTextOp),
- DRAW_OP_TEST_ENTRY(GrDrawAtlasOp),
- DRAW_OP_TEST_ENTRY(GrDrawVerticesOp),
- DRAW_OP_TEST_ENTRY(NonAAFillRectOp),
- DRAW_OP_TEST_ENTRY(NonAALatticeOp),
- DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
- DRAW_OP_TEST_ENTRY(ShadowRRectOp),
- DRAW_OP_TEST_ENTRY(SmallPathOp),
- DRAW_OP_TEST_ENTRY(RegionOp),
- DRAW_OP_TEST_ENTRY(RRectOp),
- DRAW_OP_TEST_ENTRY(TesselatingPathOp),
+ DRAW_OP_TEST_ENTRY(AAConvexPathOp),
+ DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
+ DRAW_OP_TEST_ENTRY(AAHairlineOp),
+ DRAW_OP_TEST_ENTRY(AAStrokeRectOp),
+ DRAW_OP_TEST_ENTRY(CircleOp),
+ DRAW_OP_TEST_ENTRY(DashOp),
+ DRAW_OP_TEST_ENTRY(DefaultPathOp),
+ DRAW_OP_TEST_ENTRY(DIEllipseOp),
+ DRAW_OP_TEST_ENTRY(EllipseOp),
+ DRAW_OP_TEST_ENTRY(FillRectOp),
+ DRAW_OP_TEST_ENTRY(GrAtlasTextOp),
+ DRAW_OP_TEST_ENTRY(DrawAtlasOp),
+ DRAW_OP_TEST_ENTRY(DrawVerticesOp),
+ DRAW_OP_TEST_ENTRY(NonAALatticeOp),
+ DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
+ DRAW_OP_TEST_ENTRY(ShadowRRectOp),
+ DRAW_OP_TEST_ENTRY(SmallPathOp),
+ DRAW_OP_TEST_ENTRY(RegionOp),
+ DRAW_OP_TEST_ENTRY(RRectOp),
+ DRAW_OP_TEST_ENTRY(TesselatingPathOp),
+ DRAW_OP_TEST_ENTRY(TextureOp),
};
static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories);
uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal));
auto op = gFactories[index](
- std::move(paint), random, context, renderTargetContext->fsaaType());
+ std::move(paint), random, context, renderTargetContext->numSamples());
SkASSERT(op);
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
}
diff --git a/src/third_party/skia/tools/gpu/GrTest.h b/src/third_party/skia/tools/gpu/GrTest.h
deleted file mode 100644
index d4a4c6d..0000000
--- a/src/third_party/skia/tools/gpu/GrTest.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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 GrTest_DEFINED
-#define GrTest_DEFINED
-
-#include "GrBackendSurface.h"
-#include "GrContext.h"
-
-namespace GrTest {
- /**
- * Forces the GrContext to use a small atlas which only has room for one plot and will thus
- * constantly be evicting entries
- */
- void SetupAlwaysEvictAtlas(GrContext*);
-
- GrBackendTexture CreateBackendTexture(GrBackend, int width, int height,
- GrPixelConfig, GrBackendObject);
-};
-
-#endif
diff --git a/src/third_party/skia/tools/gpu/MemoryCache.cpp b/src/third_party/skia/tools/gpu/MemoryCache.cpp
new file mode 100644
index 0000000..4da7fd7
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/MemoryCache.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/utils/SkBase64.h"
+#include "src/core/SkMD5.h"
+#include "src/gpu/GrPersistentCacheUtils.h"
+#include "tools/gpu/MemoryCache.h"
+
+#if defined(SK_VULKAN)
+#include "src/gpu/vk/GrVkGpu.h"
+#endif
+
+// Change this to 1 to log cache hits/misses/stores using SkDebugf.
+#define LOG_MEMORY_CACHE 0
+
+static SkString data_to_str(const SkData& data) {
+ size_t encodeLength = SkBase64::Encode(data.data(), data.size(), nullptr);
+ SkString str;
+ str.resize(encodeLength);
+ SkBase64::Encode(data.data(), data.size(), str.writable_str());
+ static constexpr size_t kMaxLength = 60;
+ static constexpr char kTail[] = "...";
+ static const size_t kTailLen = strlen(kTail);
+ bool overlength = encodeLength > kMaxLength;
+ if (overlength) {
+ str = SkString(str.c_str(), kMaxLength - kTailLen);
+ str.append(kTail);
+ }
+ return str;
+}
+
+namespace sk_gpu_test {
+
+sk_sp<SkData> MemoryCache::load(const SkData& key) {
+ auto result = fMap.find(key);
+ if (result == fMap.end()) {
+ if (LOG_MEMORY_CACHE) {
+ SkDebugf("Load Key: %s\n\tNot Found.\n\n", data_to_str(key).c_str());
+ }
+ ++fCacheMissCnt;
+ return nullptr;
+ }
+ if (LOG_MEMORY_CACHE) {
+ SkDebugf("Load Key: %s\n\tFound Data: %s\n\n", data_to_str(key).c_str(),
+ data_to_str(*result->second.fData).c_str());
+ }
+ result->second.fHitCount++;
+ return result->second.fData;
+}
+
+void MemoryCache::store(const SkData& key, const SkData& data) {
+ if (LOG_MEMORY_CACHE) {
+ SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
+ data_to_str(data).c_str());
+ }
+ fMap[Key(key)] = Value(data);
+}
+
+void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
+ if (GrBackendApi::kOpenGL != api && GrBackendApi::kVulkan != api) {
+ return;
+ }
+
+ for (auto it = fMap.begin(); it != fMap.end(); ++it) {
+ SkMD5 hash;
+ size_t bytesToHash = it->first.fKey->size();
+#if defined(SK_VULKAN)
+ if (GrBackendApi::kVulkan == api) {
+ // Vulkan stores two kinds of data in the cache (shaders and pipelines). The last four
+ // bytes of the key identify which one we have. We only want to extract shaders.
+ // Additionally, we don't want to hash the tag bytes, so we get the same keys as GL,
+ // which is good for cross-checking code generation and performance.
+ GrVkGpu::PersistentCacheKeyType vkKeyType;
+ SkASSERT(bytesToHash >= sizeof(vkKeyType));
+ bytesToHash -= sizeof(vkKeyType);
+ memcpy(&vkKeyType, it->first.fKey->bytes() + bytesToHash, sizeof(vkKeyType));
+ if (vkKeyType != GrVkGpu::kShader_PersistentCacheKeyType) {
+ continue;
+ }
+ }
+#endif
+ hash.write(it->first.fKey->bytes(), bytesToHash);
+ SkMD5::Digest digest = hash.finish();
+ SkString md5;
+ for (int i = 0; i < 16; ++i) {
+ md5.appendf("%02x", digest.data[i]);
+ }
+
+ SkSL::Program::Inputs inputsIgnored[kGrShaderTypeCount];
+ SkSL::String shaders[kGrShaderTypeCount];
+ const SkData* data = it->second.fData.get();
+ // Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
+ // run glslang on the input.
+ const char* ext = GrBackendApi::kOpenGL == api ? "frag" : "spv";
+ SkReader32 reader(data->data(), data->size());
+ reader.readU32(); // Shader type tag
+ GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders,
+ inputsIgnored, kGrShaderTypeCount);
+
+ SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
+ SkFILEWStream file(filename.c_str());
+ file.write(shaders[kFragment_GrShaderType].c_str(), shaders[kFragment_GrShaderType].size());
+ }
+}
+
+} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/MemoryCache.h b/src/third_party/skia/tools/gpu/MemoryCache.h
new file mode 100644
index 0000000..22911a5
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/MemoryCache.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef MemoryCache_DEFINED
+#define MemoryCache_DEFINED
+
+#include "include/core/SkData.h"
+#include "include/gpu/GrContextOptions.h"
+#include "include/private/SkChecksum.h"
+
+#include <unordered_map>
+
+namespace sk_gpu_test {
+
+/**
+ * This class can be used to maintain an in memory record of all programs cached by GrContext.
+ * It can be shared by multiple GrContexts so long as those GrContexts are created with the same
+ * options and will have the same GrCaps (e.g. same backend, same GL context creation parameters,
+ * ...).
+ */
+class MemoryCache : public GrContextOptions::PersistentCache {
+public:
+ MemoryCache() = default;
+ MemoryCache(const MemoryCache&) = delete;
+ MemoryCache& operator=(const MemoryCache&) = delete;
+ void reset() {
+ fCacheMissCnt = 0;
+ fMap.clear();
+ }
+
+ sk_sp<SkData> load(const SkData& key) override;
+ void store(const SkData& key, const SkData& data) override;
+ int numCacheMisses() const { return fCacheMissCnt; }
+ void resetNumCacheMisses() { fCacheMissCnt = 0; }
+
+ void writeShadersToDisk(const char* path, GrBackendApi backend);
+
+ template <typename Fn>
+ void foreach(Fn&& fn) {
+ for (auto it = fMap.begin(); it != fMap.end(); ++it) {
+ fn(it->first.fKey, it->second.fData, it->second.fHitCount);
+ }
+ }
+
+private:
+ struct Key {
+ Key() = default;
+ Key(const SkData& key) : fKey(SkData::MakeWithCopy(key.data(), key.size())) {}
+ Key(const Key& that) = default;
+ Key& operator=(const Key&) = default;
+ bool operator==(const Key& that) const {
+ return that.fKey->size() == fKey->size() &&
+ !memcmp(fKey->data(), that.fKey->data(), that.fKey->size());
+ }
+ sk_sp<const SkData> fKey;
+ };
+
+ struct Value {
+ Value() = default;
+ Value(const SkData& data)
+ : fData(SkData::MakeWithCopy(data.data(), data.size()))
+ , fHitCount(1) {}
+ Value(const Value& that) = default;
+ Value& operator=(const Value&) = default;
+
+ sk_sp<SkData> fData;
+ int fHitCount;
+ };
+
+ struct Hash {
+ using argument_type = Key;
+ using result_type = uint32_t;
+ uint32_t operator()(const Key& key) const {
+ return key.fKey ? SkOpts::hash_fn(key.fKey->data(), key.fKey->size(), 0) : 0;
+ }
+ };
+
+ int fCacheMissCnt = 0;
+ std::unordered_map<Key, Value, Hash> fMap;
+};
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/ProxyUtils.cpp b/src/third_party/skia/tools/gpu/ProxyUtils.cpp
new file mode 100644
index 0000000..4f6e6fb
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/ProxyUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/GrBackendSurface.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrDrawingManager.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrImageInfo.h"
+#include "src/gpu/GrProxyProvider.h"
+#include "src/gpu/SkGr.h"
+#include "tools/gpu/ProxyUtils.h"
+
+namespace sk_gpu_test {
+
+sk_sp<GrTextureProxy> MakeTextureProxyFromData(GrContext* context,
+ GrRenderable renderable,
+ int width,
+ int height,
+ GrColorType colorType, SkAlphaType alphaType,
+ GrSurfaceOrigin origin,
+ const void* data, size_t rowBytes) {
+ if (context->priv().abandoned()) {
+ return nullptr;
+ }
+
+ const GrCaps* caps = context->priv().caps();
+
+ const GrBackendFormat format = caps->getDefaultBackendFormat(colorType, renderable);
+ if (!format.isValid()) {
+ return nullptr;
+ }
+
+ sk_sp<GrTextureProxy> proxy;
+ if (kBottomLeft_GrSurfaceOrigin == origin) {
+ // We (soon will) only support using kBottomLeft with wrapped textures.
+ auto backendTex = context->createBackendTexture(
+ width, height, format, SkColors::kTransparent, GrMipMapped::kNo, renderable,
+ GrProtected::kNo);
+ if (!backendTex.isValid()) {
+ return nullptr;
+ }
+
+ // Adopt ownership so our caller doesn't have to worry about deleting the backend texture.
+ if (GrRenderable::kYes == renderable) {
+ proxy = context->priv().proxyProvider()->wrapRenderableBackendTexture(
+ backendTex, origin, 1, colorType, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
+ nullptr, nullptr);
+ } else {
+ proxy = context->priv().proxyProvider()->wrapBackendTexture(
+ backendTex, colorType, origin, kAdopt_GrWrapOwnership,
+ GrWrapCacheable::kNo, kRW_GrIOType);
+ }
+
+ if (!proxy) {
+ context->deleteBackendTexture(backendTex);
+ return nullptr;
+ }
+
+ } else {
+ GrSurfaceDesc desc;
+ desc.fConfig = GrColorTypeToPixelConfig(colorType);
+ desc.fWidth = width;
+ desc.fHeight = height;
+ proxy = context->priv().proxyProvider()->createProxy(format, desc, renderable, 1, origin,
+ GrMipMapped::kNo, SkBackingFit::kExact,
+ SkBudgeted::kYes, GrProtected::kNo);
+ if (!proxy) {
+ return nullptr;
+ }
+ }
+
+ auto sContext = context->priv().makeWrappedSurfaceContext(proxy, colorType, alphaType, nullptr);
+ if (!sContext) {
+ return nullptr;
+ }
+ if (!sContext->writePixels({colorType, alphaType, nullptr, width, height}, data, rowBytes,
+ {0, 0}, context)) {
+ return nullptr;
+ }
+ return proxy;
+}
+
+} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/ProxyUtils.h b/src/third_party/skia/tools/gpu/ProxyUtils.h
new file mode 100644
index 0000000..28eacea
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/ProxyUtils.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef ProxyUtils_DEFINED
+#define ProxyUtils_DEFINED
+
+#include "include/private/GrTypesPriv.h"
+#include "src/gpu/GrTextureProxy.h"
+
+namespace sk_gpu_test {
+
+/** Makes a texture proxy containing the passed in color data. */
+sk_sp<GrTextureProxy> MakeTextureProxyFromData(GrContext*, GrRenderable, int width, int height,
+ GrColorType, SkAlphaType, GrSurfaceOrigin,
+ const void* data, size_t rowBytes);
+
+/** Version that takes SkColorType rather than GrColorType. */
+inline sk_sp<GrTextureProxy> MakeTextureProxyFromData(GrContext* context, GrRenderable renderable,
+ int width, int height, SkColorType ct,
+ SkAlphaType alphaType, GrSurfaceOrigin origin,
+ const void* data, size_t rowBytes) {
+ GrColorType grCT = SkColorTypeToGrColorType(ct);
+ if (GrColorType::kUnknown == grCT) {
+ return nullptr;
+ }
+
+ return MakeTextureProxyFromData(context, renderable, width, height, grCT, alphaType, origin,
+ data, rowBytes);
+}
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/TestContext.cpp b/src/third_party/skia/tools/gpu/TestContext.cpp
index c80c4ea..bf961fb 100644
--- a/src/third_party/skia/tools/gpu/TestContext.cpp
+++ b/src/third_party/skia/tools/gpu/TestContext.cpp
@@ -6,11 +6,11 @@
* found in the LICENSE file.
*/
-#include "TestContext.h"
+#include "tools/gpu/TestContext.h"
-#include "GpuTimer.h"
+#include "tools/gpu/GpuTimer.h"
-#include "GrContext.h"
+#include "include/gpu/GrContext.h"
namespace sk_gpu_test {
TestContext::TestContext()
@@ -37,8 +37,15 @@
void TestContext::makeCurrent() const { this->onPlatformMakeCurrent(); }
+SkScopeExit TestContext::makeCurrentAndAutoRestore() const {
+ auto asr = SkScopeExit(this->onPlatformGetAutoContextRestore());
+ this->makeCurrent();
+ return asr;
+}
+
void TestContext::swapBuffers() { this->onPlatformSwapBuffers(); }
+
void TestContext::waitOnSyncOrSwap() {
if (!fFenceSync) {
// Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
diff --git a/src/third_party/skia/tools/gpu/TestContext.h b/src/third_party/skia/tools/gpu/TestContext.h
index 84794f3..e48c598 100644
--- a/src/third_party/skia/tools/gpu/TestContext.h
+++ b/src/third_party/skia/tools/gpu/TestContext.h
@@ -9,10 +9,12 @@
#ifndef TestContext_DEFINED
#define TestContext_DEFINED
-#include "FenceSync.h"
-#include "GrTypes.h"
-#include "SkRefCnt.h"
-#include "../private/SkTemplates.h"
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/GrTypes.h"
+#include "include/private/SkNoncopyable.h"
+#include "include/private/SkTemplates.h"
+#include "src/core/SkScopeExit.h"
+#include "tools/gpu/FenceSync.h"
class GrContext;
struct GrContextOptions;
@@ -45,8 +47,19 @@
void makeCurrent() const;
- virtual GrBackend backend() = 0;
- virtual GrBackendContext backendContext() = 0;
+ /**
+ * Like makeCurrent() but this returns an object that will restore the previous current
+ * context in its destructor. Useful to undo the effect making this current before returning to
+ * a caller that doesn't expect the current context to be changed underneath it.
+ *
+ * The returned object restores the current context of the same type (e.g. egl, glx, ...) in its
+ * destructor. It is undefined behavior if that context is destroyed before the destructor
+ * executes. If the concept of a current context doesn't make sense for this context type then
+ * the returned object's destructor is a no-op.
+ */
+ SkScopeExit SK_WARN_UNUSED_RESULT makeCurrentAndAutoRestore() const;
+
+ virtual GrBackendApi backend() = 0;
virtual sk_sp<GrContext> makeGrContext(const GrContextOptions&);
@@ -94,6 +107,14 @@
virtual void teardown();
virtual void onPlatformMakeCurrent() const = 0;
+ /**
+ * Subclasses should implement such that the returned function will cause the current context
+ * of this type to be made current again when it is called. It should additionally be the
+ * case that if "this" is already current when this is called, then "this" is destroyed (thereby
+ * setting the null context as current), and then the std::function is called the null context
+ * should remain current.
+ */
+ virtual std::function<void()> onPlatformGetAutoContextRestore() const = 0;
virtual void onPlatformSwapBuffers() const = 0;
private:
diff --git a/src/third_party/skia/tools/gpu/YUVUtils.cpp b/src/third_party/skia/tools/gpu/YUVUtils.cpp
new file mode 100644
index 0000000..eb4ca2c
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/YUVUtils.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/gpu/YUVUtils.h"
+
+#include "include/core/SkData.h"
+#include "include/gpu/GrContext.h"
+#include "src/codec/SkCodecImageGenerator.h"
+#include "src/gpu/GrContextPriv.h"
+
+namespace sk_gpu_test {
+
+std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data) {
+ std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
+ if (image->reset(std::move(data))) {
+ return image;
+ } else {
+ return nullptr;
+ }
+}
+
+sk_sp<SkImage> LazyYUVImage::refImage(GrContext* context) {
+ if (this->ensureYUVImage(context)) {
+ return fYUVImage;
+ } else {
+ return nullptr;
+ }
+}
+
+const SkImage* LazyYUVImage::getImage(GrContext* context) {
+ if (this->ensureYUVImage(context)) {
+ return fYUVImage.get();
+ } else {
+ return nullptr;
+ }
+}
+
+bool LazyYUVImage::reset(sk_sp<SkData> data) {
+ auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
+ if (!codec) {
+ return false;
+ }
+
+ if (!codec->queryYUVA8(&fSizeInfo, fComponents, &fColorSpace)) {
+ return false;
+ }
+
+ fPlaneData.reset(fSizeInfo.computeTotalBytes());
+ void* planes[SkYUVASizeInfo::kMaxCount];
+ fSizeInfo.computePlanes(fPlaneData.get(), planes);
+ if (!codec->getYUVA8Planes(fSizeInfo, fComponents, planes)) {
+ return false;
+ }
+
+ for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
+ if (fSizeInfo.fSizes[i].isEmpty()) {
+ fPlanes[i].reset();
+ } else {
+ SkASSERT(planes[i]);
+ auto planeInfo = SkImageInfo::Make(fSizeInfo.fSizes[i].fWidth,
+ fSizeInfo.fSizes[i].fHeight,
+ kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr);
+ fPlanes[i].reset(planeInfo, planes[i], fSizeInfo.fWidthBytes[i]);
+ }
+ }
+ // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
+ return true;
+}
+
+bool LazyYUVImage::ensureYUVImage(GrContext* context) {
+ if (!context) {
+ return false; // Cannot make a YUV image from planes
+ }
+ if (context->priv().contextID() == fOwningContextID) {
+ return fYUVImage != nullptr; // Have already made a YUV image (or tried and failed)
+ }
+ // Must make a new YUV image
+ fYUVImage = SkImage::MakeFromYUVAPixmaps(context, fColorSpace, fPlanes, fComponents,
+ fSizeInfo.fSizes[0], kTopLeft_GrSurfaceOrigin, false, false);
+ fOwningContextID = context->priv().contextID();
+ return fYUVImage != nullptr;
+}
+
+} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/YUVUtils.h b/src/third_party/skia/tools/gpu/YUVUtils.h
new file mode 100644
index 0000000..f6097b9
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/YUVUtils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef YUVUtils_DEFINED
+#define YUVUtils_DEFINED
+
+#include "include/core/SkImage.h"
+#include "include/core/SkYUVAIndex.h"
+#include "include/core/SkYUVASizeInfo.h"
+#include "src/core/SkAutoMalloc.h"
+
+class SkData;
+
+namespace sk_gpu_test {
+
+// Utility that decodes a JPEG but preserves the YUVA8 planes in the image, and uses
+// MakeFromYUVAPixmaps to create a GPU multiplane YUVA image for a context. It extracts the planar
+// data once, and lazily creates the actual SkImage when the GrContext is provided (and refreshes
+// the image if the context has changed, as in Viewer)
+class LazyYUVImage {
+public:
+ // Returns null if the data could not be extracted into YUVA8 planes
+ static std::unique_ptr<LazyYUVImage> Make(sk_sp<SkData> data);
+
+ sk_sp<SkImage> refImage(GrContext* context);
+
+ const SkImage* getImage(GrContext* context);
+
+private:
+ // Decoded YUV data
+ SkYUVASizeInfo fSizeInfo;
+ SkYUVColorSpace fColorSpace;
+ SkYUVAIndex fComponents[SkYUVAIndex::kIndexCount];
+ SkAutoMalloc fPlaneData;
+ SkPixmap fPlanes[SkYUVASizeInfo::kMaxCount];
+
+ // Memoized SkImage formed with planes
+ sk_sp<SkImage> fYUVImage;
+ uint32_t fOwningContextID;
+
+ LazyYUVImage() : fOwningContextID(SK_InvalidGenID) {}
+
+ bool reset(sk_sp<SkData> data);
+
+ bool ensureYUVImage(GrContext* context);
+};
+
+} // namespace sk_gpu_test
+
+#endif // YUVUtils_DEFINED
diff --git a/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp b/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
new file mode 100644
index 0000000..c8dc054
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkBitmap.h"
+#include "src/gpu/gl/GrGLDefines.h"
+#include "src/gpu/gl/GrGLUtil.h"
+#include "tools/gpu/atlastext/GLTestAtlasTextRenderer.h"
+#include "tools/gpu/atlastext/TestAtlasTextRenderer.h"
+#include "tools/gpu/gl/GLTestContext.h"
+
+using sk_gpu_test::GLTestContext;
+
+namespace {
+
+class GLTestAtlasTextRenderer : public sk_gpu_test::TestAtlasTextRenderer {
+public:
+ GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext>);
+
+ void* createTexture(AtlasFormat, int width, int height) override;
+
+ void deleteTexture(void* textureHandle) override;
+
+ void setTextureData(void* textureHandle, const void* data, int x, int y, int width, int height,
+ size_t rowBytes) override;
+
+ void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],
+ int quadCnt) override;
+
+ void* makeTargetHandle(int width, int height) override;
+
+ void targetDeleted(void* targetHandle) override;
+
+ SkBitmap readTargetHandle(void* targetHandle) override;
+
+ void clearTarget(void* targetHandle, uint32_t color) override;
+
+ bool initialized() const { return 0 != fProgram; }
+
+private:
+ struct AtlasTexture {
+ GrGLuint fID;
+ AtlasFormat fFormat;
+ int fWidth;
+ int fHeight;
+ };
+
+ struct Target {
+ GrGLuint fFBOID;
+ GrGLuint fRBID;
+ int fWidth;
+ int fHeight;
+ };
+
+ std::unique_ptr<GLTestContext> fContext;
+ GrGLuint fProgram = 0;
+ GrGLint fDstScaleAndTranslateLocation = 0;
+ GrGLint fAtlasInvSizeLocation = 0;
+ GrGLint fSamplerLocation = 0;
+};
+
+#define callgl(NAME, ...) fContext->gl()->fFunctions.f##NAME(__VA_ARGS__)
+#define checkgl() \
+ do { \
+ static constexpr auto line = __LINE__; \
+ auto error = fContext->gl()->fFunctions.fGetError(); \
+ if (error != GR_GL_NO_ERROR) { \
+ SkDebugf("GL ERROR: 0x%x, line %d\n", error, line); \
+ } \
+ } while (false)
+
+GLTestAtlasTextRenderer::GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext> context)
+ : fContext(std::move(context)) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ // First check whether the GL is supported so we can avoid spammy failures on systems
+ // where the GL simply doesn't work with this class.
+ const char* versionStr = reinterpret_cast<const char*>(callgl(GetString, GR_GL_VERSION));
+ auto version = GrGLGetVersionFromString(versionStr);
+ auto standard = GrGLGetStandardInUseFromString(versionStr);
+ switch (standard) {
+ case kWebGL_GrGLStandard:
+ case kNone_GrGLStandard:
+ return;
+ case kGLES_GrGLStandard:
+ if (version < GR_GL_VER(3, 0)) {
+ return;
+ }
+ break;
+ case kGL_GrGLStandard: {
+ if (version < GR_GL_VER(4, 3)) {
+ return;
+ }
+ GrGLint profileMask;
+ callgl(GetIntegerv, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
+ if (profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT) {
+ return;
+ }
+ }
+ }
+
+ auto vs = callgl(CreateShader, GR_GL_VERTEX_SHADER);
+ static constexpr char kGLVersionString[] = "#version 430 compatibility";
+ static constexpr char kGLESVersionString[] = "#version 300 es";
+ GrGLint lengths[2];
+ const GrGLchar* strings[2];
+ switch (fContext->gl()->fStandard) {
+ case kGL_GrGLStandard:
+ strings[0] = kGLVersionString;
+ lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLVersionString)) - 1;
+ break;
+ case kGLES_GrGLStandard:
+ strings[0] = kGLESVersionString;
+ lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLESVersionString)) - 1;
+ break;
+ default:
+ strings[0] = nullptr;
+ lengths[0] = 0;
+ break;
+ }
+
+ static constexpr const char kVS[] = R"(
+ uniform vec4 uDstScaleAndTranslate;
+ uniform vec2 uAtlasInvSize;
+
+ layout (location = 0) in vec3 inPosition;
+ layout (location = 1) in vec4 inColor;
+ layout (location = 2) in uvec2 inTextureCoords;
+
+ out vec2 vTexCoord;
+ out vec4 vColor;
+ out vec2 vIntTexCoord;
+
+ void main() {
+ vec2 intCoords;
+ // floor(vec2) doesn't seem to work on some ES devices.
+ intCoords.x = floor(float(inTextureCoords.x));
+ intCoords.y = floor(float(inTextureCoords.y));
+ vTexCoord = intCoords * uAtlasInvSize;
+ vIntTexCoord = intCoords;
+ vColor = inColor;
+ gl_Position = vec4(inPosition.x * uDstScaleAndTranslate.x + uDstScaleAndTranslate.y,
+ inPosition.y * uDstScaleAndTranslate.z + uDstScaleAndTranslate.w,
+ 0.0, inPosition.z);
+ }
+ )";
+ strings[1] = kVS;
+ lengths[1] = SK_ARRAY_COUNT(kVS) - 1;
+ callgl(ShaderSource, vs, 2, strings, lengths);
+ callgl(CompileShader, vs);
+ GrGLint compileStatus;
+ callgl(GetShaderiv, vs, GR_GL_COMPILE_STATUS, &compileStatus);
+ if (compileStatus == GR_GL_FALSE) {
+ GrGLint logLength;
+ callgl(GetShaderiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetShaderInfoLog, vs, logLength, &logLength, log.get());
+ SkDebugf("Vertex Shader failed to compile\n%s", log.get());
+ callgl(DeleteShader, vs);
+ return;
+ }
+
+ auto fs = callgl(CreateShader, GR_GL_FRAGMENT_SHADER);
+ static constexpr const char kFS[] = R"(
+ uniform sampler2D uSampler;
+
+ in vec2 vTexCoord;
+ in vec4 vColor;
+ in vec2 vIntTexCoord;
+
+ layout (location = 0) out vec4 outColor;
+
+ void main() {
+ float sdfValue = texture(uSampler, vTexCoord).r;
+ float distance = 7.96875 * (sdfValue - 0.50196078431000002);
+ vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));
+ vec2 Jdx = dFdx(vIntTexCoord);
+ vec2 Jdy = dFdy(vIntTexCoord);
+ float dg_len2 = dot(dist_grad, dist_grad);
+ if (dg_len2 < 0.0001) {
+ dist_grad = vec2(0.7071, 0.7071);
+ } else {
+ dist_grad = dist_grad * inversesqrt(dg_len2);
+ }
+ vec2 grad = vec2(dist_grad.x * Jdx.x + dist_grad.y * Jdy.x,
+ dist_grad.x * Jdx.y + dist_grad.y * Jdy.y);
+ float afwidth = abs(0.65000000000000002 * length(grad));
+ float value = smoothstep(-afwidth, afwidth, distance);
+ outColor = value * vec4(vColor.rgb * vColor.a, vColor.a);
+ }
+ )";
+ strings[1] = kFS;
+ lengths[1] = SK_ARRAY_COUNT(kFS) - 1;
+ callgl(ShaderSource, fs, 2, strings, lengths);
+ callgl(CompileShader, fs);
+ callgl(GetShaderiv, fs, GR_GL_COMPILE_STATUS, &compileStatus);
+ if (compileStatus == GR_GL_FALSE) {
+ GrGLint logLength;
+ callgl(GetShaderiv, fs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetShaderInfoLog, fs, logLength, &logLength, log.get());
+ SkDebugf("Fragment Shader failed to compile\n%s", log.get());
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ return;
+ }
+
+ fProgram = callgl(CreateProgram);
+ if (!fProgram) {
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ return;
+ }
+
+ callgl(AttachShader, fProgram, vs);
+ callgl(AttachShader, fProgram, fs);
+ callgl(LinkProgram, fProgram);
+ GrGLint linkStatus;
+ callgl(GetProgramiv, fProgram, GR_GL_LINK_STATUS, &linkStatus);
+ if (linkStatus == GR_GL_FALSE) {
+ GrGLint logLength = 0;
+ callgl(GetProgramiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetProgramInfoLog, vs, logLength, &logLength, log.get());
+ SkDebugf("Program failed to link\n%s", log.get());
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ callgl(DeleteProgram, fProgram);
+ fProgram = 0;
+ return;
+ }
+ fDstScaleAndTranslateLocation = callgl(GetUniformLocation, fProgram, "uDstScaleAndTranslate");
+ fAtlasInvSizeLocation = callgl(GetUniformLocation, fProgram, "uAtlasInvSize");
+ fSamplerLocation = callgl(GetUniformLocation, fProgram, "uSampler");
+ if (fDstScaleAndTranslateLocation < 0 || fAtlasInvSizeLocation < 0 || fSamplerLocation < 0) {
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ callgl(DeleteProgram, fProgram);
+ fProgram = 0;
+ }
+
+ checkgl();
+}
+
+inline bool atlas_format_to_gl_types(SkAtlasTextRenderer::AtlasFormat format,
+ GrGLenum* internalFormat, GrGLenum* externalFormat,
+ GrGLenum* type) {
+ switch (format) {
+ case SkAtlasTextRenderer::AtlasFormat::kA8:
+ *internalFormat = GR_GL_R8;
+ *externalFormat = GR_GL_RED;
+ *type = GR_GL_UNSIGNED_BYTE;
+ return true;
+ }
+ return false;
+}
+
+inline int atlas_format_bytes_per_pixel(SkAtlasTextRenderer::AtlasFormat format) {
+ switch (format) {
+ case SkAtlasTextRenderer::AtlasFormat::kA8:
+ return 1;
+ }
+ return 0;
+}
+
+void* GLTestAtlasTextRenderer::createTexture(AtlasFormat format, int width, int height) {
+ GrGLenum internalFormat;
+ GrGLenum externalFormat;
+ GrGLenum type;
+ if (!atlas_format_to_gl_types(format, &internalFormat, &externalFormat, &type)) {
+ return nullptr;
+ }
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ GrGLuint id;
+ callgl(GenTextures, 1, &id);
+ if (!id) {
+ return nullptr;
+ }
+
+ callgl(BindTexture, GR_GL_TEXTURE_2D, id);
+ callgl(TexImage2D, GR_GL_TEXTURE_2D, 0, internalFormat, width, height, 0, externalFormat, type,
+ nullptr);
+ checkgl();
+
+ AtlasTexture* atlas = new AtlasTexture;
+ atlas->fID = id;
+ atlas->fFormat = format;
+ atlas->fWidth = width;
+ atlas->fHeight = height;
+ return atlas;
+}
+
+void GLTestAtlasTextRenderer::deleteTexture(void* textureHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto* atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ callgl(DeleteTextures, 1, &atlasTexture->fID);
+ checkgl();
+
+ delete atlasTexture;
+}
+
+void GLTestAtlasTextRenderer::setTextureData(void* textureHandle, const void* data, int x, int y,
+ int width, int height, size_t rowBytes) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ GrGLenum internalFormat;
+ GrGLenum externalFormat;
+ GrGLenum type;
+ if (!atlas_format_to_gl_types(atlasTexture->fFormat, &internalFormat, &externalFormat, &type)) {
+ return;
+ }
+ int bpp = atlas_format_bytes_per_pixel(atlasTexture->fFormat);
+ GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
+ if (static_cast<size_t>(rowLength * bpp) != rowBytes) {
+ return;
+ }
+ callgl(PixelStorei, GR_GL_UNPACK_ALIGNMENT, 1);
+ callgl(PixelStorei, GR_GL_UNPACK_ROW_LENGTH, rowLength);
+ callgl(BindTexture, GR_GL_TEXTURE_2D, atlasTexture->fID);
+ callgl(TexSubImage2D, GR_GL_TEXTURE_2D, 0, x, y, width, height, externalFormat, type, data);
+ checkgl();
+}
+
+void GLTestAtlasTextRenderer::drawSDFGlyphs(void* targetHandle, void* textureHandle,
+ const SDFVertex vertices[], int quadCnt) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto target = reinterpret_cast<const Target*>(targetHandle);
+ auto atlas = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ callgl(UseProgram, fProgram);
+
+ callgl(ActiveTexture, GR_GL_TEXTURE0);
+ callgl(BindTexture, GR_GL_TEXTURE_2D, atlas->fID);
+ callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_LINEAR);
+ callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_LINEAR);
+
+ float uniformScaleAndTranslate[4] = {2.f / target->fWidth, -1.f, 2.f / target->fHeight, -1.f};
+ callgl(Uniform4fv, fDstScaleAndTranslateLocation, 1, uniformScaleAndTranslate);
+ callgl(Uniform2f, fAtlasInvSizeLocation, 1.f / atlas->fWidth, 1.f / atlas->fHeight);
+ callgl(Uniform1i, fSamplerLocation, 0);
+
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(Viewport, 0, 0, target->fWidth, target->fHeight);
+
+ callgl(Enable, GR_GL_BLEND);
+ callgl(BlendFunc, GR_GL_ONE, GR_GL_ONE_MINUS_SRC_ALPHA);
+ callgl(Disable, GR_GL_DEPTH_TEST);
+
+ callgl(BindVertexArray, 0);
+ callgl(BindBuffer, GR_GL_ARRAY_BUFFER, 0);
+ callgl(BindBuffer, GR_GL_ELEMENT_ARRAY_BUFFER, 0);
+ callgl(VertexAttribPointer, 0, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(SDFVertex), vertices);
+ size_t colorOffset = 3 * sizeof(float);
+ callgl(VertexAttribPointer, 1, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, sizeof(SDFVertex),
+ reinterpret_cast<const char*>(vertices) + colorOffset);
+ size_t texOffset = colorOffset + sizeof(uint32_t);
+ callgl(VertexAttribIPointer, 2, 2, GR_GL_UNSIGNED_SHORT, sizeof(SDFVertex),
+ reinterpret_cast<const char*>(vertices) + texOffset);
+ callgl(EnableVertexAttribArray, 0);
+ callgl(EnableVertexAttribArray, 1);
+ callgl(EnableVertexAttribArray, 2);
+
+ std::unique_ptr<uint16_t[]> indices(new uint16_t[quadCnt * 6]);
+ for (int q = 0; q < quadCnt; ++q) {
+ indices[q * 6 + 0] = 0 + 4 * q;
+ indices[q * 6 + 1] = 1 + 4 * q;
+ indices[q * 6 + 2] = 2 + 4 * q;
+ indices[q * 6 + 3] = 2 + 4 * q;
+ indices[q * 6 + 4] = 1 + 4 * q;
+ indices[q * 6 + 5] = 3 + 4 * q;
+ }
+ callgl(DrawElements, GR_GL_TRIANGLES, 6 * quadCnt, GR_GL_UNSIGNED_SHORT, indices.get());
+ checkgl();
+}
+
+void* GLTestAtlasTextRenderer::makeTargetHandle(int width, int height) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ GrGLuint fbo;
+ callgl(GenFramebuffers, 1, &fbo);
+ if (!fbo) {
+ return nullptr;
+ }
+ GrGLuint rb;
+ callgl(GenRenderbuffers, 1, &rb);
+ if (!rb) {
+ callgl(DeleteFramebuffers, 1, &fbo);
+ return nullptr;
+ }
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, fbo);
+ callgl(BindRenderbuffer, GR_GL_RENDERBUFFER, rb);
+ callgl(RenderbufferStorage, GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height);
+ callgl(FramebufferRenderbuffer, GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER,
+ rb);
+ GrGLenum status = callgl(CheckFramebufferStatus, GR_GL_FRAMEBUFFER);
+ if (GR_GL_FRAMEBUFFER_COMPLETE != status) {
+ callgl(DeleteFramebuffers, 1, &fbo);
+ callgl(DeleteRenderbuffers, 1, &rb);
+ return nullptr;
+ }
+ callgl(Disable, GR_GL_SCISSOR_TEST);
+ callgl(ClearColor, 0, 0, 0, 0.0);
+ callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
+ checkgl();
+ Target* target = new Target;
+ target->fFBOID = fbo;
+ target->fRBID = rb;
+ target->fWidth = width;
+ target->fHeight = height;
+ return target;
+}
+
+void GLTestAtlasTextRenderer::targetDeleted(void* targetHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+ callgl(DeleteFramebuffers, 1, &target->fFBOID);
+ callgl(DeleteRenderbuffers, 1, &target->fRBID);
+ delete target;
+}
+
+SkBitmap GLTestAtlasTextRenderer::readTargetHandle(void* targetHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+
+ auto info =
+ SkImageInfo::Make(target->fWidth, target->fHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ SkBitmap bmp;
+ bmp.setInfo(info, sizeof(uint32_t) * target->fWidth);
+ bmp.allocPixels();
+
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(ReadPixels, 0, 0, target->fWidth, target->fHeight, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
+ bmp.getPixels());
+ checkgl();
+ return bmp;
+}
+
+void GLTestAtlasTextRenderer::clearTarget(void* targetHandle, uint32_t color) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(Disable, GR_GL_SCISSOR_TEST);
+ float r = ((color >> 0) & 0xff) / 255.f;
+ float g = ((color >> 8) & 0xff) / 255.f;
+ float b = ((color >> 16) & 0xff) / 255.f;
+ float a = ((color >> 24) & 0xff) / 255.f;
+ callgl(ClearColor, r, g, b, a);
+ callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
+}
+
+} // anonymous namespace
+
+namespace sk_gpu_test {
+
+sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer() {
+ std::unique_ptr<GLTestContext> context(CreatePlatformGLTestContext(kGL_GrGLStandard));
+ if (!context) {
+ context.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
+ }
+ if (!context) {
+ return nullptr;
+ }
+ auto restorer = context->makeCurrentAndAutoRestore();
+ auto renderer = sk_make_sp<GLTestAtlasTextRenderer>(std::move(context));
+ return renderer->initialized() ? std::move(renderer) : nullptr;
+}
+
+} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h b/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
new file mode 100644
index 0000000..d1536d3
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GLTestAtlasTextRenderer_DEFINED
+#define GLTestAtlasTextRenderer_DEFINED
+
+#include "include/core/SkRefCnt.h"
+
+namespace sk_gpu_test {
+
+class TestAtlasTextRenderer;
+
+/**
+ * Creates a TestAtlasTextRenderer that uses its own OpenGL context to implement
+ * SkAtlasTextRenderer.
+ */
+sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer();
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h b/src/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
new file mode 100644
index 0000000..e928e76
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TestAtlasTextRenderer_DEFINED
+#define TestAtlasTextRenderer_DEFINED
+
+#include "include/atlastext/SkAtlasTextRenderer.h"
+#include "include/core/SkBitmap.h"
+
+namespace sk_gpu_test {
+
+class TestContext;
+
+/**
+ * Base class for implementations of SkAtlasTextRenderer in order to test the SkAtlasText APIs.
+ * Adds a helper for creating SkAtlasTextTargets and to read back the contents of a target as a
+ * bitmap.
+ */
+class TestAtlasTextRenderer : public SkAtlasTextRenderer {
+public:
+ /** Returns a handle that can be used to construct a SkAtlasTextTarget instance. */
+ virtual void* makeTargetHandle(int width, int height) = 0;
+
+ /** Makes a SkBitmap of the target handle's contents. */
+ virtual SkBitmap readTargetHandle(void* targetHandle) = 0;
+
+ /** Clears the target to the specified color, encoded as RGBA (low to high byte order) */
+ virtual void clearTarget(void* targetHandle, uint32_t color) = 0;
+};
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp b/src/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp
new file mode 100644
index 0000000..666ea6c
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "dawn/dawncpp.h"
+#include "dawn_native/DawnNative.h"
+#include "tools/gpu/dawn/DawnTestContext.h"
+
+#ifdef SK_BUILD_FOR_UNIX
+#include "GL/glx.h"
+#endif
+
+#ifdef SK_BUILD_FOR_WIN
+#include <windows.h>
+#endif
+
+#define USE_OPENGL_BACKEND 0
+
+#ifdef SK_DAWN
+#include "dawn/dawn.h"
+#include "dawn/dawn_proc.h"
+#include "include/gpu/GrContext.h"
+#include "tools/AutoreleasePool.h"
+#if USE_OPENGL_BACKEND
+#include "dawn_native/OpenGLBackend.h"
+#endif
+
+#if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND
+#include <dlfcn.h>
+static void* getProcAddressMacOS(const char* procName) {
+ return dlsym(RTLD_DEFAULT, procName);
+}
+#endif
+
+namespace {
+
+#ifdef SK_BUILD_FOR_WIN
+class ProcGetter {
+public:
+ typedef void(*Proc)();
+
+ ProcGetter()
+ : fModule(LoadLibraryA("opengl32.dll")) {
+ SkASSERT(!fInstance);
+ fInstance = this;
+ }
+
+ ~ProcGetter() {
+ if (fModule) {
+ FreeLibrary(fModule);
+ }
+ fInstance = nullptr;
+ }
+
+ static void* getProcAddress(const char* name) {
+ return fInstance->getProc(name);
+ }
+
+private:
+ Proc getProc(const char* name) {
+ PROC proc;
+ if (proc = GetProcAddress(fModule, name)) {
+ return (Proc) proc;
+ }
+ if (proc = wglGetProcAddress(name)) {
+ return (Proc) proc;
+ }
+ return nullptr;
+ }
+
+ HMODULE fModule;
+ static ProcGetter* fInstance;
+};
+
+ProcGetter* ProcGetter::fInstance;
+#endif
+
+class DawnFence {
+public:
+ DawnFence(const dawn::Device& device, const dawn::Buffer& buffer)
+ : fDevice(device), fBuffer(buffer), fCalled(false) {
+ fBuffer.MapReadAsync(callback, this);
+ }
+
+ bool wait() {
+ while (!fCalled) {
+ fDevice.Tick();
+ }
+ return true;
+ }
+
+ ~DawnFence() {
+ }
+
+ static void callback(DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength,
+ void* userData) {
+ DawnFence* fence = static_cast<DawnFence*>(userData);
+ fence->fCalled = true;
+ }
+ dawn::Buffer buffer() { return fBuffer; }
+
+private:
+ dawn::Device fDevice;
+ dawn::Buffer fBuffer;
+ bool fCalled;
+};
+
+/**
+ * Implements sk_gpu_test::FenceSync for Dawn.
+ */
+class DawnFenceSync : public sk_gpu_test::FenceSync {
+public:
+ DawnFenceSync(dawn::Device device) : fDevice(device) {
+ }
+
+ ~DawnFenceSync() override {
+ }
+
+ sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
+ dawn::Buffer buffer;
+ if (fBuffers.empty()) {
+ dawn::BufferDescriptor desc;
+ desc.usage = dawn::BufferUsage::MapRead | dawn::BufferUsage::CopyDst;
+ desc.size = 1;
+ buffer = fDevice.CreateBuffer(&desc);
+ } else {
+ buffer = fBuffers.back();
+ fBuffers.pop_back();
+ }
+ DawnFence* fence = new DawnFence(fDevice, buffer);
+ return reinterpret_cast<sk_gpu_test::PlatformFence>(fence);
+ }
+
+ bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ fAutoreleasePool.drain();
+ DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
+ return fence->wait();
+ }
+
+ void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
+ fBuffers.push_back(fence->buffer());
+ delete fence;
+ }
+
+private:
+ dawn::Device fDevice;
+ mutable std::vector<dawn::Buffer> fBuffers;
+ mutable AutoreleasePool fAutoreleasePool;
+ typedef sk_gpu_test::FenceSync INHERITED;
+};
+
+class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
+public:
+ static dawn::Device createDevice(const dawn_native::Instance& instance,
+ dawn_native::BackendType type) {
+ DawnProcTable backendProcs = dawn_native::GetProcs();
+ dawnProcSetProcs(&backendProcs);
+
+ std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
+ for (dawn_native::Adapter adapter : adapters) {
+ if (adapter.GetBackendType() == type) {
+ return adapter.CreateDevice();
+ }
+ }
+ return nullptr;
+ }
+
+ static DawnTestContext* Create(DawnTestContext* sharedContext) {
+ std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
+ dawn::Device device;
+ if (sharedContext) {
+ device = sharedContext->getDevice();
+ } else {
+ dawn_native::BackendType type;
+#if USE_OPENGL_BACKEND
+ dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
+ adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>(
+#if defined(SK_BUILD_FOR_UNIX)
+ glXGetProcAddress
+#elif defined(SK_BUILD_FOR_MAC)
+ getProcAddressMacOS
+#elif defined(SK_BUILD_FOR_WIN)
+ ProcGetter::getProcAddress
+#endif
+ );
+ instance->DiscoverAdapters(&adapterOptions);
+ type = dawn_native::BackendType::OpenGL;
+#else
+ instance->DiscoverDefaultAdapters();
+#if defined(SK_BUILD_FOR_MAC)
+ type = dawn_native::BackendType::Metal;
+#elif defined(SK_BUILD_FOR_WIN)
+ type = dawn_native::BackendType::D3D12;
+#elif defined(SK_BUILD_FOR_UNIX)
+ type = dawn_native::BackendType::Vulkan;
+#endif
+#endif
+ device = createDevice(*instance, type);
+ }
+ if (!device) {
+ return nullptr;
+ }
+ return new DawnTestContextImpl(std::move(instance), device);
+ }
+
+ ~DawnTestContextImpl() override { this->teardown(); }
+
+ void testAbandon() override {}
+
+ // There is really nothing to here since we don't own any unqueued command buffers here.
+ void submit() override {}
+
+ void finish() override {}
+
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
+ return GrContext::MakeDawn(fDevice, options);
+ }
+
+protected:
+ void teardown() override {
+ INHERITED::teardown();
+ }
+
+private:
+ DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
+ const dawn::Device& device)
+ : DawnTestContext(device)
+ , fInstance(std::move(instance)) {
+ fFenceSync.reset(new DawnFenceSync(fDevice));
+ }
+
+ void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
+ void onPlatformSwapBuffers() const override {}
+ std::unique_ptr<dawn_native::Instance> fInstance;
+
+ typedef sk_gpu_test::DawnTestContext INHERITED;
+};
+} // anonymous namespace
+
+namespace sk_gpu_test {
+DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
+ return DawnTestContextImpl::Create(sharedContext);
+}
+} // namespace sk_gpu_test
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/dawn/DawnTestContext.h b/src/third_party/skia/tools/gpu/dawn/DawnTestContext.h
new file mode 100644
index 0000000..4afd018
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/dawn/DawnTestContext.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef DawnTestContext_DEFINED
+#define DawnTestContext_DEFINED
+
+#include "tools/gpu/TestContext.h"
+
+#ifdef SK_DAWN
+
+namespace sk_gpu_test {
+class DawnTestContext : public TestContext {
+public:
+ virtual GrBackend backend() override { return GrBackendApi::kDawn; }
+
+ const dawn::Device& getDevice() {
+ return fDevice;
+ }
+
+protected:
+ DawnTestContext(const dawn::Device& device) : fDevice(device) {}
+
+ dawn::Device fDevice;
+
+private:
+ typedef TestContext INHERITED;
+};
+
+/**
+ * Creates Dawn context object bound to the Dawn library.
+ */
+DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext*);
+
+} // namespace sk_gpu_test
+
+#endif
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/gl/GLTestContext.cpp b/src/third_party/skia/tools/gpu/gl/GLTestContext.cpp
index abbb8a6..d4aa605 100644
--- a/src/third_party/skia/tools/gpu/gl/GLTestContext.cpp
+++ b/src/third_party/skia/tools/gpu/gl/GLTestContext.cpp
@@ -5,16 +5,17 @@
* found in the LICENSE file.
*/
-#include "GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
-#include "GpuTimer.h"
-#include "gl/GrGLUtil.h"
+#include "include/gpu/GrContext.h"
+#include "src/gpu/gl/GrGLUtil.h"
+#include "tools/gpu/GpuTimer.h"
namespace {
class GLFenceSync : public sk_gpu_test::FenceSync {
public:
- static std::unique_ptr<GLFenceSync> MakeIfSupported(const sk_gpu_test::GLTestContext*);
+ static std::unique_ptr<FenceSync> MakeIfSupported(const sk_gpu_test::GLTestContext*);
sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override;
bool waitFence(sk_gpu_test::PlatformFence fence) const override;
@@ -23,7 +24,7 @@
private:
GLFenceSync(const sk_gpu_test::GLTestContext*, const char* ext = "");
- bool validate() { return fGLFenceSync && fGLClientWaitSync && fGLDeleteSync; }
+ bool validate() const override { return fGLFenceSync && fGLClientWaitSync && fGLDeleteSync; }
static constexpr GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117;
static constexpr GrGLenum GL_WAIT_FAILED = 0x911d;
@@ -43,8 +44,37 @@
typedef FenceSync INHERITED;
};
-std::unique_ptr<GLFenceSync> GLFenceSync::MakeIfSupported(const sk_gpu_test::GLTestContext* ctx) {
- std::unique_ptr<GLFenceSync> ret;
+class GLNVFenceSync : public sk_gpu_test::FenceSync {
+public:
+ GLNVFenceSync(const sk_gpu_test::GLTestContext*);
+
+ sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override;
+ bool waitFence(sk_gpu_test::PlatformFence fence) const override;
+ void deleteFence(sk_gpu_test::PlatformFence fence) const override;
+
+private:
+ bool validate() const override {
+ return fGLGenFencesNV && fGLDeleteFencesNV && fGLSetFenceNV && fGLFinishFenceNV;
+ }
+
+ static constexpr GrGLenum GL_ALL_COMPLETED_NV = 0x84F2;
+
+ typedef GrGLvoid(GR_GL_FUNCTION_TYPE* GLGenFencesNVProc) (GrGLsizei, GrGLuint*);
+ typedef GrGLvoid(GR_GL_FUNCTION_TYPE* GLDeleteFencesNVProc) (GrGLsizei, const GrGLuint*);
+ typedef GrGLvoid(GR_GL_FUNCTION_TYPE* GLSetFenceNVProc) (GrGLuint, GrGLenum);
+ typedef GrGLvoid(GR_GL_FUNCTION_TYPE* GLFinishFenceNVProc) (GrGLuint);
+
+ GLGenFencesNVProc fGLGenFencesNV;
+ GLDeleteFencesNVProc fGLDeleteFencesNV;
+ GLSetFenceNVProc fGLSetFenceNV;
+ GLFinishFenceNVProc fGLFinishFenceNV;
+
+ typedef FenceSync INHERITED;
+};
+
+std::unique_ptr<sk_gpu_test::FenceSync> GLFenceSync::MakeIfSupported(
+ const sk_gpu_test::GLTestContext* ctx) {
+ std::unique_ptr<FenceSync> ret;
if (kGL_GrGLStandard == ctx->gl()->fStandard) {
if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync")) {
return nullptr;
@@ -53,6 +83,8 @@
} else {
if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
ret.reset(new GLFenceSync(ctx, "APPLE"));
+ } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
+ ret.reset(new GLNVFenceSync(ctx));
} else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
ret.reset(new GLFenceSync(ctx));
} else {
@@ -66,9 +98,9 @@
}
GLFenceSync::GLFenceSync(const sk_gpu_test::GLTestContext* ctx, const char* ext) {
- ctx->getGLProcAddress(&fGLFenceSync, "glFenceSync");
- ctx->getGLProcAddress(&fGLClientWaitSync, "glClientWaitSync");
- ctx->getGLProcAddress(&fGLDeleteSync, "glDeleteSync");
+ ctx->getGLProcAddress(&fGLFenceSync, "glFenceSync", ext);
+ ctx->getGLProcAddress(&fGLClientWaitSync, "glClientWaitSync", ext);
+ ctx->getGLProcAddress(&fGLDeleteSync, "glDeleteSync", ext);
}
sk_gpu_test::PlatformFence GLFenceSync::insertFence() const {
@@ -86,6 +118,30 @@
fGLDeleteSync(glsync);
}
+GLNVFenceSync::GLNVFenceSync(const sk_gpu_test::GLTestContext* ctx) {
+ ctx->getGLProcAddress(&fGLGenFencesNV, "glGenFencesNV");
+ ctx->getGLProcAddress(&fGLDeleteFencesNV, "glDeleteFencesNV");
+ ctx->getGLProcAddress(&fGLSetFenceNV, "glSetFenceNV");
+ ctx->getGLProcAddress(&fGLFinishFenceNV, "glFinishFenceNV");
+}
+
+sk_gpu_test::PlatformFence GLNVFenceSync::insertFence() const {
+ GrGLuint fence;
+ fGLGenFencesNV(1, &fence);
+ fGLSetFenceNV(fence, GL_ALL_COMPLETED_NV);
+ return fence;
+}
+
+bool GLNVFenceSync::waitFence(sk_gpu_test::PlatformFence fence) const {
+ fGLFinishFenceNV(fence);
+ return true;
+}
+
+void GLNVFenceSync::deleteFence(sk_gpu_test::PlatformFence fence) const {
+ GrGLuint glFence = static_cast<GrGLuint>(fence);
+ fGLDeleteFencesNV(1, &glFence);
+}
+
class GLGpuTimer : public sk_gpu_test::GpuTimer {
public:
static std::unique_ptr<GLGpuTimer> MakeIfSupported(const sk_gpu_test::GLTestContext*);
@@ -228,9 +284,8 @@
SkASSERT(nullptr == fGL.get());
}
-void GLTestContext::init(const GrGLInterface* gl, std::unique_ptr<FenceSync> fenceSync) {
- SkASSERT(!fGL.get());
- fGL.reset(gl);
+void GLTestContext::init(sk_sp<const GrGLInterface> gl, std::unique_ptr<FenceSync> fenceSync) {
+ fGL = std::move(gl);
fFenceSync = fenceSync ? std::move(fenceSync) : GLFenceSync::MakeIfSupported(this);
fGpuTimer = GLGpuTimer::MakeIfSupported(this);
}
@@ -259,11 +314,14 @@
}
}
-GrGLint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat,
- GrGLenum externalFormat, GrGLenum externalType,
- GrGLvoid* data) {
- if (!(kGL_GrGLStandard == fGL->fStandard && GrGLGetVersion(fGL.get()) >= GR_GL_VER(3, 1)) &&
- !fGL->fExtensions.has("GL_ARB_texture_rectangle")) {
+GrGLuint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat,
+ GrGLenum externalFormat, GrGLenum externalType,
+ GrGLvoid* data) {
+ // Should match GrGLCaps check for fRectangleTextureSupport.
+ if (kGL_GrGLStandard != fGL->fStandard ||
+ (GrGLGetVersion(fGL.get()) < GR_GL_VER(3, 1) &&
+ !fGL->fExtensions.has("GL_ARB_texture_rectangle") &&
+ !fGL->fExtensions.has("GL_ANGLE_texture_rectangle"))) {
return 0;
}
@@ -286,4 +344,9 @@
externalFormat, externalType, data));
return id;
}
+
+sk_sp<GrContext> GLTestContext::makeGrContext(const GrContextOptions& options) {
+ return GrContext::MakeGL(fGL, options);
+}
+
} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/gl/GLTestContext.h b/src/third_party/skia/tools/gpu/gl/GLTestContext.h
index f5afa31..197148c 100644
--- a/src/third_party/skia/tools/gpu/gl/GLTestContext.h
+++ b/src/third_party/skia/tools/gpu/gl/GLTestContext.h
@@ -8,8 +8,8 @@
#ifndef GLTestContext_DEFINED
#define GLTestContext_DEFINED
-#include "TestContext.h"
-#include "gl/GrGLInterface.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/gpu/TestContext.h"
namespace sk_gpu_test {
/**
@@ -20,24 +20,20 @@
public:
~GLTestContext() override;
- virtual GrBackend backend() override { return kOpenGL_GrBackend; }
- virtual GrBackendContext backendContext() override {
- return reinterpret_cast<GrBackendContext>(fGL.get());
- }
+ virtual GrBackendApi backend() override { return GrBackendApi::kOpenGL; }
bool isValid() const { return SkToBool(this->gl()); }
- const GrGLInterface *gl() const { return fGL.get(); }
+ const GrGLInterface* gl() const { return fGL.get(); }
/** Used for testing EGLImage integration. Take a GL_TEXTURE_2D and wraps it in an EGL Image */
- virtual GrEGLImage texture2DToEGLImage(GrGLuint /*texID*/) const { return 0; }
+ virtual GrEGLImage texture2DToEGLImage(GrGLuint /*texID*/) const { return nullptr; }
virtual void destroyEGLImage(GrEGLImage) const { }
/** Used for testing GL_TEXTURE_RECTANGLE integration. */
- GrGLint createTextureRectangle(int width, int height, GrGLenum internalFormat,
- GrGLenum externalFormat, GrGLenum externalType,
- GrGLvoid *data);
+ GrGLuint createTextureRectangle(int width, int height, GrGLenum internalFormat,
+ GrGLenum externalFormat, GrGLenum externalType, GrGLvoid* data);
/**
* Used for testing EGLImage integration. Takes a EGLImage and wraps it in a
@@ -64,7 +60,7 @@
const char* name, const char* ext = nullptr) const {
using Proc = Ret(GR_GL_FUNCTION_TYPE*)(Args...);
if (!SkStrStartsWith(name, "gl")) {
- SkFAIL("getGLProcAddress: proc name must have 'gl' prefix");
+ SK_ABORT("getGLProcAddress: proc name must have 'gl' prefix");
*out = nullptr;
} else if (ext) {
SkString fullname(name);
@@ -75,13 +71,15 @@
}
}
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override;
+
protected:
GLTestContext();
/*
* Methods that sublcasses must call from their constructors and destructors.
*/
- void init(const GrGLInterface *, std::unique_ptr<FenceSync> = nullptr);
+ void init(sk_sp<const GrGLInterface>, std::unique_ptr<FenceSync> = nullptr);
void teardown() override;
diff --git a/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp b/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
index 52cc512..c7c9149 100644
--- a/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
+++ b/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
@@ -5,17 +5,22 @@
* found in the LICENSE file.
*/
-#include "GLTestContext_angle.h"
+#include "tools/gpu/gl/angle/GLTestContext_angle.h"
+
+#define EGL_EGL_PROTOTYPES 1
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "gl/GrGLDefines.h"
-#include "gl/GrGLUtil.h"
+#include "src/gpu/gl/GrGLDefines.h"
+#include "src/gpu/gl/GrGLUtil.h"
-#include "gl/GrGLInterface.h"
-#include "gl/GrGLAssembleInterface.h"
-#include "../ports/SkOSLibrary.h"
+#include "include/core/SkTime.h"
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "src/core/SkTraceEvent.h"
+#include "src/ports/SkOSLibrary.h"
+#include "third_party/externals/angle2/include/platform/Platform.h"
#include <EGL/egl.h>
@@ -34,6 +39,16 @@
void* fEGLLib;
};
+std::function<void()> context_restorer() {
+ auto display = eglGetCurrentDisplay();
+ auto dsurface = eglGetCurrentSurface(EGL_DRAW);
+ auto rsurface = eglGetCurrentSurface(EGL_READ);
+ auto context = eglGetCurrentContext();
+ return [display, dsurface, rsurface, context] {
+ eglMakeCurrent(display, dsurface, rsurface, context);
+ };
+}
+
static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
const Libs* libs = reinterpret_cast<const Libs*>(ctx);
GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
@@ -87,6 +102,7 @@
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
@@ -96,6 +112,11 @@
ANGLEBackend fType;
ANGLEContextVersion fVersion;
+ angle::ResetDisplayPlatformFunc fResetPlatform = nullptr;
+
+ PFNEGLCREATEIMAGEKHRPROC fCreateImage = nullptr;
+ PFNEGLDESTROYIMAGEKHRPROC fDestroyImage = nullptr;
+
#ifdef SK_BUILD_FOR_WIN
HWND fWindow;
HDC fDeviceContext;
@@ -105,8 +126,53 @@
#ifdef SK_BUILD_FOR_WIN
ATOM ANGLEGLContext::gWC = 0;
+
+enum class IsWine { kUnknown, kNo, kYes };
+
+static IsWine is_wine() {
+ HMODULE ntdll = GetModuleHandle("ntdll.dll");
+ if (!ntdll) {
+ SkDebugf("No ntdll.dll on Windows?!\n");
+ return IsWine::kUnknown;
+ }
+ return GetProcAddress(ntdll, "wine_get_version") == nullptr ? IsWine::kNo : IsWine::kYes;
+}
+
#endif
+static const unsigned char* ANGLE_getTraceCategoryEnabledFlag(angle::PlatformMethods* platform,
+ const char* category_group) {
+ return SkEventTracer::GetInstance()->getCategoryGroupEnabled(category_group);
+}
+
+static angle::TraceEventHandle ANGLE_addTraceEvent(angle::PlatformMethods* platform,
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ double timestamp,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ unsigned char flags) {
+ static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "Non-64-bit trace event args!");
+ return SkEventTracer::GetInstance()->addTraceEvent(
+ phase, category_group_enabled, name, id, num_args, arg_names, arg_types,
+ reinterpret_cast<const uint64_t*>(arg_values), flags);
+}
+
+static void ANGLE_updateTraceEventDuration(angle::PlatformMethods* platform,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ angle::TraceEventHandle handle) {
+ SkEventTracer::GetInstance()->updateTraceEventDuration(category_group_enabled, name, handle);
+}
+
+static double ANGLE_monotonicallyIncreasingTime(angle::PlatformMethods* platform) {
+ return SkTime::GetSecs();
+}
+
ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
ANGLEGLContext* shareContext, void* display)
: fContext(EGL_NO_CONTEXT)
@@ -118,6 +184,14 @@
fWindow = nullptr;
fDeviceContext = nullptr;
+ static IsWine gIsWine = is_wine();
+ if (gIsWine == IsWine::kYes && type != ANGLEBackend::kOpenGL) {
+ // D3D backends of ANGLE don't really work well under Wine with our tests and are likely to
+ // crash. This makes it easier to test using the GL ANGLE backend under Wine on Linux
+ // without lots of spurious Wine debug spew and crashes.
+ return;
+ }
+
if (EGL_NO_DISPLAY == fDisplay) {
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr);
@@ -167,6 +241,24 @@
return;
}
+ // Add ANGLE platform hooks to connect to Skia's tracing implementation
+ angle::GetDisplayPlatformFunc getPlatform = reinterpret_cast<angle::GetDisplayPlatformFunc>(
+ eglGetProcAddress("ANGLEGetDisplayPlatform"));
+ if (getPlatform) {
+ fResetPlatform = reinterpret_cast<angle::ResetDisplayPlatformFunc>(
+ eglGetProcAddress("ANGLEResetDisplayPlatform"));
+ SkASSERT(fResetPlatform);
+
+ angle::PlatformMethods* platformMethods = nullptr;
+ if (getPlatform(fDisplay, angle::g_PlatformMethodNames, angle::g_NumPlatformMethods,
+ nullptr, &platformMethods)) {
+ platformMethods->addTraceEvent = ANGLE_addTraceEvent;
+ platformMethods->getTraceCategoryEnabledFlag = ANGLE_getTraceCategoryEnabledFlag;
+ platformMethods->updateTraceEventDuration = ANGLE_updateTraceEventDuration;
+ platformMethods->monotonicallyIncreasingTime = ANGLE_monotonicallyIncreasingTime;
+ }
+ }
+
EGLint majorVersion;
EGLint minorVersion;
if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
@@ -214,13 +306,14 @@
fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
+ SkScopeExit restorer(context_restorer());
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Could not set the context.");
this->destroyGLContext();
return;
}
- sk_sp<const GrGLInterface> gl(sk_gpu_test::CreateANGLEGLInterface());
+ sk_sp<const GrGLInterface> gl = sk_gpu_test::CreateANGLEGLInterface();
if (nullptr == gl.get()) {
SkDebugf("Could not create ANGLE GL interface!\n");
this->destroyGLContext();
@@ -249,8 +342,13 @@
break;
}
#endif
+ const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
+ if (strstr(extensions, "EGL_KHR_image")) {
+ fCreateImage = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+ fDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+ }
- this->init(gl.release());
+ this->init(std::move(gl));
}
ANGLEGLContext::~ANGLEGLContext() {
@@ -262,21 +360,15 @@
if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
return GR_EGL_NO_IMAGE;
}
- GrEGLImage img;
- GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
- GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
- GR_EGL_NONE };
+ EGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
+ GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
+ GR_EGL_NONE };
// 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
- GR_GL_CALL_RET(this->gl(), img,
- EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
- attribs));
- return img;
+ return fCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs);
}
-void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
- GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
-}
+void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const { fDestroyImage(fDisplay, image); }
GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
GrGLClearErr(this->gl());
@@ -320,7 +412,10 @@
void ANGLEGLContext::destroyGLContext() {
if (EGL_NO_DISPLAY != fDisplay) {
- eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (eglGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
if (EGL_NO_CONTEXT != fContext) {
eglDestroyContext(fDisplay, fContext);
@@ -332,6 +427,10 @@
fSurface = EGL_NO_SURFACE;
}
+ if (fResetPlatform) {
+ fResetPlatform(fDisplay);
+ }
+
eglTerminate(fDisplay);
fDisplay = EGL_NO_DISPLAY;
}
@@ -355,6 +454,13 @@
}
}
+std::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const {
+ if (eglGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void ANGLEGLContext::onPlatformSwapBuffers() const {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
@@ -367,7 +473,7 @@
} // anonymous namespace
namespace sk_gpu_test {
-const GrGLInterface* CreateANGLEGLInterface() {
+sk_sp<const GrGLInterface> CreateANGLEGLInterface() {
static Libs gLibs = { nullptr, nullptr };
if (nullptr == gLibs.fGLLib) {
@@ -389,11 +495,19 @@
return nullptr;
}
- return GrGLAssembleGLESInterface(&gLibs, angle_get_gl_proc);
+ return GrGLMakeAssembledGLESInterface(&gLibs, angle_get_gl_proc);
}
std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
- GLTestContext* shareContext, void* display){
+ GLTestContext* shareContext, void* display) {
+#if defined(SK_BUILD_FOR_WIN) && defined(_M_ARM64)
+ // Windows-on-ARM only has D3D11. This will fail correctly, but it produces huge amounts of
+ // debug output for every unit test from both ANGLE and our context factory.
+ if (ANGLEBackend::kD3D11 != type) {
+ return nullptr;
+ }
+#endif
+
ANGLEGLContext* angleShareContext = reinterpret_cast<ANGLEGLContext*>(shareContext);
std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version,
angleShareContext, display));
diff --git a/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.h b/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.h
index 5a72b93..1dc563a 100644
--- a/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.h
+++ b/src/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.h
@@ -8,7 +8,7 @@
#ifndef GLTestContext_angle_DEFINED
#define GLTestContext_angle_DEFINED
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
namespace sk_gpu_test {
@@ -16,7 +16,7 @@
* Creates a GrGLInterface for the current ANGLE GLES Context. Here current means bound in ANGLE's
* implementation of EGL.
*/
-const GrGLInterface* CreateANGLEGLInterface();
+sk_sp<const GrGLInterface> CreateANGLEGLInterface();
enum class ANGLEBackend {
kD3D9,
diff --git a/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp b/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
index 54845fc..cf82e35 100644
--- a/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
+++ b/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
@@ -8,12 +8,15 @@
#ifndef SK_NO_COMMAND_BUFFER
-#include "SkMutex.h"
-#include "SkOnce.h"
-#include "gl/GrGLInterface.h"
-#include "gl/GrGLAssembleInterface.h"
-#include "gl/command_buffer/GLTestContext_command_buffer.h"
-#include "../ports/SkOSLibrary.h"
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "include/private/SkMutex.h"
+#include "include/private/SkOnce.h"
+#include "src/core/SkTLS.h"
+#include "src/ports/SkOSLibrary.h"
+#include "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h"
+
+namespace {
typedef void *EGLDisplay;
typedef unsigned int EGLBoolean;
@@ -25,6 +28,7 @@
typedef void* EGLNativeWindowType;
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#define EGL_FALSE 0
+#define EGL_TRUE 1
#define EGL_OPENGL_ES2_BIT 0x0004
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
#define EGL_NO_SURFACE ((EGLSurface)0)
@@ -45,6 +49,8 @@
#define EGL_NONE 0x3038
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
+#define EGL_DRAW 0x3059
+#define EGL_READ 0x305A
typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id);
typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor);
@@ -77,7 +83,6 @@
static void* gLibrary = nullptr;
static bool gfFunctionsLoadedSuccessfully = false;
-namespace {
static void load_command_buffer_functions() {
if (!gLibrary) {
static constexpr const char* libName =
@@ -104,12 +109,11 @@
gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers");
gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress");
- gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate &&
- gfChooseConfig && gfCreateWindowSurface &&
- gfCreatePbufferSurface && gfDestroySurface &&
- gfCreateContext && gfDestroyContext && gfMakeCurrent &&
- gfSwapBuffers && gfGetProcAddress;
-
+ gfFunctionsLoadedSuccessfully =
+ gfGetDisplay && gfInitialize && gfTerminate && gfChooseConfig &&
+ gfCreateWindowSurface && gfCreatePbufferSurface && gfDestroySurface &&
+ gfCreateContext && gfDestroyContext && gfMakeCurrent && gfSwapBuffers &&
+ gfGetProcAddress;
}
}
}
@@ -126,12 +130,86 @@
once(load_command_buffer_functions);
}
-static const GrGLInterface* create_command_buffer_interface() {
+static sk_sp<const GrGLInterface> create_command_buffer_interface() {
load_command_buffer_once();
if (!gfFunctionsLoadedSuccessfully) {
return nullptr;
}
- return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc);
+ return GrGLMakeAssembledGLESInterface(gLibrary, command_buffer_get_gl_proc);
+}
+
+
+// The command buffer does not correctly implement eglGetCurrent. It always returns EGL_NO_<foo>.
+// So we implement them ourselves and hook eglMakeCurrent to store the current values in TLS.
+class TLSCurrentObjects {
+public:
+ static EGLDisplay CurrentDisplay() {
+ if (auto objects = Get()) {
+ return objects->fDisplay;
+ }
+ return EGL_NO_DISPLAY;
+ }
+
+ static EGLSurface CurrentSurface(EGLint readdraw) {
+ if (auto objects = Get()) {
+ switch (readdraw) {
+ case EGL_DRAW:
+ return objects->fDrawSurface;
+ case EGL_READ:
+ return objects->fReadSurface;
+ default:
+ return EGL_NO_SURFACE;
+ }
+ }
+ return EGL_NO_SURFACE;
+ }
+
+ static EGLContext CurrentContext() {
+ if (auto objects = Get()) {
+ return objects->fContext;
+ }
+ return EGL_NO_CONTEXT;
+ }
+
+ static EGLBoolean MakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read,
+ EGLContext ctx) {
+ if (gfFunctionsLoadedSuccessfully && EGL_TRUE == gfMakeCurrent(display, draw, read, ctx)) {
+ if (auto objects = Get()) {
+ objects->fDisplay = display;
+ objects->fDrawSurface = draw;
+ objects->fReadSurface = read;
+ objects->fContext = ctx;
+ }
+ return EGL_TRUE;
+ }
+ return EGL_FALSE;
+
+ }
+
+private:
+ EGLDisplay fDisplay = EGL_NO_DISPLAY;
+ EGLSurface fReadSurface = EGL_NO_SURFACE;
+ EGLSurface fDrawSurface = EGL_NO_SURFACE;
+ EGLContext fContext = EGL_NO_CONTEXT;
+
+ static TLSCurrentObjects* Get() {
+ return (TLSCurrentObjects*) SkTLS::Get(TLSCreate, TLSDelete);
+ }
+ static void* TLSCreate() { return new TLSCurrentObjects(); }
+ static void TLSDelete(void* objs) { delete (TLSCurrentObjects*)objs; }
+};
+
+std::function<void()> context_restorer() {
+ if (!gfFunctionsLoadedSuccessfully) {
+ return nullptr;
+ }
+ auto display = TLSCurrentObjects::CurrentDisplay();
+ auto dsurface = TLSCurrentObjects::CurrentSurface(EGL_DRAW);
+ auto rsurface = TLSCurrentObjects::CurrentSurface(EGL_READ);
+ auto context = TLSCurrentObjects::CurrentContext();
+ return [display, dsurface, rsurface, context] {
+ TLSCurrentObjects::MakeCurrent(display, dsurface, rsurface, context);
+ };
}
} // anonymous namespace
@@ -204,14 +282,15 @@
return;
}
- if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+ SkScopeExit restorer(context_restorer());
+ if (!TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Command Buffer: Could not make EGL context current.\n");
this->destroyGLContext();
return;
}
- sk_sp<const GrGLInterface> gl(create_command_buffer_interface());
- if (nullptr == gl.get()) {
+ auto gl = create_command_buffer_interface();
+ if (!gl) {
SkDebugf("Command Buffer: Could not create CommandBuffer GL interface.\n");
this->destroyGLContext();
return;
@@ -222,7 +301,7 @@
return;
}
- this->init(gl.release());
+ this->init(std::move(gl));
}
CommandBufferGLTestContext::~CommandBufferGLTestContext() {
@@ -237,15 +316,19 @@
if (EGL_NO_DISPLAY == fDisplay) {
return;
}
+ bool wasCurrent = false;
if (EGL_NO_CONTEXT != fContext) {
+ wasCurrent = (TLSCurrentObjects::CurrentContext() == fContext);
gfDestroyContext(fDisplay, fContext);
fContext = EGL_NO_CONTEXT;
}
- // Call MakeCurrent after destroying the context, so that the EGL implementation knows that
- // the context is not used anymore after it is released from being current. This way
- // command buffer does not need to abandon the context before destruction, and no
- // client-side errors are printed.
- gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (wasCurrent) {
+ // Call MakeCurrent after destroying the context, so that the EGL implementation knows that
+ // the context is not used anymore after it is released from being current.This way the
+ // command buffer does not need to abandon the context before destruction, and no
+ // client-side errors are printed.
+ TLSCurrentObjects::MakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
if (EGL_NO_SURFACE != fSurface) {
gfDestroySurface(fDisplay, fSurface);
@@ -258,11 +341,18 @@
if (!gfFunctionsLoadedSuccessfully) {
return;
}
- if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+ if (!TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Command Buffer: Could not make EGL context current.\n");
}
}
+std::function<void()> CommandBufferGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (!gfFunctionsLoadedSuccessfully || TLSCurrentObjects::CurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void CommandBufferGLTestContext::onPlatformSwapBuffers() const {
if (!gfFunctionsLoadedSuccessfully) {
return;
@@ -288,7 +378,7 @@
}
bool CommandBufferGLTestContext::makeCurrent() {
- return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
+ return TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
}
int CommandBufferGLTestContext::getStencilBits() {
diff --git a/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h b/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
index 7582f16..089c06e 100644
--- a/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
+++ b/src/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
@@ -9,7 +9,7 @@
#ifndef GLTestContext_command_buffer_DEFINED
#define GLTestContext_command_buffer_DEFINED
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
namespace sk_gpu_test {
class CommandBufferGLTestContext : public GLTestContext {
@@ -42,6 +42,8 @@
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
+
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char *name) const override;
diff --git a/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp b/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
deleted file mode 100644
index e8eea8f..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
+++ /dev/null
@@ -1,1222 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DebugGLTestContext.h"
-
-#include "GrBufferObj.h"
-#include "GrFrameBufferObj.h"
-#include "GrProgramObj.h"
-#include "GrRenderBufferObj.h"
-#include "GrShaderObj.h"
-#include "GrTextureObj.h"
-#include "GrTextureUnitObj.h"
-#include "GrVertexArrayObj.h"
-#include "gl/GrGLTestInterface.h"
-
-#include "SkMutex.h"
-
-namespace {
-
-// Helper macro to make creating an object (where you need to get back a derived type) easier
-#define CREATE(className, classEnum) \
- reinterpret_cast<className *>(this->createObj(classEnum))
-
-// Helper macro to make creating an object (where you need to get back a derived type) easier
-#define FIND(id, className, classEnum) \
- reinterpret_cast<className *>(this->findObject(id, classEnum))
-
-class DebugInterface : public GrGLTestInterface {
-public:
- DebugInterface()
- : fCurrGenericID(0)
- , fCurrTextureUnit(0)
- , fVertexArray(nullptr)
- , fPackRowLength(0)
- , fUnpackRowLength(0)
- , fPackAlignment(4)
- , fFrameBuffer(nullptr)
- , fRenderBuffer(nullptr)
- , fProgram(nullptr)
- , fAbandoned(false) {
- for (int i = 0; i < kDefaultMaxTextureUnits; ++i) {
- fTextureUnits[i] =
- reinterpret_cast<GrTextureUnitObj*>(this->createObj(kTextureUnit_ObjTypes));
- fTextureUnits[i]->ref();
- fTextureUnits[i]->setNumber(i);
- }
- memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
- this->init(kGL_GrGLStandard);
- }
-
- ~DebugInterface() override {
- // unref & delete the texture units first so they don't show up on the leak report
- for (int i = 0; i < kDefaultMaxTextureUnits; ++i) {
- fTextureUnits[i]->unref();
- fTextureUnits[i]->deleteAction();
- }
- for (int i = 0; i < fObjects.count(); ++i) {
- delete fObjects[i];
- }
- fObjects.reset();
-
- memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
- fVertexArray = nullptr;
-
- this->report();
- }
-
- void abandon() const override { fAbandoned = true; }
-
- GrGLvoid activeTexture(GrGLenum texture) override {
- // Ganesh offsets the texture unit indices
- texture -= GR_GL_TEXTURE0;
- GrAlwaysAssert(texture < kDefaultMaxTextureUnits);
- fCurrTextureUnit = texture;
- }
-
- GrGLvoid attachShader(GrGLuint programID, GrGLuint shaderID) override {
-
- GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
- GrAlwaysAssert(program);
-
- GrShaderObj *shader = FIND(shaderID, GrShaderObj, kShader_ObjTypes);
- GrAlwaysAssert(shader);
-
- program->AttachShader(shader);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- GrGLvoid bindTexture(GrGLenum target, GrGLuint textureID) override {
- GrAlwaysAssert(target == GR_GL_TEXTURE_2D ||
- target == GR_GL_TEXTURE_RECTANGLE ||
- target == GR_GL_TEXTURE_EXTERNAL);
-
- // a textureID of 0 is acceptable - it binds to the default texture target
- GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
-
- this->setTexture(texture);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
- GrGLenum usage) override {
- GrAlwaysAssert(size >= 0);
- GrAlwaysAssert(GR_GL_STREAM_DRAW == usage ||
- GR_GL_STATIC_DRAW == usage ||
- GR_GL_DYNAMIC_DRAW == usage);
-
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- GrAlwaysAssert(buffer);
- GrAlwaysAssert(buffer->getBound());
-
- buffer->allocate(size, reinterpret_cast<const GrGLchar *>(data));
- buffer->setUsage(usage);
- }
-
-
- GrGLvoid pixelStorei(GrGLenum pname, GrGLint param) override {
-
- switch (pname) {
- case GR_GL_UNPACK_ROW_LENGTH:
- fUnpackRowLength = param;
- break;
- case GR_GL_PACK_ROW_LENGTH:
- fPackRowLength = param;
- break;
- case GR_GL_UNPACK_ALIGNMENT:
- break;
- case GR_GL_PACK_ALIGNMENT:
- fPackAlignment = param;
- break;
- default:
- GrAlwaysAssert(false);
- break;
- }
- }
-
- GrGLvoid readPixels(GrGLint x,
- GrGLint y,
- GrGLsizei width,
- GrGLsizei height,
- GrGLenum format,
- GrGLenum type,
- GrGLvoid* pixels) override {
-
- GrGLint pixelsInRow = width;
- if (fPackRowLength > 0) {
- pixelsInRow = fPackRowLength;
- }
-
- GrGLint componentsPerPixel = 0;
-
- switch (format) {
- case GR_GL_RGBA:
- // fallthrough
- case GR_GL_BGRA:
- componentsPerPixel = 4;
- break;
- case GR_GL_RGB:
- componentsPerPixel = 3;
- break;
- case GR_GL_RED:
- componentsPerPixel = 1;
- break;
- default:
- GrAlwaysAssert(false);
- break;
- }
-
- GrGLint alignment = fPackAlignment;
-
- GrGLint componentSize = 0; // size (in bytes) of a single component
-
- switch (type) {
- case GR_GL_UNSIGNED_BYTE:
- componentSize = 1;
- break;
- default:
- GrAlwaysAssert(false);
- break;
- }
-
- GrGLint rowStride = 0; // number of components (not bytes) to skip
- if (componentSize >= alignment) {
- rowStride = componentsPerPixel * pixelsInRow;
- } else {
- float fTemp =
- sk_float_ceil(componentSize * componentsPerPixel * pixelsInRow /
- static_cast<float>(alignment));
- rowStride = static_cast<GrGLint>(alignment * fTemp / componentSize);
- }
-
- GrGLchar *scanline = static_cast<GrGLchar *>(pixels);
- for (int y = 0; y < height; ++y) {
- memset(scanline, 0, componentsPerPixel * componentSize * width);
- scanline += rowStride;
- }
- }
-
- GrGLvoid useProgram(GrGLuint programID) override {
-
- // A programID of 0 is legal
- GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
-
- this->useProgram(program);
- }
-
- GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint frameBufferID) override {
-
- GrAlwaysAssert(GR_GL_FRAMEBUFFER == target ||
- GR_GL_READ_FRAMEBUFFER == target ||
- GR_GL_DRAW_FRAMEBUFFER);
-
- // a frameBufferID of 0 is acceptable - it binds to the default
- // frame buffer
- GrFrameBufferObj *frameBuffer = FIND(frameBufferID, GrFrameBufferObj,
- kFrameBuffer_ObjTypes);
-
- this->setFrameBuffer(frameBuffer);
- }
-
- GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderBufferID) override {
-
- GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
-
- // a renderBufferID of 0 is acceptable - it unbinds the bound render buffer
- GrRenderBufferObj *renderBuffer = FIND(renderBufferID, GrRenderBufferObj,
- kRenderBuffer_ObjTypes);
-
- this->setRenderBuffer(renderBuffer);
- }
-
- GrGLvoid deleteTextures(GrGLsizei n, const GrGLuint* textures) override {
- // first potentially unbind the texture
- for (unsigned int i = 0; i < kDefaultMaxTextureUnits; ++i) {
- GrTextureUnitObj *pTU = this->getTextureUnit(i);
-
- if (pTU->getTexture()) {
- for (int j = 0; j < n; ++j) {
-
- if (textures[j] == pTU->getTexture()->getID()) {
- // this ID is the current texture - revert the binding to 0
- pTU->setTexture(nullptr);
- }
- }
- }
- }
-
- // TODO: fuse the following block with DeleteRenderBuffers?
- // Open GL will remove a deleted render buffer from the active
- // frame buffer but not from any other frame buffer
- if (this->getFrameBuffer()) {
-
- GrFrameBufferObj *frameBuffer = this->getFrameBuffer();
-
- for (int i = 0; i < n; ++i) {
-
- if (frameBuffer->getColor() &&
- textures[i] == frameBuffer->getColor()->getID()) {
- frameBuffer->setColor(nullptr);
- }
- if (frameBuffer->getDepth() &&
- textures[i] == frameBuffer->getDepth()->getID()) {
- frameBuffer->setDepth(nullptr);
- }
- if (frameBuffer->getStencil() &&
- textures[i] == frameBuffer->getStencil()->getID()) {
- frameBuffer->setStencil(nullptr);
- }
- }
- }
-
- // then actually "delete" the buffers
- for (int i = 0; i < n; ++i) {
- GrTextureObj *buffer = FIND(textures[i], GrTextureObj, kTexture_ObjTypes);
- GrAlwaysAssert(buffer);
-
- // OpenGL gives no guarantees if a texture is deleted while attached to
- // something other than the currently bound frame buffer
- GrAlwaysAssert(!buffer->getBound());
-
- GrAlwaysAssert(!buffer->getDeleted());
- buffer->deleteAction();
- }
-
- }
-
- GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint *frameBuffers) override {
-
- // first potentially unbind the buffers
- if (this->getFrameBuffer()) {
- for (int i = 0; i < n; ++i) {
-
- if (frameBuffers[i] ==
- this->getFrameBuffer()->getID()) {
- // this ID is the current frame buffer - rebind to the default
- this->setFrameBuffer(nullptr);
- }
- }
- }
-
- // then actually "delete" the buffers
- for (int i = 0; i < n; ++i) {
- GrFrameBufferObj *buffer = FIND(frameBuffers[i], GrFrameBufferObj,
- kFrameBuffer_ObjTypes);
- GrAlwaysAssert(buffer);
-
- GrAlwaysAssert(!buffer->getDeleted());
- buffer->deleteAction();
- }
- }
-
- GrGLvoid deleteRenderbuffers(GrGLsizei n,const GrGLuint *renderBuffers) override {
-
- // first potentially unbind the buffers
- if (this->getRenderBuffer()) {
- for (int i = 0; i < n; ++i) {
-
- if (renderBuffers[i] ==
- this->getRenderBuffer()->getID()) {
- // this ID is the current render buffer - make no
- // render buffer be bound
- this->setRenderBuffer(nullptr);
- }
- }
- }
-
- // TODO: fuse the following block with DeleteTextures?
- // Open GL will remove a deleted render buffer from the active frame
- // buffer but not from any other frame buffer
- if (this->getFrameBuffer()) {
-
- GrFrameBufferObj *frameBuffer = this->getFrameBuffer();
-
- for (int i = 0; i < n; ++i) {
-
- if (frameBuffer->getColor() &&
- renderBuffers[i] == frameBuffer->getColor()->getID()) {
- frameBuffer->setColor(nullptr);
- }
- if (frameBuffer->getDepth() &&
- renderBuffers[i] == frameBuffer->getDepth()->getID()) {
- frameBuffer->setDepth(nullptr);
- }
- if (frameBuffer->getStencil() &&
- renderBuffers[i] == frameBuffer->getStencil()->getID()) {
- frameBuffer->setStencil(nullptr);
- }
- }
- }
-
- // then actually "delete" the buffers
- for (int i = 0; i < n; ++i) {
- GrRenderBufferObj *buffer = FIND(renderBuffers[i], GrRenderBufferObj,
- kRenderBuffer_ObjTypes);
- GrAlwaysAssert(buffer);
-
- // OpenGL gives no guarantees if a render buffer is deleted
- // while attached to something other than the currently
- // bound frame buffer
- GrAlwaysAssert(!buffer->getColorBound());
- GrAlwaysAssert(!buffer->getDepthBound());
- // However, at GrContext destroy time we release all GrRsources and so stencil buffers
- // may get deleted before FBOs that refer to them.
- //GrAlwaysAssert(!buffer->getStencilBound());
-
- GrAlwaysAssert(!buffer->getDeleted());
- buffer->deleteAction();
- }
- }
-
- GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width,
- GrGLsizei height) override {
- GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
- GrRenderBufferObj* renderBuffer = this->getRenderBuffer();
- GrAlwaysAssert(renderBuffer);
- renderBuffer->setNumSamples(1);
- }
-
- GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples,
- GrGLenum internalformat, GrGLsizei width,
- GrGLsizei height) override {
- GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
- GrRenderBufferObj* renderBuffer = this->getRenderBuffer();
- GrAlwaysAssert(renderBuffer);
- renderBuffer->setNumSamples(samples);
- }
-
- GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
- GrGLsizei width, GrGLsizei height) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
- GrGLenum GrGLinternalformat, GrGLsizei width,
- GrGLsizei height) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLvoid framebufferRenderbuffer(GrGLenum target,
- GrGLenum attachment,
- GrGLenum renderbuffertarget,
- GrGLuint renderBufferID) override {
-
- GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
- GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
- GR_GL_DEPTH_ATTACHMENT == attachment ||
- GR_GL_STENCIL_ATTACHMENT == attachment);
- GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
-
- GrFrameBufferObj *framebuffer = this->getFrameBuffer();
- // A render buffer cannot be attached to the default framebuffer
- GrAlwaysAssert(framebuffer);
-
- // a renderBufferID of 0 is acceptable - it unbinds the current
- // render buffer
- GrRenderBufferObj *renderbuffer = FIND(renderBufferID, GrRenderBufferObj,
- kRenderBuffer_ObjTypes);
-
- switch (attachment) {
- case GR_GL_COLOR_ATTACHMENT0:
- framebuffer->setColor(renderbuffer);
- break;
- case GR_GL_DEPTH_ATTACHMENT:
- framebuffer->setDepth(renderbuffer);
- break;
- case GR_GL_STENCIL_ATTACHMENT:
- framebuffer->setStencil(renderbuffer);
- break;
- default:
- GrAlwaysAssert(false);
- break;
- };
-
- }
-
- GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
- GrGLenum renderbuffertarget,
- GrGLuint renderbuffer) override {
- SK_ABORT("Not implemented");
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
- GrGLuint textureID, GrGLint level) override {
-
- GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
- GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
- GR_GL_DEPTH_ATTACHMENT == attachment ||
- GR_GL_STENCIL_ATTACHMENT == attachment);
- GrAlwaysAssert(GR_GL_TEXTURE_2D == textarget);
-
- GrFrameBufferObj *framebuffer = this->getFrameBuffer();
- // A texture cannot be attached to the default framebuffer
- GrAlwaysAssert(framebuffer);
-
- // A textureID of 0 is allowed - it unbinds the currently bound texture
- GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
- if (texture) {
- // The texture shouldn't be bound to a texture unit - this
- // could lead to a feedback loop
- GrAlwaysAssert(!texture->getBound());
- }
-
- GrAlwaysAssert(0 == level);
-
- switch (attachment) {
- case GR_GL_COLOR_ATTACHMENT0:
- framebuffer->setColor(texture);
- break;
- case GR_GL_DEPTH_ATTACHMENT:
- framebuffer->setDepth(texture);
- break;
- case GR_GL_STENCIL_ATTACHMENT:
- framebuffer->setStencil(texture);
- break;
- default:
- GrAlwaysAssert(false);
- break;
- };
- }
-
- GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
- GrGLenum textarget, GrGLuint texture, GrGLint level,
- GrGLsizei samples) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
- GrGLenum textarget, GrGLuint texture,
- GrGLint level) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
- GrGLenum textarget, GrGLuint texture,
- GrGLint level) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
- GrGLenum textarget, GrGLuint texture, GrGLint level,
- GrGLint zoffset) override {
- SK_ABORT("Not implemented");
- }
-
- GrGLuint createProgram() override {
-
- GrProgramObj *program = CREATE(GrProgramObj, kProgram_ObjTypes);
-
- return program->getID();
- }
-
- GrGLuint createShader(GrGLenum type) override {
-
- GrAlwaysAssert(GR_GL_VERTEX_SHADER == type ||
- GR_GL_FRAGMENT_SHADER == type);
-
- GrShaderObj *shader = CREATE(GrShaderObj, kShader_ObjTypes);
- shader->setType(type);
-
- return shader->getID();
- }
-
- GrGLenum checkFramebufferStatus(GrGLenum target) override { return GR_GL_FRAMEBUFFER_COMPLETE; }
-
- GrGLvoid deleteProgram(GrGLuint programID) override {
-
- GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
- GrAlwaysAssert(program);
-
- if (program->getRefCount()) {
- // someone is still using this program so we can't delete it here
- program->setMarkedForDeletion();
- } else {
- program->deleteAction();
- }
- }
-
- GrGLvoid deleteShader(GrGLuint shaderID) override {
-
- GrShaderObj *shader = FIND(shaderID, GrShaderObj, kShader_ObjTypes);
- GrAlwaysAssert(shader);
-
- if (shader->getRefCount()) {
- // someone is still using this shader so we can't delete it here
- shader->setMarkedForDeletion();
- } else {
- shader->deleteAction();
- }
- }
-
- GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
- this->genObjs(kBuffer_ObjTypes, n, ids);
- }
-
- GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint* ids) override {
- this->genObjs(kFrameBuffer_ObjTypes, n, ids);
- }
-
- GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint* ids) override {
- this->genObjs(kRenderBuffer_ObjTypes, n, ids);
- }
-
- GrGLvoid genTextures(GrGLsizei n, GrGLuint* ids) override {
- this->genObjs(kTexture_ObjTypes, n, ids);
- }
-
- GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint* ids) override {
- this->genObjs(kVertexArray_ObjTypes, n, ids);
- }
-
- GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
-
- GrGLenum getError() override { return GR_GL_NO_ERROR; }
-
- GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
- // TODO: remove from Ganesh the #defines for gets we don't use.
- // We would like to minimize gets overall due to performance issues
- switch (pname) {
- case GR_GL_CONTEXT_PROFILE_MASK:
- *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
- break;
- case GR_GL_STENCIL_BITS:
- *params = 8;
- break;
- case GR_GL_SAMPLES: {
- GrFrameBufferObj* framebuffer = this->getFrameBuffer();
- GrAlwaysAssert(framebuffer);
- int numSamples = 0;
-
- if (GrFBBindableObj* stencil = framebuffer->getStencil()) {
- numSamples = stencil->numSamples();
- }
- if (GrFBBindableObj* depth = framebuffer->getDepth()) {
- GrAlwaysAssert(!numSamples || numSamples == depth->numSamples());
- numSamples = depth->numSamples();
- }
- if (GrFBBindableObj* color = framebuffer->getColor()) {
- GrAlwaysAssert(!numSamples || numSamples == color->numSamples());
- numSamples = color->numSamples();
- }
- GrAlwaysAssert(numSamples);
- *params = numSamples;
- break;
- }
- case GR_GL_FRAMEBUFFER_BINDING:
- *params = 0;
- break;
- case GR_GL_VIEWPORT:
- params[0] = 0;
- params[1] = 0;
- params[2] = 800;
- params[3] = 600;
- break;
- case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
- case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
- case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
- case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
- *params = 8;
- break;
- case GR_GL_MAX_TEXTURE_COORDS:
- *params = 8;
- break;
- case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
- *params = kDefaultMaxVertexUniformVectors;
- break;
- case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
- *params = kDefaultMaxFragmentUniformVectors;
- break;
- case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
- *params = 16 * 4;
- break;
- case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- *params = 0;
- break;
- case GR_GL_COMPRESSED_TEXTURE_FORMATS:
- break;
- case GR_GL_MAX_TEXTURE_SIZE:
- *params = 8192;
- break;
- case GR_GL_MAX_RENDERBUFFER_SIZE:
- *params = 8192;
- break;
- case GR_GL_MAX_SAMPLES:
- *params = 32;
- break;
- case GR_GL_MAX_VERTEX_ATTRIBS:
- *params = kDefaultMaxVertexAttribs;
- break;
- case GR_GL_MAX_VARYING_VECTORS:
- *params = kDefaultMaxVaryingVectors;
- break;
- case GR_GL_NUM_EXTENSIONS: {
- GrGLint i = 0;
- while (kExtensions[i++]);
- *params = i;
- break;
- }
- default:
- SkFAIL("Unexpected pname to GetIntegerv");
- }
- }
-
- GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
- val[0] = val[1] = 0.5f;
- }
-
- GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
- this->getShaderOrProgramiv(program, pname, params);
- }
-
- GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
- char* infolog) override {
- this->getInfoLog(program, bufsize, length, infolog);
- }
-
- GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
- switch (pname) {
- case GR_GL_CURRENT_QUERY:
- *params = 0;
- break;
- case GR_GL_QUERY_COUNTER_BITS:
- *params = 32;
- break;
- default:
- SkFAIL("Unexpected pname passed GetQueryiv.");
- }
- }
-
- GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
- this->queryResult(id, pname, params);
- }
-
- GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
- this->queryResult(id, pname, params);
- }
-
- GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
- this->queryResult(id, pname, params);
- }
-
- GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
- this->queryResult(id, pname, params);
- }
-
- GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
- this->getShaderOrProgramiv(shader, pname, params);
- }
-
- GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
- char* infolog) override {
- this->getInfoLog(shader, bufsize, length, infolog);
- }
-
- const GrGLubyte* getString(GrGLenum name) override {
- switch (name) {
- case GR_GL_EXTENSIONS:
- return CombinedExtensionString();
- case GR_GL_VERSION:
- return (const GrGLubyte*)"4.0 Debug GL";
- case GR_GL_SHADING_LANGUAGE_VERSION:
- return (const GrGLubyte*)"4.20.8 Debug GLSL";
- case GR_GL_VENDOR:
- return (const GrGLubyte*)"Debug Vendor";
- case GR_GL_RENDERER:
- return (const GrGLubyte*)"The Debug (Non-)Renderer";
- default:
- SkFAIL("Unexpected name passed to GetString");
- return nullptr;
- }
- }
-
- const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
- switch (name) {
- case GR_GL_EXTENSIONS: {
- GrGLint count;
- this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
- if ((GrGLint)i <= count) {
- return (const GrGLubyte*) kExtensions[i];
- } else {
- return nullptr;
- }
- }
- default:
- SkFAIL("Unexpected name passed to GetStringi");
- return nullptr;
- }
- }
-
- GrGLvoid getTexLevelParameteriv(GrGLenum target, GrGLint level, GrGLenum pname,
- GrGLint* params) override {
- // we used to use this to query stuff about externally created textures,
- // now we just require clients to tell us everything about the texture.
- SkFAIL("Should never query texture parameters.");
- }
-
- GrGLvoid deleteVertexArrays(GrGLsizei n, const GrGLuint* ids) override {
- for (GrGLsizei i = 0; i < n; ++i) {
- GrVertexArrayObj* array = FIND(ids[i], GrVertexArrayObj, kVertexArray_ObjTypes);
- GrAlwaysAssert(array);
-
- // Deleting the current vertex array binds object 0
- if (this->getVertexArray() == array) {
- this->setVertexArray(nullptr);
- }
-
- if (array->getRefCount()) {
- // someone is still using this vertex array so we can't delete it here
- array->setMarkedForDeletion();
- } else {
- array->deleteAction();
- }
- }
- }
-
- GrGLvoid bindVertexArray(GrGLuint id) override {
- GrVertexArrayObj* array = FIND(id, GrVertexArrayObj, kVertexArray_ObjTypes);
- GrAlwaysAssert((0 == id) || array);
- this->setVertexArray(array);
- }
-
- GrGLvoid bindBuffer(GrGLenum target, GrGLuint bufferID) override {
- GrBufferObj *buffer = FIND(bufferID, GrBufferObj, kBuffer_ObjTypes);
- // 0 is a permissible bufferID - it unbinds the current buffer
-
- this->setBuffer(GetBufferIndex(target), buffer);
- }
-
- // deleting a bound buffer has the side effect of binding 0
- GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override {
- // first potentially unbind the buffers
- for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) {
- GrBufferObj* buffer = fBoundBuffers[buffIdx];
- if (!buffer) {
- continue;
- }
- for (int i = 0; i < n; ++i) {
- if (ids[i] == buffer->getID()) {
- this->setBuffer(buffIdx, nullptr);
- break;
- }
- }
- }
-
- // then actually "delete" the buffers
- for (int i = 0; i < n; ++i) {
- GrBufferObj *buffer = FIND(ids[i], GrBufferObj, kBuffer_ObjTypes);
- GrAlwaysAssert(buffer);
-
- GrAlwaysAssert(!buffer->getDeleted());
- buffer->deleteAction();
- }
- }
-
- // map a buffer to the caller's address space
- GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
- GrGLbitfield access) override {
- // We only expect read access and we expect that the buffer or range is always invalidated.
- GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
- GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
-
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- if (buffer) {
- GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
- GrAlwaysAssert(!buffer->getMapped());
- buffer->setMapped(offset, length);
- return buffer->getDataPtr() + offset;
- }
-
- GrAlwaysAssert(false);
- return nullptr; // no buffer bound to the target
- }
-
- GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
- GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- return this->mapBufferRange(target, 0, buffer->getSize(),
- GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
- }
-
- // remove a buffer from the caller's address space
- // TODO: check if the "access" method from "glMapBuffer" was honored
- GrGLboolean unmapBuffer(GrGLenum target) override {
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- if (buffer) {
- GrAlwaysAssert(buffer->getMapped());
- buffer->resetMapped();
- return GR_GL_TRUE;
- }
-
- GrAlwaysAssert(false);
- return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
- }
-
- GrGLvoid flushMappedBufferRange(GrGLenum target, GrGLintptr offset,
- GrGLsizeiptr length) override {
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- if (buffer) {
- GrAlwaysAssert(buffer->getMapped());
- GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
- } else {
- GrAlwaysAssert(false);
- }
- }
-
- GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum value, GrGLint* params) override {
-
- GrAlwaysAssert(GR_GL_BUFFER_SIZE == value ||
- GR_GL_BUFFER_USAGE == value);
-
- GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
- GrAlwaysAssert(buffer);
-
- switch (value) {
- case GR_GL_BUFFER_MAPPED:
- *params = GR_GL_FALSE;
- if (buffer)
- *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
- break;
- case GR_GL_BUFFER_SIZE:
- *params = 0;
- if (buffer)
- *params = SkToInt(buffer->getSize());
- break;
- case GR_GL_BUFFER_USAGE:
- *params = GR_GL_STATIC_DRAW;
- if (buffer)
- *params = buffer->getUsage();
- break;
- default:
- SkFAIL("Unexpected value to glGetBufferParamateriv");
- break;
- }
- }
-
-private:
- inline int static GetBufferIndex(GrGLenum glTarget) {
- switch (glTarget) {
- default: SkFAIL("Unexpected GL target to GetBufferIndex");
- case GR_GL_ARRAY_BUFFER: return 0;
- case GR_GL_ELEMENT_ARRAY_BUFFER: return 1;
- case GR_GL_TEXTURE_BUFFER: return 2;
- case GR_GL_DRAW_INDIRECT_BUFFER: return 3;
- }
- }
- constexpr int static kNumBufferTargets = 4;
-
- // the OpenGLES 2.0 spec says this must be >= 128
- static const GrGLint kDefaultMaxVertexUniformVectors = 128;
-
- // the OpenGLES 2.0 spec says this must be >=16
- static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
-
- // the OpenGLES 2.0 spec says this must be >= 8
- static const GrGLint kDefaultMaxVertexAttribs = 8;
-
- // the OpenGLES 2.0 spec says this must be >= 8
- static const GrGLint kDefaultMaxVaryingVectors = 8;
-
- // the OpenGLES 2.0 spec says this must be >= 2
- static const GrGLint kDefaultMaxTextureUnits = 8;
-
- static const char* kExtensions[];
-
- GrGLuint fCurrGenericID;
- GrGLuint fCurrTextureUnit;
- GrTextureUnitObj* fTextureUnits[kDefaultMaxTextureUnits];
- GrBufferObj* fBoundBuffers[kNumBufferTargets];
- GrVertexArrayObj* fVertexArray;
- GrGLint fPackRowLength;
- GrGLint fUnpackRowLength;
- GrGLint fPackAlignment;
- GrFrameBufferObj* fFrameBuffer;
- GrRenderBufferObj* fRenderBuffer;
- GrProgramObj* fProgram;
- mutable bool fAbandoned;
- // global store of all objects
- SkTArray<GrFakeRefObj *> fObjects;
-
- static const GrGLubyte* CombinedExtensionString() {
- static SkString gExtString;
- static SkMutex gMutex;
- gMutex.acquire();
- if (0 == gExtString.size()) {
- int i = 0;
- while (kExtensions[i]) {
- if (i > 0) {
- gExtString.append(" ");
- }
- gExtString.append(kExtensions[i]);
- ++i;
- }
- }
- gMutex.release();
- return (const GrGLubyte*) gExtString.c_str();
- }
-
- GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
- for (int i = 0; i < n; ++i) {
- ids[i] = ++fCurrGenericID;
- }
- }
-
- GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
- char* infolog) {
- if (length) {
- *length = 0;
- }
- if (bufsize > 0) {
- *infolog = 0;
- }
- }
-
- GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* params) {
- switch (pname) {
- case GR_GL_LINK_STATUS: // fallthru
- case GR_GL_COMPILE_STATUS:
- *params = GR_GL_TRUE;
- break;
- case GR_GL_INFO_LOG_LENGTH:
- *params = 0;
- break;
- // we don't expect any other pnames
- default:
- SkFAIL("Unexpected pname to GetProgramiv");
- break;
- }
- }
-
- template <typename T>
- void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
- switch (pname) {
- case GR_GL_QUERY_RESULT_AVAILABLE:
- *params = GR_GL_TRUE;
- break;
- case GR_GL_QUERY_RESULT:
- *params = 0;
- break;
- default:
- SkFAIL("Unexpected pname passed to GetQueryObject.");
- break;
- }
- }
-
- enum ObjTypes {
- kTexture_ObjTypes = 0,
- kBuffer_ObjTypes,
- kRenderBuffer_ObjTypes,
- kFrameBuffer_ObjTypes,
- kShader_ObjTypes,
- kProgram_ObjTypes,
- kTextureUnit_ObjTypes,
- kVertexArray_ObjTypes,
- kObjTypeCount
- };
-
- typedef GrFakeRefObj *(*Create)();
-
- static Create gFactoryFunc[kObjTypeCount];
-
- GrGLvoid genObjs(ObjTypes type, GrGLsizei n, GrGLuint* ids) {
- for (int i = 0; i < n; ++i) {
- GrAlwaysAssert(ids[i] == 0);
- GrFakeRefObj *obj = this->createObj(type);
- GrAlwaysAssert(obj);
- ids[i] = obj->getID();
- }
- }
-
- GrFakeRefObj* createObj(ObjTypes type) {
- GrFakeRefObj *temp = (*gFactoryFunc[type])();
-
- fObjects.push_back(temp);
-
- return temp;
- }
-
- GrFakeRefObj* findObject(GrGLuint ID, ObjTypes type) {
- for (int i = 0; i < fObjects.count(); ++i) {
- if (fObjects[i]->getID() == ID) { // && fObjects[i]->getType() == type) {
- // The application shouldn't be accessing objects
- // that (as far as OpenGL knows) were already deleted
- GrAlwaysAssert(!fObjects[i]->getDeleted());
- GrAlwaysAssert(!fObjects[i]->getMarkedForDeletion());
- return fObjects[i];
- }
- }
- return nullptr;
- }
-
- GrTextureUnitObj* getTextureUnit(int unit) {
- GrAlwaysAssert(0 <= unit && kDefaultMaxTextureUnits > unit);
-
- return fTextureUnits[unit];
- }
-
- GrGLvoid setBuffer(int buffIdx, GrBufferObj* buffer) {
- if (fBoundBuffers[buffIdx]) {
- // automatically break the binding of the old buffer
- GrAlwaysAssert(fBoundBuffers[buffIdx]->getBound());
- fBoundBuffers[buffIdx]->resetBound();
-
- GrAlwaysAssert(!fBoundBuffers[buffIdx]->getDeleted());
- fBoundBuffers[buffIdx]->unref();
- }
-
- if (buffer) {
- GrAlwaysAssert(!buffer->getDeleted());
- buffer->ref();
-
- GrAlwaysAssert(!buffer->getBound());
- buffer->setBound();
- }
-
- fBoundBuffers[buffIdx] = buffer;
- }
-
- void setVertexArray(GrVertexArrayObj* vertexArray) {
- if (vertexArray) {
- SkASSERT(!vertexArray->getDeleted());
- }
- SkRefCnt_SafeAssign(fVertexArray, vertexArray);
- }
-
- GrVertexArrayObj* getVertexArray() { return fVertexArray; }
-
- void setTexture(GrTextureObj *texture) {
- fTextureUnits[fCurrTextureUnit]->setTexture(texture);
- }
-
- void setFrameBuffer(GrFrameBufferObj *frameBuffer) {
- if (fFrameBuffer) {
- GrAlwaysAssert(fFrameBuffer->getBound());
- fFrameBuffer->resetBound();
-
- GrAlwaysAssert(!fFrameBuffer->getDeleted());
- fFrameBuffer->unref();
- }
-
- fFrameBuffer = frameBuffer;
-
- if (fFrameBuffer) {
- GrAlwaysAssert(!fFrameBuffer->getDeleted());
- fFrameBuffer->ref();
-
- GrAlwaysAssert(!fFrameBuffer->getBound());
- fFrameBuffer->setBound();
- }
- }
-
- GrFrameBufferObj *getFrameBuffer() { return fFrameBuffer; }
-
- void setRenderBuffer(GrRenderBufferObj *renderBuffer) {
- if (fRenderBuffer) {
- GrAlwaysAssert(fRenderBuffer->getBound());
- fRenderBuffer->resetBound();
-
- GrAlwaysAssert(!fRenderBuffer->getDeleted());
- fRenderBuffer->unref();
- }
-
- fRenderBuffer = renderBuffer;
-
- if (fRenderBuffer) {
- GrAlwaysAssert(!fRenderBuffer->getDeleted());
- fRenderBuffer->ref();
-
- GrAlwaysAssert(!fRenderBuffer->getBound());
- fRenderBuffer->setBound();
- }
- }
- GrRenderBufferObj *getRenderBuffer() { return fRenderBuffer; }
-
- void useProgram(GrProgramObj *program) {
- if (fProgram) {
- GrAlwaysAssert(fProgram->getInUse());
- fProgram->resetInUse();
-
- GrAlwaysAssert(!fProgram->getDeleted());
- fProgram->unref();
- }
-
- fProgram = program;
-
- if (fProgram) {
- GrAlwaysAssert(!fProgram->getDeleted());
- fProgram->ref();
-
- GrAlwaysAssert(!fProgram->getInUse());
- fProgram->setInUse();
- }
- }
-
- void report() const {
- for (int i = 0; i < fObjects.count(); ++i) {
- if (!fAbandoned) {
- GrAlwaysAssert(0 == fObjects[i]->getRefCount());
- GrAlwaysAssert(fObjects[i]->getDeleted());
- }
- }
- }
-
- typedef GrGLTestInterface INHERITED;
-};
-
-#undef CREATE
-#undef FIND
-
-DebugInterface::Create DebugInterface::gFactoryFunc[kObjTypeCount] = {
- GrTextureObj::createGrTextureObj,
- GrBufferObj::createGrBufferObj,
- GrRenderBufferObj::createGrRenderBufferObj,
- GrFrameBufferObj::createGrFrameBufferObj,
- GrShaderObj::createGrShaderObj,
- GrProgramObj::createGrProgramObj,
- GrTextureUnitObj::createGrTextureUnitObj,
- GrVertexArrayObj::createGrVertexArrayObj,
-};
-
-const char* DebugInterface::kExtensions[] = {
- "GL_ARB_framebuffer_object",
- "GL_ARB_blend_func_extended",
- "GL_ARB_timer_query",
- "GL_ARB_draw_buffers",
- "GL_ARB_occlusion_query",
- "GL_EXT_stencil_wrap",
- nullptr, // signifies the end of the array.
-};
-
-class DebugGLContext : public sk_gpu_test::GLTestContext {
-public:
- DebugGLContext() {
- this->init(new DebugInterface());
- }
-
- ~DebugGLContext() override { this->teardown(); }
-
-private:
- void onPlatformMakeCurrent() const override {}
- void onPlatformSwapBuffers() const override {}
- GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
-};
-} // anonymous namespace
-
-namespace sk_gpu_test {
-GLTestContext* CreateDebugGLTestContext(GLTestContext* shareContext) {
- if (shareContext) {
- return nullptr;
- }
- GLTestContext* ctx = new DebugGLContext();
- if (ctx->isValid()) {
- return ctx;
- }
- delete ctx;
- return nullptr;
-}
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.h b/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.h
deleted file mode 100644
index 9b9abe5..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef DebugGLContext_DEFINED
-#define DebugGLContext_DEFINED
-
-#include "gl/GLTestContext.h"
-
-namespace sk_gpu_test {
-GLTestContext* CreateDebugGLTestContext(GLTestContext* shareContext = nullptr);
-} // namespace sk_gpu_test
-
-#endif
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.cpp
deleted file mode 100644
index 37d4438..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrBufferObj.h"
-
-void GrBufferObj::allocate(GrGLsizeiptr size, const GrGLchar *dataPtr) {
- GrAlwaysAssert(size >= 0);
-
- // delete pre-existing data
- delete[] fDataPtr;
-
- fSize = size;
- fDataPtr = new GrGLchar[size];
- if (dataPtr) {
- memcpy(fDataPtr, dataPtr, fSize);
- }
- // TODO: w/ no dataPtr the data is unitialized - this could be tracked
-}
-
-void GrBufferObj::deleteAction() {
-
- // buffers are automatically unmapped when deleted
- this->resetMapped();
-
- this->INHERITED::deleteAction();
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.h
deleted file mode 100644
index d0217b2..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrBufferObj.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrBufferObj_DEFINED
-#define GrBufferObj_DEFINED
-
-#include "GrFakeRefObj.h"
-#include "gl/GrGLDefines.h"
-
-////////////////////////////////////////////////////////////////////////////////
-class GrBufferObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrBufferObj)
-
-public:
- GrBufferObj()
- : GrFakeRefObj()
- , fDataPtr(nullptr)
- , fMapped(false)
- , fBound(false)
- , fSize(0)
- , fUsage(GR_GL_STATIC_DRAW) {
- }
- ~GrBufferObj() override {
- delete[] fDataPtr;
- }
-
- void access() {
- // cannot access the buffer if it is currently mapped
- GrAlwaysAssert(!fMapped);
- }
-
- void setMapped(GrGLintptr offset, GrGLsizeiptr length) {
- fMapped = true;
- fMappedOffset = offset;
- fMappedLength = length;
- }
- void resetMapped() { fMapped = false; }
- bool getMapped() const { return fMapped; }
- GrGLintptr getMappedOffset() const { return fMappedOffset; }
- GrGLsizeiptr getMappedLength() const { return fMappedLength; }
-
- void setBound() { fBound = true; }
- void resetBound() { fBound = false; }
- bool getBound() const { return fBound; }
-
- void allocate(GrGLsizeiptr size, const GrGLchar *dataPtr);
- GrGLsizeiptr getSize() const { return fSize; }
- GrGLchar *getDataPtr() { return fDataPtr; }
-
- void setUsage(GrGLint usage) { fUsage = usage; }
- GrGLint getUsage() const { return fUsage; }
-
- void deleteAction() override;
-
-protected:
-private:
-
- GrGLchar* fDataPtr;
- bool fMapped; // is the buffer object mapped via "glMapBuffer[Range]"?
- GrGLintptr fMappedOffset; // the offset of the buffer range that is mapped
- GrGLsizeiptr fMappedLength; // the size of the buffer range that is mapped
- bool fBound; // is the buffer object bound via "glBindBuffer"?
- GrGLsizeiptr fSize; // size in bytes
- GrGLint fUsage; // one of: GL_STREAM_DRAW,
- // GL_STATIC_DRAW,
- // GL_DYNAMIC_DRAW
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrBufferObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrFBBindableObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrFBBindableObj.h
deleted file mode 100644
index f5b46ab..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrFBBindableObj.h
+++ /dev/null
@@ -1,92 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrFBBindableObj_DEFINED
-#define GrFBBindableObj_DEFINED
-
-#include "SkTDArray.h"
-#include "GrFakeRefObj.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// A common base class for render buffers and textures
-class GrFBBindableObj : public GrFakeRefObj {
-
-public:
- GrFBBindableObj()
- : GrFakeRefObj()
- , fNumSamples(1) {
- }
-
- virtual ~GrFBBindableObj() {
- GrAlwaysAssert(0 == fColorReferees.count());
- GrAlwaysAssert(0 == fDepthReferees.count());
- GrAlwaysAssert(0 == fStencilReferees.count());
- }
-
- void setColorBound(GrFakeRefObj *referee) {
- fColorReferees.append(1, &referee);
- }
- void resetColorBound(GrFakeRefObj *referee) {
- int index = fColorReferees.find(referee);
- GrAlwaysAssert(0 <= index);
- fColorReferees.removeShuffle(index);
- }
- bool getColorBound(GrFakeRefObj *referee) const {
- int index = fColorReferees.find(referee);
- return 0 <= index;
- }
- bool getColorBound() const {
- return 0 != fColorReferees.count();
- }
-
- void setDepthBound(GrFakeRefObj *referee) {
- fDepthReferees.append(1, &referee);
- }
- void resetDepthBound(GrFakeRefObj *referee) {
- int index = fDepthReferees.find(referee);
- GrAlwaysAssert(0 <= index);
- fDepthReferees.removeShuffle(index);
- }
- bool getDepthBound(GrFakeRefObj *referee) const {
- int index = fDepthReferees.find(referee);
- return 0 <= index;
- }
- bool getDepthBound() const {
- return 0 != fDepthReferees.count();
- }
-
- void setStencilBound(GrFakeRefObj *referee) {
- fStencilReferees.append(1, &referee);
- }
- void resetStencilBound(GrFakeRefObj *referee) {
- int index = fStencilReferees.find(referee);
- GrAlwaysAssert(0 <= index);
- fStencilReferees.removeShuffle(index);
- }
- bool getStencilBound(GrFakeRefObj *referee) const {
- int index = fStencilReferees.find(referee);
- return 0 <= index;
- }
- bool getStencilBound() const {
- return 0 != fStencilReferees.count();
- }
-
- int numSamples() { return fNumSamples; }
-
-protected:
- int fNumSamples;
-
-private:
- SkTDArray<GrFakeRefObj *> fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
- SkTDArray<GrFakeRefObj *> fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
- SkTDArray<GrFakeRefObj *> fStencilReferees; // frame buffers that use this as a stencil buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrFBBindableObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrFakeRefObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrFakeRefObj.h
deleted file mode 100644
index e59aeb3..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrFakeRefObj.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrFakeRefObj_DEFINED
-#define GrFakeRefObj_DEFINED
-
-#include "SkTypes.h"
-#include "gl/GrGLInterface.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// This object is used to track the OpenGL objects. We don't use real
-// reference counting (i.e., we don't free the objects when their ref count
-// goes to 0) so that we can detect invalid memory accesses. The refs we
-// are tracking in this class are actually OpenGL's references to the objects
-// not "ours"
-// Each object also gets a unique globally identifying ID
-class GrFakeRefObj : SkNoncopyable {
-public:
- GrFakeRefObj()
- : fRef(0)
- , fMarkedForDeletion(false)
- , fDeleted(false) {
-
- // source for globally unique IDs - 0 is reserved!
- static int fNextID = 0;
-
- fID = ++fNextID;
- }
- virtual ~GrFakeRefObj() {}
-
- void ref() {
- fRef++;
- }
- void unref() {
- fRef--;
- GrAlwaysAssert(fRef >= 0);
-
- // often in OpenGL a given object may still be in use when the
- // delete call is made. In these cases the object is marked
- // for deletion and then freed when it is no longer in use
- if (0 == fRef && fMarkedForDeletion) {
- this->deleteAction();
- }
- }
- int getRefCount() const { return fRef; }
-
- GrGLuint getID() const { return fID; }
-
- void setMarkedForDeletion() { fMarkedForDeletion = true; }
- bool getMarkedForDeletion() const { return fMarkedForDeletion; }
-
- bool getDeleted() const { return fDeleted; }
-
- // The deleteAction fires if the object has been marked for deletion but
- // couldn't be deleted earlier due to refs
- virtual void deleteAction() {
- this->setDeleted();
- }
-
-protected:
-private:
- int fRef; // ref count
- GrGLuint fID; // globally unique ID
- bool fMarkedForDeletion;
- // The deleted flag is only set when OpenGL thinks the object is deleted
- // It is obviously still allocated w/in this framework
- bool fDeleted;
-
- // setDeleted should only ever appear in the deleteAction method!
- void setDeleted() { fDeleted = true; }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Each class derived from GrFakeRefObj should use this macro to add a
-// factory creation entry point. This entry point is used by the GrGLDebug
-// object to instantiate the various objects
-// all globally unique IDs
-#define GR_DEFINE_CREATOR(className) \
-public: \
- static GrFakeRefObj *create##className() { return new className; }
-
-#endif // GrFakeRefObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.cpp
deleted file mode 100644
index 7dc12ac..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrFrameBufferObj.h"
-#include "GrFBBindableObj.h"
-
-void GrFrameBufferObj::setColor(GrFBBindableObj *buffer) {
- if (fColorBuffer) {
- // automatically break the binding of the old buffer
- GrAlwaysAssert(fColorBuffer->getColorBound(this));
- fColorBuffer->resetColorBound(this);
-
- GrAlwaysAssert(!fColorBuffer->getDeleted());
- fColorBuffer->unref();
- }
- fColorBuffer = buffer;
- if (fColorBuffer) {
- GrAlwaysAssert(!fColorBuffer->getDeleted());
- fColorBuffer->ref();
-
- GrAlwaysAssert(!fColorBuffer->getColorBound(this));
- fColorBuffer->setColorBound(this);
- }
-}
-
-void GrFrameBufferObj::setDepth(GrFBBindableObj *buffer) {
- if (fDepthBuffer) {
- // automatically break the binding of the old buffer
- GrAlwaysAssert(fDepthBuffer->getDepthBound(this));
- fDepthBuffer->resetDepthBound(this);
-
- GrAlwaysAssert(!fDepthBuffer->getDeleted());
- fDepthBuffer->unref();
- }
- fDepthBuffer = buffer;
- if (fDepthBuffer) {
- GrAlwaysAssert(!fDepthBuffer->getDeleted());
- fDepthBuffer->ref();
-
- GrAlwaysAssert(!fDepthBuffer->getDepthBound(this));
- fDepthBuffer->setDepthBound(this);
- }
-}
-
-void GrFrameBufferObj::setStencil(GrFBBindableObj *buffer) {
- if (fStencilBuffer) {
- // automatically break the binding of the old buffer
- GrAlwaysAssert(fStencilBuffer->getStencilBound(this));
- fStencilBuffer->resetStencilBound(this);
-
- //GrAlwaysAssert(!fStencilBuffer->getDeleted());
- fStencilBuffer->unref();
- }
- fStencilBuffer = buffer;
- if (fStencilBuffer) {
- GrAlwaysAssert(!fStencilBuffer->getDeleted());
- fStencilBuffer->ref();
-
- GrAlwaysAssert(!fStencilBuffer->getStencilBound(this));
- fStencilBuffer->setStencilBound(this);
- }
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.h
deleted file mode 100644
index 9003127..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrFrameBufferObj.h
+++ /dev/null
@@ -1,68 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrFrameBufferObj_DEFINED
-#define GrFrameBufferObj_DEFINED
-
-#include "GrFakeRefObj.h"
-class GrFBBindableObj;
-
-////////////////////////////////////////////////////////////////////////////////
-// TODO: when a framebuffer obj is bound the GL_SAMPLES query must return 0
-// TODO: GL_STENCIL_BITS must also be redirected to the framebuffer
-class GrFrameBufferObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrFrameBufferObj)
-
-public:
- GrFrameBufferObj()
- : GrFakeRefObj()
- , fBound(false)
- , fColorBuffer(nullptr)
- , fDepthBuffer(nullptr)
- , fStencilBuffer(nullptr) {
- }
-
- ~GrFrameBufferObj() override {
- fColorBuffer = nullptr;
- fDepthBuffer = nullptr;
- fStencilBuffer = nullptr;
- }
-
- void setBound() { fBound = true; }
- void resetBound() { fBound = false; }
- bool getBound() const { return fBound; }
-
- void setColor(GrFBBindableObj *buffer);
- GrFBBindableObj *getColor() { return fColorBuffer; }
-
- void setDepth(GrFBBindableObj *buffer);
- GrFBBindableObj *getDepth() { return fDepthBuffer; }
-
- void setStencil(GrFBBindableObj *buffer);
- GrFBBindableObj *getStencil() { return fStencilBuffer; }
-
- void deleteAction() override {
-
- setColor(nullptr);
- setDepth(nullptr);
- setStencil(nullptr);
-
- this->INHERITED::deleteAction();
- }
-
-protected:
-private:
- bool fBound; // is this frame buffer currently bound via "glBindFramebuffer"?
- GrFBBindableObj * fColorBuffer;
- GrFBBindableObj * fDepthBuffer;
- GrFBBindableObj * fStencilBuffer;
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrFrameBufferObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.cpp
deleted file mode 100644
index d6cc36b..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrProgramObj.h"
-#include "GrShaderObj.h"
-
-void GrProgramObj::AttachShader(GrShaderObj *shader) {
- shader->ref();
- fShaders.push_back(shader);
-}
-
-void GrProgramObj::deleteAction() {
-
- // shaders are automatically detached from a deleted program. They will only be
- // deleted if they were marked for deletion by a prior call to glDeleteShader
- for (int i = 0; i < fShaders.count(); ++i) {
- fShaders[i]->unref();
- }
- fShaders.reset();
-
- this->INHERITED::deleteAction();
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.h
deleted file mode 100644
index f4ff9d1..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrProgramObj.h
+++ /dev/null
@@ -1,43 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrProgramObj_DEFINED
-#define GrProgramObj_DEFINED
-
-#include "SkTArray.h"
-#include "GrFakeRefObj.h"
-class GrShaderObj;
-
-////////////////////////////////////////////////////////////////////////////////
-class GrProgramObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrProgramObj)
-
-public:
- GrProgramObj()
- : GrFakeRefObj()
- , fInUse(false) {}
-
- void AttachShader(GrShaderObj *shader);
-
- void deleteAction() override;
-
- // TODO: this flag system won't work w/ multiple contexts!
- void setInUse() { fInUse = true; }
- void resetInUse() { fInUse = false; }
- bool getInUse() const { return fInUse; }
-
-protected:
-
-private:
- SkTArray<GrShaderObj *> fShaders;
- bool fInUse; // has this program been activated by a glUseProgram call?
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrProgramObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrRenderBufferObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrRenderBufferObj.h
deleted file mode 100644
index 1802eb5..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrRenderBufferObj.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrRenderBufferObj_DEFINED
-#define GrRenderBufferObj_DEFINED
-
-#include "GrFBBindableObj.h"
-
-////////////////////////////////////////////////////////////////////////////////
-class GrRenderBufferObj : public GrFBBindableObj {
- GR_DEFINE_CREATOR(GrRenderBufferObj)
-
-public:
- GrRenderBufferObj()
- : GrFBBindableObj()
- , fBound(false) {
- }
-
- void setBound() { fBound = true; }
- void resetBound() { fBound = false; }
- bool getBound() const { return fBound; }
-
- void deleteAction() override {
-
- this->INHERITED::deleteAction();
- }
-
- void setNumSamples(int numSamples) {
- GrAlwaysAssert(numSamples > 0);
- fNumSamples = numSamples;
- }
-
-protected:
-private:
- bool fBound; // is this render buffer currently bound via "glBindRenderbuffer"?
-
- typedef GrFBBindableObj INHERITED;
-};
-
-#endif // GrRenderBufferObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.cpp
deleted file mode 100644
index 8d3caa1..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrShaderObj.h"
-
-void GrShaderObj::deleteAction() {
-
- this->INHERITED::deleteAction();
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.h
deleted file mode 100644
index 8ecb990..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrShaderObj.h
+++ /dev/null
@@ -1,36 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrShaderObj_DEFINED
-#define GrShaderObj_DEFINED
-
-#include "GrFakeRefObj.h"
-#include "gl/GrGLDefines.h"
-
-////////////////////////////////////////////////////////////////////////////////
-class GrShaderObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrShaderObj)
-
-public:
- GrShaderObj()
- : GrFakeRefObj()
- , fType(GR_GL_VERTEX_SHADER) {}
-
- void setType(GrGLenum type) { fType = type; }
- GrGLenum getType() { return fType; }
-
- void deleteAction() override;
-
-protected:
-private:
- GrGLenum fType; // either GR_GL_VERTEX_SHADER or GR_GL_FRAGMENT_SHADER
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrShaderObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.cpp
deleted file mode 100644
index 86063fb..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrTextureObj.h"
-
-void GrTextureObj::deleteAction() {
-
- this->INHERITED::deleteAction();
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.h
deleted file mode 100644
index 5532723..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrTextureObj.h
+++ /dev/null
@@ -1,57 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrTextureObj_DEFINED
-#define GrTextureObj_DEFINED
-
-#include "GrFBBindableObj.h"
-
-class GrTextureUnitObj;
-
-////////////////////////////////////////////////////////////////////////////////
-class GrTextureObj : public GrFBBindableObj {
- GR_DEFINE_CREATOR(GrTextureObj)
-
-public:
- GrTextureObj()
- : GrFBBindableObj() {
- }
-
- ~GrTextureObj() override {
- GrAlwaysAssert(0 == fTextureUnitReferees.count());
- }
-
- void setBound(GrTextureUnitObj *referee) {
- fTextureUnitReferees.append(1, &referee);
- }
-
- void resetBound(GrTextureUnitObj *referee) {
- int index = fTextureUnitReferees.find(referee);
- GrAlwaysAssert(0 <= index);
- fTextureUnitReferees.removeShuffle(index);
- }
- bool getBound(GrTextureUnitObj *referee) const {
- int index = fTextureUnitReferees.find(referee);
- return 0 <= index;
- }
- bool getBound() const {
- return 0 != fTextureUnitReferees.count();
- }
-
- void deleteAction() override;
-
-protected:
-
-private:
- // texture units that bind this texture (via "glBindTexture")
- SkTDArray<GrTextureUnitObj *> fTextureUnitReferees;
-
- typedef GrFBBindableObj INHERITED;
-};
-
-#endif // GrTextureObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.cpp b/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.cpp
deleted file mode 100644
index 316dcec..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrTextureUnitObj.h"
-#include "GrTextureObj.h"
-
-void GrTextureUnitObj::setTexture(GrTextureObj *texture) {
-
- if (fTexture) {
- GrAlwaysAssert(fTexture->getBound(this));
- fTexture->resetBound(this);
-
- GrAlwaysAssert(!fTexture->getDeleted());
- fTexture->unref();
- }
-
- fTexture = texture;
-
- if (fTexture) {
- GrAlwaysAssert(!fTexture->getDeleted());
- fTexture->ref();
-
- GrAlwaysAssert(!fTexture->getBound(this));
- fTexture->setBound(this);
- }
-}
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.h
deleted file mode 100644
index b06d117..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrTextureUnitObj.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrTextureUnitObj_DEFINED
-#define GrTextureUnitObj_DEFINED
-
-#include "GrFakeRefObj.h"
-class GrTextureObj;
-
-////////////////////////////////////////////////////////////////////////////////
-// Although texture unit objects are allocated & deallocated like the other
-// GL emulation objects they are derived from GrFakeRefObj to provide some
-// uniformity in how the debug interface class manages resources
-class GrTextureUnitObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrTextureUnitObj)
-
-public:
- GrTextureUnitObj()
- : GrFakeRefObj()
- , fNumber(0)
- , fTexture(nullptr) {
- }
-
- void setNumber(GrGLenum number) {
- fNumber = number;
- }
- GrGLenum getNumber() const { return fNumber; }
-
- void setTexture(GrTextureObj *texture);
- GrTextureObj *getTexture() { return fTexture; }
-
-protected:
-private:
- GrGLenum fNumber;
- GrTextureObj *fTexture;
-
- typedef GrFakeRefObj INHERITED;
-};
-
-#endif // GrTextureUnitObj_DEFINED
diff --git a/src/third_party/skia/tools/gpu/gl/debug/GrVertexArrayObj.h b/src/third_party/skia/tools/gpu/gl/debug/GrVertexArrayObj.h
deleted file mode 100644
index 3aeb0b2..0000000
--- a/src/third_party/skia/tools/gpu/gl/debug/GrVertexArrayObj.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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 GrVertexArrayObj_DEFINED
-#define GrVertexArrayObj_DEFINED
-
-#include "GrFakeRefObj.h"
-
-class GrVertexArrayObj : public GrFakeRefObj {
- GR_DEFINE_CREATOR(GrVertexArrayObj)
-
-public:
- GrVertexArrayObj() : GrFakeRefObj() {}
-
- typedef GrFakeRefObj INHERITED;
-};
-#endif
diff --git a/src/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/src/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
index c006098..96900fd 100644
--- a/src/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
+++ b/src/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
@@ -5,16 +5,17 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
#define GL_GLEXT_PROTOTYPES
+
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "gl/GrGLDefines.h"
-#include "gl/GrGLUtil.h"
+#include "src/gpu/gl/GrGLDefines.h"
+#include "src/gpu/gl/GrGLUtil.h"
namespace {
@@ -39,6 +40,16 @@
typedef sk_gpu_test::FenceSync INHERITED;
};
+std::function<void()> context_restorer() {
+ auto display = eglGetCurrentDisplay();
+ auto dsurface = eglGetCurrentSurface(EGL_DRAW);
+ auto rsurface = eglGetCurrentSurface(EGL_READ);
+ auto context = eglGetCurrentContext();
+ return [display, dsurface, rsurface, context] {
+ eglMakeCurrent(display, dsurface, rsurface, context);
+ };
+}
+
class EGLGLTestContext : public sk_gpu_test::GLTestContext {
public:
EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
@@ -53,14 +64,38 @@
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
+ PFNEGLCREATEIMAGEKHRPROC fEglCreateImageProc = nullptr;
+ PFNEGLDESTROYIMAGEKHRPROC fEglDestroyImageProc = nullptr;
+
EGLContext fContext;
EGLDisplay fDisplay;
EGLSurface fSurface;
};
+static EGLContext create_gles_egl_context(EGLDisplay display,
+ EGLConfig surfaceConfig,
+ EGLContext eglShareContext,
+ EGLint eglContextClientVersion) {
+ const EGLint contextAttribsForOpenGLES[] = {
+ EGL_CONTEXT_CLIENT_VERSION,
+ eglContextClientVersion,
+ EGL_NONE
+ };
+ return eglCreateContext(display, surfaceConfig, eglShareContext, contextAttribsForOpenGLES);
+}
+static EGLContext create_gl_egl_context(EGLDisplay display,
+ EGLConfig surfaceConfig,
+ EGLContext eglShareContext) {
+ const EGLint contextAttribsForOpenGL[] = {
+ EGL_NONE
+ };
+ return eglCreateContext(display, surfaceConfig, eglShareContext, contextAttribsForOpenGL);
+}
+
EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext)
: fContext(EGL_NO_CONTEXT)
, fDisplay(EGL_NO_DISPLAY)
@@ -68,43 +103,19 @@
EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
- static const EGLint kEGLContextAttribsForOpenGL[] = {
- EGL_NONE
+ static const GrGLStandard kStandards[] = {
+ kGL_GrGLStandard,
+ kGLES_GrGLStandard,
};
- static const EGLint kEGLContextAttribsForOpenGLES[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- static const struct {
- const EGLint* fContextAttribs;
- EGLenum fAPI;
- EGLint fRenderableTypeBit;
- GrGLStandard fStandard;
- } kAPIs[] = {
- { // OpenGL
- kEGLContextAttribsForOpenGL,
- EGL_OPENGL_API,
- EGL_OPENGL_BIT,
- kGL_GrGLStandard
- },
- { // OpenGL ES. This seems to work for both ES2 and 3 (when available).
- kEGLContextAttribsForOpenGLES,
- EGL_OPENGL_ES_API,
- EGL_OPENGL_ES2_BIT,
- kGLES_GrGLStandard
- },
- };
-
- size_t apiLimit = SK_ARRAY_COUNT(kAPIs);
+ size_t apiLimit = SK_ARRAY_COUNT(kStandards);
size_t api = 0;
if (forcedGpuAPI == kGL_GrGLStandard) {
apiLimit = 1;
} else if (forcedGpuAPI == kGLES_GrGLStandard) {
api = 1;
}
- SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI);
+ SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kStandards[api] == forcedGpuAPI);
sk_sp<const GrGLInterface> gl;
@@ -121,15 +132,16 @@
SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS));
#endif
+ bool gles = kGLES_GrGLStandard == kStandards[api];
- if (!eglBindAPI(kAPIs[api].fAPI)) {
+ if (!eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) {
continue;
}
EGLint numConfigs = 0;
const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit,
+ EGL_RENDERABLE_TYPE, gles ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
@@ -148,8 +160,20 @@
continue;
}
- fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext,
- kAPIs[api].fContextAttribs);
+ if (gles) {
+#ifdef GR_EGL_TRY_GLES3_THEN_GLES2
+ // Some older devices (Nexus7/Tegra3) crash when you try this. So it is (for now)
+ // hidden behind this flag.
+ fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 3);
+ if (EGL_NO_CONTEXT == fContext) {
+ fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 2);
+ }
+#else
+ fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 2);
+#endif
+ } else {
+ fContext = create_gl_egl_context(fDisplay, surfaceConfig, eglShareContext);
+ }
if (EGL_NO_CONTEXT == fContext) {
SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError());
continue;
@@ -168,14 +192,15 @@
continue;
}
+ SkScopeExit restorer(context_restorer());
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
this->destroyGLContext();
continue;
}
- gl.reset(GrGLCreateNativeInterface());
- if (nullptr == gl.get()) {
+ gl = GrGLMakeNativeInterface();
+ if (!gl) {
SkDebugf("Failed to create gl interface.\n");
this->destroyGLContext();
continue;
@@ -186,8 +211,14 @@
this->destroyGLContext();
continue;
}
+ const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
+ if (strstr(extensions, "EGL_KHR_image")) {
+ fEglCreateImageProc = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+ fEglDestroyImageProc =
+ (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+ }
- this->init(gl.release(), EGLFenceSync::MakeIfSupported(fDisplay));
+ this->init(std::move(gl), EGLFenceSync::MakeIfSupported(fDisplay));
break;
}
}
@@ -199,9 +230,11 @@
void EGLGLTestContext::destroyGLContext() {
if (fDisplay) {
- eglMakeCurrent(fDisplay, 0, 0, 0);
-
if (fContext) {
+ if (eglGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
eglDestroyContext(fDisplay, fContext);
fContext = EGL_NO_CONTEXT;
}
@@ -217,19 +250,16 @@
}
GrEGLImage EGLGLTestContext::texture2DToEGLImage(GrGLuint texID) const {
- if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
+ if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image") || !fEglCreateImageProc) {
return GR_EGL_NO_IMAGE;
}
- GrEGLImage img;
- GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0, GR_EGL_NONE };
+ EGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0, GR_EGL_NONE };
GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>(texID);
- GR_GL_CALL_RET(this->gl(), img,
- EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs));
- return img;
+ return fEglCreateImageProc(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs);
}
void EGLGLTestContext::destroyEGLImage(GrEGLImage image) const {
- GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
+ fEglDestroyImageProc(fDisplay, image);
}
GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
@@ -237,7 +267,6 @@
if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
return 0;
}
-#ifndef EGL_NO_IMAGE_EXTERNAL
typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
@@ -246,24 +275,21 @@
return 0;
}
GrGLuint texID;
- glGenTextures(1, &texID);
+ GR_GL_CALL(this->gl(), GenTextures(1, &texID));
if (!texID) {
return 0;
}
- glBindTexture(GR_GL_TEXTURE_EXTERNAL, texID);
- if (glGetError() != GR_GL_NO_ERROR) {
- glDeleteTextures(1, &texID);
+ GR_GL_CALL_NOERRCHECK(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
- if (glGetError() != GR_GL_NO_ERROR) {
- glDeleteTextures(1, &texID);
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
return texID;
-#else
- return 0;
-#endif //EGL_NO_IMAGE_EXTERNAL
}
std::unique_ptr<sk_gpu_test::GLTestContext> EGLGLTestContext::makeNew() const {
@@ -281,6 +307,13 @@
}
}
+std::function<void()> EGLGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (eglGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void EGLGLTestContext::onPlatformSwapBuffers() const {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
diff --git a/src/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp b/src/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
index 76b6d21..5e643e2 100644
--- a/src/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
+++ b/src/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#include "gl/GLTestContext.h"
-#include "SkOnce.h"
+#include "include/private/SkOnce.h"
+#include "tools/gpu/gl/GLTestContext.h"
#include <X11/Xlib.h>
#include <GL/glx.h>
@@ -62,6 +62,7 @@
GLXContext glxSharedContext);
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -90,11 +91,27 @@
return ad->display();
}
+std::function<void()> context_restorer() {
+ auto display = glXGetCurrentDisplay();
+ auto drawable = glXGetCurrentDrawable();
+ auto context = glXGetCurrentContext();
+ // On some systems calling glXMakeCurrent with a null display crashes.
+ if (!display) {
+ display = get_display();
+ }
+ return [display, drawable, context] { glXMakeCurrent(display, drawable, context); };
+}
+
GLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareContext)
: fContext(nullptr)
, fDisplay(nullptr)
, fPixmap(0)
, fGlxPixmap(0) {
+ // We cross our fingers that this is the first X call in the program and that if the application
+ // is actually threaded that this succeeds.
+ static SkOnce gOnce;
+ gOnce([] { XInitThreads(); });
+
fDisplay = get_display();
GLXContext glxShareContext = shareContext ? shareContext->fContext : nullptr;
@@ -214,6 +231,7 @@
//SkDebugf("Direct GLX rendering context obtained.\n");
}
+ SkScopeExit restorer(context_restorer());
//SkDebugf("Making context current.\n");
if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
SkDebugf("Could not set the context.\n");
@@ -221,8 +239,8 @@
return;
}
- sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
- if (nullptr == gl.get()) {
+ auto gl = GrGLMakeNativeInterface();
+ if (!gl) {
SkDebugf("Failed to create gl interface");
this->destroyGLContext();
return;
@@ -234,7 +252,7 @@
return;
}
- this->init(gl.release());
+ this->init(std::move(gl));
}
@@ -245,9 +263,11 @@
void GLXGLTestContext::destroyGLContext() {
if (fDisplay) {
- glXMakeCurrent(fDisplay, 0, 0);
-
if (fContext) {
+ if (glXGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ glXMakeContextCurrent(fDisplay, None, None, nullptr);
+ }
glXDestroyContext(fDisplay, fContext);
fContext = nullptr;
}
@@ -334,6 +354,13 @@
}
}
+std::function<void()> GLXGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (glXGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void GLXGLTestContext::onPlatformSwapBuffers() const {
glXSwapBuffers(fDisplay, fGlxPixmap);
}
diff --git a/src/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm b/src/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
index 1fd50d1..0605fdf 100644
--- a/src/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
+++ b/src/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
@@ -6,7 +6,7 @@
* found in the LICENSE file.
*/
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
#import <OpenGLES/EAGL.h>
#include <dlfcn.h>
@@ -14,6 +14,11 @@
namespace {
+std::function<void()> context_restorer() {
+ EAGLContext* context = [EAGLContext currentContext];
+ return [context] { [EAGLContext setCurrentContext:context]; };
+}
+
class IOSGLTestContext : public sk_gpu_test::GLTestContext {
public:
IOSGLTestContext(IOSGLTestContext* shareContext);
@@ -23,6 +28,7 @@
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -36,11 +42,19 @@
if (shareContext) {
EAGLContext* iosShareContext = shareContext->fEAGLContext;
- fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
- sharegroup: [iosShareContext sharegroup]];
+ fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
+ sharegroup:[iosShareContext sharegroup]];
+ if (fEAGLContext == nil) {
+ fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
+ sharegroup:[iosShareContext sharegroup]];
+ }
} else {
- fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
+ if (fEAGLContext == nil) {
+ fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ }
}
+ SkScopeExit restorer(context_restorer());
[EAGLContext setCurrentContext:fEAGLContext];
sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
@@ -59,7 +73,7 @@
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
RTLD_LAZY);
- this->init(gl.release());
+ this->init(std::move(gl));
}
IOSGLTestContext::~IOSGLTestContext() {
@@ -70,11 +84,12 @@
void IOSGLTestContext::destroyGLContext() {
if (fEAGLContext) {
if ([EAGLContext currentContext] == fEAGLContext) {
+ // This will ensure that the context is immediately deleted.
[EAGLContext setCurrentContext:nil];
}
fEAGLContext = nil;
}
- if (RTLD_DEFAULT != fGLLibrary) {
+ if (nullptr != fGLLibrary) {
dlclose(fGLLibrary);
}
}
@@ -86,10 +101,18 @@
}
}
+std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
+ if ([EAGLContext currentContext] == fEAGLContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void IOSGLTestContext::onPlatformSwapBuffers() const { }
GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const {
- return reinterpret_cast<GrGLFuncPtr>(dlsym(fGLLibrary, procName));
+ void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
+ return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
}
} // anonymous namespace
diff --git a/src/third_party/skia/tools/gpu/gl/interface/Makefile b/src/third_party/skia/tools/gpu/gl/interface/Makefile
new file mode 100644
index 0000000..b7f5ced
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/gl/interface/Makefile
@@ -0,0 +1,5 @@
+generate:
+ go run *.go --in_table "./interface.json5" --out_dir "../../../../src/gpu/gl"
+
+dryrun:
+ go run *.go --in_table "./interface.json5" --out_dir "../../../../src/gpu/gl" --dryrun
\ No newline at end of file
diff --git a/src/third_party/skia/tools/gpu/gl/interface/README.md b/src/third_party/skia/tools/gpu/gl/interface/README.md
new file mode 100644
index 0000000..f4e1788
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/gl/interface/README.md
@@ -0,0 +1,22 @@
+GrGlInterface Autogeneration
+============================
+
+Background
+----------
+
+At a high level, the first three steps of making a GrGLInterface (a generic way to
+interact with a GL-like GPU) are:
+
+ - Assemble: Copy a set of function pointers into the struct
+ - Validate: Make sure the function pointers advertised actually exist.
+ - Capabilities: Compute what fast/slow paths are enabled based on the functions
+ in the struct (GrGLCaps, for short)
+
+Autogeneration
+--------------
+
+The first two steps have been automated with a table-based generation script located
+in this folder. The table is in JSON5 format (like JSON, but with comments). O
+
+Once edited, the Assemble/Validate code can be re-generated by running
+`make generate` in this folder.
\ No newline at end of file
diff --git a/src/third_party/skia/tools/gpu/gl/interface/gen_interface.go b/src/third_party/skia/tools/gpu/gl/interface/gen_interface.go
new file mode 100644
index 0000000..6eb94a5
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/gl/interface/gen_interface.go
@@ -0,0 +1,460 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package main
+
+// gen_interface creates the assemble/validate cpp files given the
+// interface.json5 file.
+// See README for more details.
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "github.com/flynn/json5"
+)
+
+var (
+ outDir = flag.String("out_dir", "../../src/gpu/gl", "Where to output the GrGlAssembleInterface_* and GrGlInterface.cpp files")
+ inTable = flag.String("in_table", "./interface.json5", "The JSON5 table to read in")
+ dryRun = flag.Bool("dryrun", false, "Print the outputs, don't write to file")
+)
+
+const (
+ CORE_FEATURE = "<core>"
+ SPACER = " "
+ GLES_FILE_NAME = "GrGLAssembleGLESInterfaceAutogen.cpp"
+ GL_FILE_NAME = "GrGLAssembleGLInterfaceAutogen.cpp"
+ WEBGL_FILE_NAME = "GrGLAssembleWebGLInterfaceAutogen.cpp"
+ INTERFACE_FILE_NAME = "GrGLInterfaceAutogen.cpp"
+)
+
+// FeatureSet represents one set of requirements for each of the GL "standards" that
+// Skia supports. This is currently OpenGL, OpenGL ES and WebGL.
+// OpenGL is typically abbreviated as just "GL".
+// https://www.khronos.org/registry/OpenGL/index_gl.php
+// https://www.khronos.org/opengles/
+// https://www.khronos.org/registry/webgl/specs/1.0/
+type FeatureSet struct {
+ GLReqs []Requirement `json:"GL"`
+ GLESReqs []Requirement `json:"GLES"`
+ WebGLReqs []Requirement `json:"WebGL"`
+
+ Functions []string `json:"functions"`
+ HardCodeFunctions []HardCodeFunction `json:"hardcode_functions"`
+ OptionalFunctions []string `json:"optional"` // not checked in validate
+
+ // only assembled/validated when testing
+ TestOnlyFunctions []string `json:"test_functions"`
+
+ Required bool `json:"required"`
+}
+
+// Requirement lists how we know if a function exists. Extension is the
+// GL extension (or the string CORE_FEATURE if it's part of the core functionality).
+// MinVersion optionally indicates the minimum version of a standard
+// that has the function.
+// SuffixOverride allows the extension suffix to be manually specified instead
+// of automatically derived from the extension name.
+// (for example, if an NV extension specifies some EXT extensions)
+type Requirement struct {
+ Extension string `json:"ext"` // required
+ MinVersion *GLVersion `json:"min_version"`
+ SuffixOverride *string `json:"suffix"`
+}
+
+// HardCodeFunction indicates to not use the C++ macro and just directly
+// adds a given function ptr to the struct.
+type HardCodeFunction struct {
+ PtrName string `json:"ptr_name"`
+ CastName string `json:"cast_name"`
+ GetName string `json:"get_name"`
+}
+
+var CORE_REQUIREMENT = Requirement{Extension: CORE_FEATURE, MinVersion: nil}
+
+type GLVersion [2]int
+
+// RequirementGetter functions allows us to "iterate" over the requirements
+// of the different standards which are stored as keys in FeatureSet and
+// normally not easily iterable.
+type RequirementGetter func(FeatureSet) []Requirement
+
+func glRequirements(fs FeatureSet) []Requirement {
+ return fs.GLReqs
+}
+
+func glesRequirements(fs FeatureSet) []Requirement {
+ return fs.GLESReqs
+}
+
+func webglRequirements(fs FeatureSet) []Requirement {
+ return fs.WebGLReqs
+}
+
+// generateAssembleInterface creates one GrGLAssembleInterface_[type]_gen.cpp
+// for each of the standards
+func generateAssembleInterface(features []FeatureSet) {
+ gl := fillAssembleTemplate(ASSEMBLE_INTERFACE_GL, features, glRequirements)
+ writeToFile(*outDir, GL_FILE_NAME, gl)
+ gles := fillAssembleTemplate(ASSEMBLE_INTERFACE_GL_ES, features, glesRequirements)
+ writeToFile(*outDir, GLES_FILE_NAME, gles)
+ webgl := fillAssembleTemplate(ASSEMBLE_INTERFACE_WEBGL, features, webglRequirements)
+ writeToFile(*outDir, WEBGL_FILE_NAME, webgl)
+}
+
+// fillAssembleTemplate returns a generated file given a template (for a single standard)
+// to fill out and a slice of features with which to fill it. getReqs is used to select
+// the requirements for the standard we are working on.
+func fillAssembleTemplate(template string, features []FeatureSet, getReqs RequirementGetter) string {
+ content := ""
+ for _, feature := range features {
+ // For each feature set, we are going to create a series of
+ // if statements, which check for the requirements (e.g. extensions, version)
+ // and inside those if branches, write the code to load the
+ // correct function pointer to the interface. GET_PROC and
+ // GET_PROC_SUFFIX are macros defined in C++ part of the template
+ // to accomplish this (for a core feature and extensions, respectively).
+ reqs := getReqs(feature)
+ if len(reqs) == 0 {
+ continue
+ }
+ // blocks holds all the if blocks generated - it will be joined with else
+ // after and appended to content
+ blocks := []string{}
+ for i, req := range reqs {
+ block := ""
+ ifExpr := requirementIfExpression(req, true)
+
+ if ifExpr != "" {
+ if strings.HasPrefix(ifExpr, "(") {
+ ifExpr = "if " + ifExpr + " {"
+ } else {
+ ifExpr = "if (" + ifExpr + ") {"
+ }
+ // Indent the first if statement
+ if i == 0 {
+ block = addLine(block, ifExpr)
+ } else {
+ block += ifExpr + "\n"
+ }
+ }
+ // sort for determinism
+ sort.Strings(feature.Functions)
+ for _, function := range feature.Functions {
+ block = assembleFunction(block, ifExpr, function, req)
+ }
+ sort.Strings(feature.TestOnlyFunctions)
+ if len(feature.TestOnlyFunctions) > 0 {
+ block += "#if GR_TEST_UTILS\n"
+ for _, function := range feature.TestOnlyFunctions {
+ block = assembleFunction(block, ifExpr, function, req)
+ }
+ block += "#endif\n"
+ }
+
+ // a hard code function does not use the C++ macro
+ for _, hcf := range feature.HardCodeFunctions {
+ if ifExpr != "" {
+ // extra tab for being in an if statement
+ block += SPACER
+ }
+ line := fmt.Sprintf(`functions->%s =(%s*)get(ctx, "%s");`, hcf.PtrName, hcf.CastName, hcf.GetName)
+ block = addLine(block, line)
+ }
+ if ifExpr != "" {
+ block += SPACER + "}"
+ }
+ blocks = append(blocks, block)
+ }
+ content += strings.Join(blocks, " else ")
+
+ if feature.Required && reqs[0] != CORE_REQUIREMENT {
+ content += ` else {
+ SkASSERT(false); // Required feature
+ return nullptr;
+ }`
+ }
+
+ if !strings.HasSuffix(content, "\n") {
+ content += "\n"
+ }
+ // Add an extra space between blocks for easier readability
+ content += "\n"
+
+ }
+
+ return strings.Replace(template, "[[content]]", content, 1)
+}
+
+// assembleFunction is a little helper that will add a function to the interface
+// using an appropriate macro (e.g. if the function is added)
+// with an extension.
+func assembleFunction(block, ifExpr, function string, req Requirement) string {
+ if ifExpr != "" {
+ // extra tab for being in an if statement
+ block += SPACER
+ }
+ suffix := deriveSuffix(req.Extension)
+ // Some ARB extensions don't have ARB suffixes because they were written
+ // for backwards compatibility simultaneous to adding them as required
+ // in a new GL version.
+ if suffix == "ARB" {
+ suffix = ""
+ }
+ if req.SuffixOverride != nil {
+ suffix = *req.SuffixOverride
+ }
+ if req.Extension == CORE_FEATURE || suffix == "" {
+ block = addLine(block, fmt.Sprintf("GET_PROC(%s);", function))
+ } else if req.Extension != "" {
+ block = addLine(block, fmt.Sprintf("GET_PROC_SUFFIX(%s, %s);", function, suffix))
+ }
+ return block
+}
+
+// requirementIfExpression returns a string that is an if expression
+// Notably, there is no if expression if the function is a "core" function
+// on all supported versions.
+// The expressions are wrapped in parentheses so they can be safely
+// joined together with && or ||.
+func requirementIfExpression(req Requirement, isLocal bool) string {
+ mv := req.MinVersion
+ if req == CORE_REQUIREMENT {
+ return ""
+ }
+ if req.Extension == CORE_FEATURE && mv != nil {
+ return fmt.Sprintf("(glVer >= GR_GL_VER(%d,%d))", mv[0], mv[1])
+ }
+ extVar := "fExtensions"
+ if isLocal {
+ extVar = "extensions"
+ }
+ // We know it has an extension
+ if req.Extension != "" {
+ if mv == nil {
+ return fmt.Sprintf("%s.has(%q)", extVar, req.Extension)
+ } else {
+ return fmt.Sprintf("(glVer >= GR_GL_VER(%d,%d) && %s.has(%q))", mv[0], mv[1], extVar, req.Extension)
+ }
+ }
+ abort("ERROR: requirement must have ext")
+ return "ERROR"
+}
+
+// driveSuffix returns the suffix of the function associated with the given
+// extension.
+func deriveSuffix(ext string) string {
+ // Some extensions begin with GL_ and then have the actual
+ // extension like KHR, EXT etc.
+ ext = strings.TrimPrefix(ext, "GL_")
+ return strings.Split(ext, "_")[0]
+}
+
+// addLine is a little helper function which handles the newline and tab
+func addLine(str, line string) string {
+ return str + SPACER + line + "\n"
+}
+
+func writeToFile(parent, file, content string) {
+ p := filepath.Join(parent, file)
+ if *dryRun {
+ fmt.Printf("Writing to %s\n", p)
+ fmt.Println(content)
+ } else {
+ if err := ioutil.WriteFile(p, []byte(content), 0644); err != nil {
+ abort("Error while writing to file %s: %s", p, err)
+ }
+ }
+}
+
+// validationEntry is a helper struct that contains anything
+// necessary to make validation code for a given standard.
+type validationEntry struct {
+ StandardCheck string
+ GetReqs RequirementGetter
+}
+
+func generateValidateInterface(features []FeatureSet) {
+ standards := []validationEntry{
+ {
+ StandardCheck: "GR_IS_GR_GL(fStandard)",
+ GetReqs: glRequirements,
+ }, {
+ StandardCheck: "GR_IS_GR_GL_ES(fStandard)",
+ GetReqs: glesRequirements,
+ }, {
+ StandardCheck: "GR_IS_GR_WEBGL(fStandard)",
+ GetReqs: webglRequirements,
+ },
+ }
+ content := ""
+ // For each feature, we are going to generate a series of
+ // boolean expressions which check that the functions we thought
+ // were gathered during the assemble phase actually were applied to
+ // the interface (functionCheck). This check will be guarded
+ // another set of if statements (one per standard) based
+ // on the same requirements (standardChecks) that were used when
+ // assembling the interface.
+ for _, feature := range features {
+ if allReqsAreCore(feature) {
+ content += functionCheck(feature, 1)
+ } else {
+ content += SPACER
+ standardChecks := []string{}
+ for _, std := range standards {
+ reqs := std.GetReqs(feature)
+ if reqs == nil || len(reqs) == 0 {
+ continue
+ }
+ expr := []string{}
+ for _, r := range reqs {
+ e := requirementIfExpression(r, false)
+ if e != "" {
+ expr = append(expr, e)
+ }
+ }
+ check := ""
+ if len(expr) == 0 {
+ check = fmt.Sprintf("%s", std.StandardCheck)
+ } else {
+ lineBreak := "\n" + SPACER + " "
+ check = fmt.Sprintf("(%s && (%s%s))", std.StandardCheck, lineBreak, strings.Join(expr, " ||"+lineBreak))
+ }
+ standardChecks = append(standardChecks, check)
+ }
+ content += fmt.Sprintf("if (%s) {\n", strings.Join(standardChecks, " ||\n"+SPACER+" "))
+ content += functionCheck(feature, 2)
+
+ content += SPACER + "}\n"
+ }
+ // add additional line between each block
+ content += "\n"
+ }
+ content = strings.Replace(VALIDATE_INTERFACE, "[[content]]", content, 1)
+ writeToFile(*outDir, INTERFACE_FILE_NAME, content)
+}
+
+// functionCheck returns an if statement that checks that all functions
+// in the passed in slice are on the interface (that is, they are truthy
+// on the fFunctions struct)
+func functionCheck(feature FeatureSet, indentLevel int) string {
+ // sort for determinism
+ sort.Strings(feature.Functions)
+ indent := strings.Repeat(SPACER, indentLevel)
+
+ checks := []string{}
+ for _, function := range feature.Functions {
+ if in(function, feature.OptionalFunctions) {
+ continue
+ }
+ checks = append(checks, "!fFunctions.f"+function)
+ }
+ testOnly := []string{}
+ for _, function := range feature.TestOnlyFunctions {
+ if in(function, feature.OptionalFunctions) {
+ continue
+ }
+ testOnly = append(testOnly, "!fFunctions.f"+function)
+ }
+ for _, hcf := range feature.HardCodeFunctions {
+ checks = append(checks, "!fFunctions."+hcf.PtrName)
+ }
+ preCheck := ""
+ if len(testOnly) != 0 {
+ preCheck = fmt.Sprintf(`#if GR_TEST_UTILS
+%sif (%s) {
+%s%sRETURN_FALSE_INTERFACE;
+%s}
+#endif
+`, indent, strings.Join(testOnly, " ||\n"+indent+" "), indent, SPACER, indent)
+ }
+
+ if len(checks) == 0 {
+ return preCheck + strings.Repeat(SPACER, indentLevel) + "// all functions were marked optional or test_only\n"
+ }
+
+ return preCheck + fmt.Sprintf(`%sif (%s) {
+%s%sRETURN_FALSE_INTERFACE;
+%s}
+`, indent, strings.Join(checks, " ||\n"+indent+" "), indent, SPACER, indent)
+}
+
+// allReqsAreCore returns true iff the FeatureSet is part of "core" for
+// all standards
+func allReqsAreCore(feature FeatureSet) bool {
+ if feature.GLReqs == nil || feature.GLESReqs == nil {
+ return false
+ }
+ return feature.GLReqs[0] == CORE_REQUIREMENT && feature.GLESReqs[0] == CORE_REQUIREMENT && feature.WebGLReqs[0] == CORE_REQUIREMENT
+}
+
+func validateFeatures(features []FeatureSet) {
+ seen := map[string]bool{}
+ for _, feature := range features {
+ for _, fn := range feature.Functions {
+ if seen[fn] {
+ abort("ERROR: Duplicate function %s", fn)
+ }
+ seen[fn] = true
+ }
+ for _, fn := range feature.TestOnlyFunctions {
+ if seen[fn] {
+ abort("ERROR: Duplicate function %s\n", fn)
+ }
+ seen[fn] = true
+ }
+ }
+}
+
+// in returns true if |s| is *in* |a| slice.
+func in(s string, a []string) bool {
+ for _, x := range a {
+ if x == s {
+ return true
+ }
+ }
+ return false
+}
+
+func abort(fmtStr string, inputs ...interface{}) {
+ fmt.Printf(fmtStr+"\n", inputs...)
+ os.Exit(1)
+}
+
+func main() {
+ flag.Parse()
+ b, err := ioutil.ReadFile(*inTable)
+ if err != nil {
+ abort("Could not read file %s", err)
+ }
+
+ dir, err := os.Open(*outDir)
+ if err != nil {
+ abort("Could not write to output dir %s", err)
+ }
+ defer dir.Close()
+ if fi, err := dir.Stat(); err != nil {
+ abort("Error getting info about %s: %s", *outDir, err)
+ } else if !fi.IsDir() {
+ abort("%s must be a directory", *outDir)
+ }
+
+ features := []FeatureSet{}
+
+ err = json5.Unmarshal(b, &features)
+ if err != nil {
+ abort("Invalid JSON: %s", err)
+ }
+
+ validateFeatures(features)
+
+ generateAssembleInterface(features)
+ generateValidateInterface(features)
+}
diff --git a/src/third_party/skia/tools/gpu/gl/interface/interface.json5 b/src/third_party/skia/tools/gpu/gl/interface/interface.json5
new file mode 100644
index 0000000..ceb3f44
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/gl/interface/interface.json5
@@ -0,0 +1,692 @@
+// This file specifies which functions should be attached to GrGLInterface
+// for a given standard (OpenGL, OpenGL ES, etc). It allows specifing
+// how and when to attach them (e.g. only if an extension is present).
+// It is used for both the assemble and validate step.
+//
+// To regenerate the Assemble/Validate code after editing this file, execute:
+//
+// make -C tools/gpu/gl/interface generate
+//
+// Currently it assumes the minimum versions:
+// - GL: 2.0
+// - GLES: 2.0
+// - WebGL: [WIP] 1.0
+//
+// http://web.eecs.umich.edu/~sugih/courses/eecs487/common/notes/APITables.xml
+// is a handy reference comparing GL and GLES API
+[
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"ext": "<core>"}],
+ "WebGL": [{"ext": "<core>"}],
+
+ "functions": [
+ "ActiveTexture", "AttachShader", "BindAttribLocation", "BindBuffer",
+ "BindTexture", "BlendColor", "BlendEquation", "BlendFunc",
+ "BufferData", "BufferSubData", "Clear", "ClearColor",
+ "ClearStencil", "ColorMask", "CompileShader", "CompressedTexImage2D",
+ "CompressedTexSubImage2D", "CopyTexSubImage2D", "CreateProgram", "CreateShader",
+ "CullFace", "DeleteBuffers", "DeleteProgram",
+ "DeleteShader", "DeleteTextures", "DepthMask", "Disable",
+ "DisableVertexAttribArray", "DrawArrays", "DrawElements", "Enable",
+ "EnableVertexAttribArray", "Finish", "Flush",
+ "FrontFace", "GenBuffers",
+ "GenTextures", "GetBufferParameteriv", "GetError",
+ "GetIntegerv", "GetProgramInfoLog",
+ "GetProgramiv", "GetShaderInfoLog",
+ "GetShaderiv", "GetString",
+ "GetUniformLocation", "IsTexture", "LineWidth", "LinkProgram", "PixelStorei",
+ "ReadPixels", "Scissor", "ShaderSource", "StencilFunc",
+ "StencilFuncSeparate", "StencilMask", "StencilMaskSeparate", "StencilOp",
+ "StencilOpSeparate", "TexImage2D", "TexParameterf", "TexParameterfv", "TexParameteri",
+ "TexParameteriv", "TexSubImage2D", "Uniform1f", "Uniform1fv", "Uniform1i", "Uniform1iv",
+ "Uniform2f", "Uniform2fv", "Uniform2i", "Uniform2iv", "Uniform3f", "Uniform3fv", "Uniform3i",
+ "Uniform3iv", "Uniform4f", "Uniform4fv", "Uniform4i", "Uniform4iv", "UniformMatrix2fv",
+ "UniformMatrix3fv", "UniformMatrix4fv", "UseProgram", "VertexAttrib1f",
+ "VertexAttrib2fv", "VertexAttrib3fv", "VertexAttrib4fv", "VertexAttribPointer",
+ "Viewport",
+ ],
+ },
+ { // GL exclusive core functions
+ "GL": [{"ext": "<core>"}],
+ "GLES": null,
+
+ "functions": [
+ "DrawBuffer", "PolygonMode",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "GetStringi",
+ ]
+ },
+
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_vertex_array_object"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_vertex_array_object"},
+ {/* else if */ "ext": "OES_vertex_array_object"}],
+
+ // WebGL uses createVertexArray instead of genVertexArrays, but Emscripten
+ // creates an alias called genVertexArray which papers over this difference.
+ "functions": [
+ "BindVertexArray", "DeleteVertexArrays", "GenVertexArrays",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "GL_EXT_blend_func_extended"}],
+ "WebGL": null,
+
+ "functions": [
+ "BindFragDataLocation",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_blend_func_extended"}],
+ "GLES": [{"min_version": [3, 0], "ext": "GL_EXT_blend_func_extended"}],
+ "WebGL": null,
+
+ "functions": [
+ "BindFragDataLocationIndexed",
+ ],
+ },
+
+ {
+ "GL": [{"ext": "GL_KHR_blend_equation_advanced"},
+ {"ext": "GL_NV_blend_equation_advanced"}],
+ "GLES": [{"ext": "GL_KHR_blend_equation_advanced"},
+ {"ext": "GL_NV_blend_equation_advanced"}],
+ "WebGL": null,
+
+ "functions": [
+ "BlendBarrier",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [4, 4], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_clear_texture"}],
+ "GLES": [{"ext": "GL_EXT_clear_texture", "suffix": "EXT"}],
+ "WebGL": null,
+
+ "functions": [
+ "ClearTexImage", "ClearTexSubImage",
+ ],
+ // https://bugs.chromium.org/p/skia/issues/detail?id=8913
+ "optional": [
+ "ClearTexImage", "ClearTexSubImage",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [3, 1], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_draw_instanced"},
+ {/* else if */ "ext": "GL_EXT_draw_instanced"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_EXT_draw_instanced"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "DrawArraysInstanced", "DrawElementsInstanced",
+ ]
+ },
+ { // ES 3.0 has glDrawBuffers but not glDrawBuffer
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "DrawBuffers", "ReadBuffer",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [4, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_draw_indirect"}],
+ "GLES": [{"min_version": [3, 1], "ext": "<core>"}],
+ "WebGL": null,
+
+ "functions": [
+ "DrawArraysIndirect", "DrawElementsIndirect",
+ ]
+ },
+
+ { // glDrawRangeElements was added to ES in 3.0.
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "DrawRangeElements",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_texture_multisample"}],
+ "GLES": [{"min_version": [3, 1], "ext": "<core>"}],
+ "WebGL": null,
+
+ "functions": [
+ "GetMultisamplefv",
+ ]
+ },
+
+ // glGetTexLevelParameteriv was added to ES in 3.1.
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 1], "ext": "<core>"}],
+ "WebGL": null,
+
+ "functions": [
+ "GetTexLevelParameteriv",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_multi_draw_indirect"}],
+ "GLES": [{"ext": "GL_EXT_multi_draw_indirect"}],
+ "WebGL": null,
+
+ "functions": [
+ "MultiDrawArraysIndirect", "MultiDrawElementsIndirect",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [3, 1], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_texture_buffer"},
+ {/* else if */ "ext": "GL_EXT_texture_buffer"}],
+ "WebGL": null,
+
+ "functions": [
+ "TexBuffer",
+ ]
+ },
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_texture_buffer"},
+ {/* else if */ "ext": "GL_EXT_texture_buffer"}],
+ "WebGL": null,
+
+ "functions": [
+ "TexBufferRange",
+ ]
+ },
+
+ // GL_EXT_texture_storage is part of desktop 4.2
+ // There is a desktop ARB extension and an ES+desktop EXT extension
+ {
+ "GL": [{"min_version": [4, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_texture_storage"},
+ {/* else if */ "ext": "GL_EXT_texture_storage"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_EXT_texture_storage"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "TexStorage2D",
+ ]
+ },
+
+ // glTextureBarrier is part of desktop 4.5. There are also ARB and NV extensions.
+ {
+ "GL": [{"min_version": [4, 5], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_texture_barrier"},
+ {/* else if */ "ext": "GL_NV_texture_barrier"}],
+ "GLES": [{"ext": "GL_NV_texture_barrier"}],
+ "WebGL": null,
+
+ "functions": [
+ "TextureBarrier",
+ ]
+ },
+
+ {
+ "GL": null, // Not supported
+ "GLES": [{"ext": "GL_EXT_discard_framebuffer"}],
+ "WebGL": null,
+
+ "functions": [
+ "DiscardFramebuffer",
+ ]
+ },
+
+ {
+ "GL": null, // Not supported
+ "GLES": [{"ext": "GL_QCOM_tiled_rendering"}],
+ "WebGL": null,
+
+ "functions": [
+ "StartTiling", "EndTiling",
+ ]
+ },
+
+ {
+ "GL": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_instanced_arrays"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_EXT_instanced_arrays"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "VertexAttribDivisor",
+ ]
+ },
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "VertexAttribIPointer",
+ ]
+ },
+
+ // FrameBuffer Object (FBO) related calls
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_framebuffer_object"},
+ {/* else if */ "ext": "GL_EXT_framebuffer_object"}],
+ "GLES": [{"ext": "<core>"}], // These are all in ES 2.0 and above
+ "WebGL": [{"ext": "<core>"}],
+
+ "functions": [
+ "BindFramebuffer", "BindRenderbuffer", "CheckFramebufferStatus",
+ "DeleteFramebuffers", "DeleteRenderbuffers", "FramebufferRenderbuffer",
+ "FramebufferTexture2D", "GenFramebuffers", "GenRenderbuffers", "GenerateMipmap",
+ "GetFramebufferAttachmentParameteriv", "GetRenderbufferParameteriv",
+ "RenderbufferStorage",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_framebuffer_object"},
+ {/* else if */ "ext": "GL_EXT_framebuffer_blit"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_CHROMIUM_framebuffer_multisample"},
+ {/* else if */ "ext": "GL_ANGLE_framebuffer_blit"}],
+ // WebGL 2.0 might have support for blitFramebuffer and related functions.
+
+ "functions": [
+ "BlitFramebuffer",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_framebuffer_object"},
+ {/* else if */ "ext": "GL_EXT_framebuffer_multisample"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_CHROMIUM_framebuffer_multisample"},
+ {/* else if */ "ext": "GL_ANGLE_framebuffer_multisample"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "RenderbufferStorageMultisample",
+ ],
+ },
+
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_CHROMIUM_map_sub"}],
+ "WebGL": null,
+
+ "functions": [
+ "MapBufferSubData", "MapTexSubImage2D", "UnmapBufferSubData",
+ "UnmapTexSubImage2D"
+ ],
+ },
+
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_EXT_multisampled_render_to_texture"},
+ {"ext": "GL_IMG_multisampled_render_to_texture"}],
+ "WebGL": null,
+
+ "functions": [
+ "FramebufferTexture2DMultisample",
+ ],
+ },
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_EXT_multisampled_render_to_texture"}],
+ "WebGL": null,
+
+ "hardcode_functions" : [
+ {
+ "ptr_name": "fRenderbufferStorageMultisampleES2EXT",
+ "cast_name": "GrGLRenderbufferStorageMultisampleFn",
+ "get_name": "glRenderbufferStorageMultisampleEXT",
+ }
+ ]
+ },
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_IMG_multisampled_render_to_texture"}],
+ "WebGL": null,
+
+ "hardcode_functions" : [
+ {
+ "ptr_name": "fRenderbufferStorageMultisampleES2EXT",
+ "cast_name": "GrGLRenderbufferStorageMultisampleFn",
+ "get_name": "glRenderbufferStorageMultisampleIMG",
+ }
+ ]
+ },
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_APPLE_framebuffer_multisample"}],
+ "WebGL": null,
+
+ "functions" : ["ResolveMultisampleFramebuffer"],
+ "hardcode_functions" : [
+ {
+ "ptr_name": "fRenderbufferStorageMultisampleES2APPLE",
+ "cast_name": "GrGLRenderbufferStorageMultisampleFn",
+ "get_name": "glRenderbufferStorageMultisampleAPPLE",
+ }
+ ]
+ },
+
+ // There are several APIs for buffer mapping:
+ // ES2 + GL_OES_mapbuffer: MapBufferOES and UnmapBufferOES
+ // ES2 + GL_EXT_map_buffer_range: Adds MapBufferRangeEXT and FlushMappedBufferRangeEXT
+ // ES3: MapBufferRange, FlushMappedBufferRange, and UnmapBuffer are core (so no suffix).
+ //
+ // MapBuffer is not part of ES3, but implementations may still report the OES versions of
+ // MapBuffer and UnmapBuffer, per the older GL_OES_mapbuffer extension. Some implementations
+ // let us mix the newer MapBufferRange with the older UnmapBufferOES, but we've hit others that
+ // don't permit it. Note that in GrGLBuffer, we choose which API to use based on version and
+ // extensions. This code is written so that we never mix OES and non-OES functions.
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"ext": "GL_OES_mapbuffer"}],
+ "WebGL": null,
+
+ "functions": [
+ "MapBuffer",
+ ],
+ },
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_mapbuffer"}],
+ "WebGL": null, // explicitly removed https://www.khronos.org/registry/webgl/specs/2.0/#5.14
+
+ "functions": [
+ "UnmapBuffer",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_map_buffer_range"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_EXT_map_buffer_range"}],
+ "WebGL": null, // explicitly removed https://www.khronos.org/registry/webgl/specs/2.0/#5.14
+
+ "functions": [
+ // These functions are added to the 3.0 version of both GLES and GL.
+ "MapBufferRange", "FlushMappedBufferRange",
+ ],
+ },
+
+ {
+ "GL": [{"ext": "GL_EXT_debug_marker"}],
+ "GLES": [{"ext": "GL_EXT_debug_marker"}],
+ "WebGL": null,
+
+ "functions": [
+ "InsertEventMarker", "PushGroupMarker", "PopGroupMarker"
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_program_interface_query"}],
+ "GLES": [{"min_version": [3, 1], "ext": "<core>"}],
+ "WebGL": null,
+
+ "functions": [
+ "GetProgramResourceLocation",
+ ],
+ },
+
+ { // It appears that the GL_NV_path_rendering sometimes provides these
+ // functions under the "EXT" extension instead of "NV".
+ "GL": [{"ext": "GL_NV_path_rendering", "suffix": "EXT"}],
+
+ "GLES": [{"ext": "GL_CHROMIUM_path_rendering"},
+ {"ext": "GL_NV_path_rendering", "suffix": "EXT"}],
+ "WebGL": null,
+
+ "functions": [
+ "MatrixLoadIdentity", "MatrixLoadf"
+ ],
+ },
+ {
+ "GL": [{"ext": "GL_NV_path_rendering"}],
+ "GLES": [{"ext": "GL_CHROMIUM_path_rendering"},
+ {"ext": "GL_NV_path_rendering"}],
+ "WebGL": null,
+
+ "functions": [
+ "CoverFillPath", "CoverFillPathInstanced", "CoverStrokePath",
+ "CoverStrokePathInstanced", "DeletePaths", "GenPaths",
+ "IsPath", "PathCommands", "PathParameterf", "PathParameteri",
+ "PathStencilFunc", "ProgramPathFragmentInputGen", "StencilFillPath",
+ "StencilFillPathInstanced", "StencilStrokePath", "StencilStrokePathInstanced",
+ "StencilThenCoverFillPath", "StencilThenCoverFillPathInstanced",
+ "StencilThenCoverStrokePath", "StencilThenCoverStrokePathInstanced",
+ ],
+ // List of functions that Skia uses, but which have been added since the initial release
+ // of NV_path_rendering driver. We do not want to fail interface validation due to
+ // missing features, we will just not use the extension.
+ // If one updates this list, then update GrGLCaps::hasPathRenderingSupport too.
+ "optional": [
+ "ProgramPathFragmentInputGen", "StencilThenCoverFillPath",
+ "StencilThenCoverFillPathInstanced", "StencilThenCoverStrokePath",
+ "StencilThenCoverStrokePathInstanced",
+ ],
+ },
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_CHROMIUM_path_rendering"}],
+ "WebGL": null,
+
+ "functions": [
+ "BindFragmentInputLocation",
+ ],
+ },
+ {
+ "GL": [{"ext": "GL_NV_framebuffer_mixed_samples"}],
+ "GLES": [{"ext": "GL_CHROMIUM_framebuffer_mixed_samples"},
+ {"ext": "GL_NV_framebuffer_mixed_samples"}],
+ "WebGL": null,
+
+ "functions": [
+ "CoverageModulation",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_KHR_debug", "suffix": ""}],
+ "GLES": [{"ext": "GL_KHR_debug"}],
+ "WebGL": null,
+
+ // In OpenGL (but not ES), KHR_debug defines these methods to have no suffix.
+ "functions": [
+ "DebugMessageControl", "DebugMessageInsert", "DebugMessageCallback",
+ "GetDebugMessageLog", "PushDebugGroup", "PopDebugGroup", "ObjectLabel",
+ ],
+ },
+
+ {
+ "GL": null,
+ "GLES": [{"ext": "GL_CHROMIUM_bind_uniform_location"}],
+ "WebGL": null,
+
+ "functions": [
+ "BindUniformLocation",
+ ],
+ },
+
+ {
+ "GL": [{"ext": "GL_EXT_window_rectangles"}],
+ "GLES": [{"ext": "GL_EXT_window_rectangles"}],
+ "WebGL": null,
+
+ "functions": [
+ "WindowRectangles",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_sync"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_APPLE_sync"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "ClientWaitSync", "DeleteSync", "FenceSync",
+ "IsSync", "WaitSync"
+ ],
+ },
+
+ { // getInternalformativ was added in GL 4.2, ES 3.0, and with
+ // extension ARB_internalformat_query
+ "GL": [{"min_version": [4, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_internalformat_query"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": null,
+
+ "functions": [
+ "GetInternalformativ"
+ ],
+ },
+
+ // GetProgramBinary and ProgramBinary are available with an ES2 extension...
+ {
+ "GL": [{"min_version": [4, 1], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_OES_get_program_binary"}],
+ "WebGL": null, // explicitly not supported in WebGL 2.0
+
+ "functions": [
+ "GetProgramBinary", "ProgramBinary",
+ ],
+ },
+
+ // ... but the related ProgramParameteri is only in ES3
+ {
+ "GL": [{"min_version": [4, 1], "ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": null, // explicitly not supported in WebGL 2.0
+
+ "functions": [
+ "ProgramParameteri",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [3, 2], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_sampler_objects"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "BindSampler", "DeleteSamplers", "GenSamplers",
+ "SamplerParameteri", "SamplerParameteriv",
+ ],
+ },
+
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": null, // not in ES
+ "WebGL": null,
+
+ "functions": [
+ "GetQueryObjectiv",
+ ],
+ },
+ {
+ "GL": [{"ext": "<core>"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"},
+ {/* else if */ "ext": "GL_EXT_occlusion_query_boolean"}],
+ "WebGL": null,
+
+ // We only use these in our test tools
+ "test_functions": [
+ "GenQueries", "DeleteQueries", "BeginQuery", "EndQuery",
+ "GetQueryObjectuiv", "GetQueryiv",
+ ]
+ },
+ {
+ "GL": [{"min_version": [3, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_timer_query"},
+ {/* else if */ "ext": "GL_EXT_timer_query"}],
+ "GLES": null,
+ "WebGL": null,
+
+ "functions": [
+ "GetQueryObjecti64v", "GetQueryObjectui64v",
+ ],
+ },
+ {
+ "GL": [{"min_version": [3, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_timer_query"}],
+ "GLES": null,
+ "WebGL": null,
+
+ "functions": [
+ "QueryCounter",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_invalidate_subdata"}],
+ "GLES": null,
+ "WebGL": null,
+
+ "functions": [
+ "InvalidateBufferData", "InvalidateBufferSubData", "InvalidateTexImage",
+ "InvalidateTexSubImage",
+ ],
+ },
+ { // ES 3.0 adds the framebuffer functions but not the others.
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_invalidate_subdata"}],
+ "GLES": [{"min_version": [3, 0], "ext": "<core>"}],
+ "WebGL": [{"min_version": [2, 0], "ext": "<core>"}],
+
+ "functions": [
+ "InvalidateFramebuffer", "InvalidateSubFramebuffer",
+ ],
+ },
+
+ {
+ "GL": [{"min_version": [4, 3], "ext": "<core>"},
+ {/* else if */ "ext": "GL_ARB_ES2_compatibility"}],
+ "GLES": [{"ext": "<core>"}],
+ "WebGL": [{"ext": "<core>"}],
+
+ "functions": [
+ "GetShaderPrecisionFormat",
+ ],
+ },
+
+]
diff --git a/src/third_party/skia/tools/gpu/gl/interface/templates.go b/src/third_party/skia/tools/gpu/gl/interface/templates.go
new file mode 100644
index 0000000..650e855
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/gl/interface/templates.go
@@ -0,0 +1,268 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package main
+
+const ASSEMBLE_INTERFACE_GL_ES = `/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * THIS FILE IS AUTOGENERATED
+ * Make edits to tools/gpu/gl/interface/templates.go or they will
+ * be overwritten.
+ */
+
+#include "include/gpu/gl/GrGLAssembleHelpers.h"
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "src/gpu/gl/GrGLUtil.h"
+
+#define GET_PROC(F) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+#define GET_PROC_SUFFIX(F, S) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F #S)
+#define GET_PROC_LOCAL(F) GrGL##F##Fn* F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+
+#define GET_EGL_PROC_SUFFIX(F, S) functions->fEGL##F = (GrEGL##F##Fn*)get(ctx, "egl" #F #S)
+
+#if SK_DISABLE_GL_ES_INTERFACE
+sk_sp<const GrGLInterface> GrGLMakeAssembledGLESInterface(void *ctx, GrGLGetProc get) {
+ return nullptr;
+}
+#else
+sk_sp<const GrGLInterface> GrGLMakeAssembledGLESInterface(void *ctx, GrGLGetProc get) {
+ GET_PROC_LOCAL(GetString);
+ if (nullptr == GetString) {
+ return nullptr;
+ }
+
+ const char* verStr = reinterpret_cast<const char*>(GetString(GR_GL_VERSION));
+ GrGLVersion glVer = GrGLGetVersionFromString(verStr);
+
+ if (glVer < GR_GL_VER(2,0)) {
+ return nullptr;
+ }
+
+ GET_PROC_LOCAL(GetIntegerv);
+ GET_PROC_LOCAL(GetStringi);
+ GrEGLQueryStringFn* queryString;
+ GrEGLDisplay display;
+ GrGetEGLQueryAndDisplay(&queryString, &display, ctx, get);
+ GrGLExtensions extensions;
+ if (!extensions.init(kGLES_GrGLStandard, GetString, GetStringi, GetIntegerv, queryString,
+ display)) {
+ return nullptr;
+ }
+
+ sk_sp<GrGLInterface> interface(new GrGLInterface);
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+
+ // Autogenerated content follows
+[[content]]
+ // End autogenerated content
+ // TODO(kjlubick): Do we want a feature that removes the extension if it doesn't have
+ // the function? This is common on some low-end GPUs.
+
+ if (extensions.has("GL_KHR_debug")) {
+ // In general we have a policy against removing extension strings when the driver does
+ // not provide function pointers for an advertised extension. However, because there is a
+ // known device that advertises GL_KHR_debug but fails to provide the functions and this is
+ // a debugging- only extension we've made an exception. This also can happen when using
+ // APITRACE.
+ if (!interface->fFunctions.fDebugMessageControl) {
+ extensions.remove("GL_KHR_debug");
+ }
+ }
+ interface->fStandard = kGLES_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
+
+ return interface;
+}
+#endif
+`
+
+const ASSEMBLE_INTERFACE_GL = `/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * THIS FILE IS AUTOGENERATED
+ * Make edits to tools/gpu/gl/interface/templates.go or they will
+ * be overwritten.
+ */
+
+#include "include/gpu/gl/GrGLAssembleHelpers.h"
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "src/gpu/gl/GrGLUtil.h"
+
+#define GET_PROC(F) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+#define GET_PROC_SUFFIX(F, S) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F #S)
+#define GET_PROC_LOCAL(F) GrGL##F##Fn* F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+
+#define GET_EGL_PROC_SUFFIX(F, S) functions->fEGL##F = (GrEGL##F##Fn*)get(ctx, "egl" #F #S)
+
+#if SK_DISABLE_GL_INTERFACE
+sk_sp<const GrGLInterface> GrGLMakeAssembledGLInterface(void *ctx, GrGLGetProc get) {
+ return nullptr;
+}
+#else
+sk_sp<const GrGLInterface> GrGLMakeAssembledGLInterface(void *ctx, GrGLGetProc get) {
+ GET_PROC_LOCAL(GetString);
+ GET_PROC_LOCAL(GetStringi);
+ GET_PROC_LOCAL(GetIntegerv);
+
+ // GetStringi may be nullptr depending on the GL version.
+ if (nullptr == GetString || nullptr == GetIntegerv) {
+ return nullptr;
+ }
+
+ const char* versionString = (const char*) GetString(GR_GL_VERSION);
+ GrGLVersion glVer = GrGLGetVersionFromString(versionString);
+
+ if (glVer < GR_GL_VER(2,0) || GR_GL_INVALID_VER == glVer) {
+ // This is our minimum for non-ES GL.
+ return nullptr;
+ }
+
+ GrEGLQueryStringFn* queryString;
+ GrEGLDisplay display;
+ GrGetEGLQueryAndDisplay(&queryString, &display, ctx, get);
+ GrGLExtensions extensions;
+ if (!extensions.init(kGL_GrGLStandard, GetString, GetStringi, GetIntegerv, queryString,
+ display)) {
+ return nullptr;
+ }
+
+ sk_sp<GrGLInterface> interface(new GrGLInterface());
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+
+ // Autogenerated content follows
+[[content]]
+ // End autogenerated content
+ interface->fStandard = kGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
+
+ return interface;
+}
+#endif
+`
+
+const ASSEMBLE_INTERFACE_WEBGL = `/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * THIS FILE IS AUTOGENERATED
+ * Make edits to tools/gpu/gl/interface/templates.go or they will
+ * be overwritten.
+ */
+
+#include "include/gpu/gl/GrGLAssembleHelpers.h"
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "src/gpu/gl/GrGLUtil.h"
+
+#define GET_PROC(F) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+#define GET_PROC_SUFFIX(F, S) functions->f##F = (GrGL##F##Fn*)get(ctx, "gl" #F #S)
+#define GET_PROC_LOCAL(F) GrGL##F##Fn* F = (GrGL##F##Fn*)get(ctx, "gl" #F)
+
+#define GET_EGL_PROC_SUFFIX(F, S) functions->fEGL##F = (GrEGL##F##Fn*)get(ctx, "egl" #F #S)
+
+#if SK_DISABLE_WEBGL_INTERFACE
+sk_sp<const GrGLInterface> GrGLMakeAssembledWebGLInterface(void *ctx, GrGLGetProc get) {
+ return nullptr;
+}
+#else
+sk_sp<const GrGLInterface> GrGLMakeAssembledWebGLInterface(void *ctx, GrGLGetProc get) {
+ GET_PROC_LOCAL(GetString);
+ if (nullptr == GetString) {
+ return nullptr;
+ }
+
+ const char* verStr = reinterpret_cast<const char*>(GetString(GR_GL_VERSION));
+ GrGLVersion glVer = GrGLGetVersionFromString(verStr);
+
+ if (glVer < GR_GL_VER(1,0)) {
+ return nullptr;
+ }
+
+ GET_PROC_LOCAL(GetIntegerv);
+ GET_PROC_LOCAL(GetStringi);
+ GrEGLQueryStringFn* queryString;
+ GrEGLDisplay display;
+ GrGetEGLQueryAndDisplay(&queryString, &display, ctx, get);
+ GrGLExtensions extensions;
+ if (!extensions.init(kWebGL_GrGLStandard, GetString, GetStringi, GetIntegerv, queryString,
+ display)) {
+ return nullptr;
+ }
+
+ sk_sp<GrGLInterface> interface(new GrGLInterface);
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+
+ // Autogenerated content follows
+[[content]]
+ // End autogenerated content
+
+ interface->fStandard = kWebGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
+
+ return interface;
+}
+#endif
+`
+
+const VALIDATE_INTERFACE = `/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * THIS FILE IS AUTOGENERATED
+ * Make edits to tools/gpu/gl/interface/templates.go or they will
+ * be overwritten.
+ */
+
+#include "include/gpu/gl/GrGLExtensions.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "src/gpu/gl/GrGLUtil.h"
+
+#include <stdio.h>
+
+GrGLInterface::GrGLInterface() {
+ fStandard = kNone_GrGLStandard;
+}
+
+#define RETURN_FALSE_INTERFACE \
+ SkDEBUGF("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); \
+ return false
+
+bool GrGLInterface::validate() const {
+
+ if (kNone_GrGLStandard == fStandard) {
+ RETURN_FALSE_INTERFACE;
+ }
+
+ if (!fExtensions.isInitialized()) {
+ RETURN_FALSE_INTERFACE;
+ }
+
+ GrGLVersion glVer = GrGLGetVersion(this);
+ if (GR_GL_INVALID_VER == glVer) {
+ RETURN_FALSE_INTERFACE;
+ }
+ // Autogenerated content follows
+[[content]]
+ // End autogenerated content
+ return true;
+}
+
+#if GR_TEST_UTILS
+
+void GrGLInterface::abandon() const {
+ const_cast<GrGLInterface*>(this)->fFunctions = GrGLInterface::Functions();
+}
+
+#endif // GR_TEST_UTILS
+`
diff --git a/src/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp b/src/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
index 8ce687d..c27fe24 100644
--- a/src/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
+++ b/src/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
@@ -5,15 +5,21 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
#include "AvailabilityMacros.h"
#include <OpenGL/OpenGL.h>
#include <dlfcn.h>
namespace {
+
+std::function<void()> context_restorer() {
+ auto context = CGLGetCurrentContext();
+ return [context] { CGLSetCurrentContext(context); };
+}
+
class MacGLTestContext : public sk_gpu_test::GLTestContext {
public:
MacGLTestContext(MacGLTestContext* shareContext);
@@ -23,6 +29,7 @@
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -58,10 +65,11 @@
return;
}
+ SkScopeExit restorer(context_restorer());
CGLSetCurrentContext(fContext);
- sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
- if (nullptr == gl.get()) {
+ auto gl = GrGLMakeNativeInterface();
+ if (!gl) {
SkDebugf("Context could not create GL interface.\n");
this->destroyGLContext();
return;
@@ -76,7 +84,7 @@
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
RTLD_LAZY);
- this->init(gl.release());
+ this->init(std::move(gl));
}
MacGLTestContext::~MacGLTestContext() {
@@ -86,10 +94,14 @@
void MacGLTestContext::destroyGLContext() {
if (fContext) {
+ if (CGLGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ CGLSetCurrentContext(nullptr);
+ }
CGLReleaseContext(fContext);
fContext = nullptr;
}
- if (RTLD_DEFAULT != fGLLibrary) {
+ if (nullptr != fGLLibrary) {
dlclose(fGLLibrary);
}
}
@@ -98,12 +110,20 @@
CGLSetCurrentContext(fContext);
}
+std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (CGLGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void MacGLTestContext::onPlatformSwapBuffers() const {
CGLFlushDrawable(fContext);
}
GrGLFuncPtr MacGLTestContext::onPlatformGetProcAddress(const char* procName) const {
- return reinterpret_cast<GrGLFuncPtr>(dlsym(fGLLibrary, procName));
+ void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
+ return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
}
} // anonymous namespace
diff --git a/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp b/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
deleted file mode 100644
index 5d0014b..0000000
--- a/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <GL/osmesa.h>
-
-#include "gl/mesa/GLTestContext_mesa.h"
-#include "gl/GrGLDefines.h"
-
-#include "gl/GrGLAssembleInterface.h"
-#include "gl/GrGLUtil.h"
-#include "osmesa_wrapper.h"
-
-namespace {
-
-static GrGLFuncPtr osmesa_get(void* ctx, const char name[]) {
- SkASSERT(nullptr == ctx);
- SkASSERT(OSMesaGetCurrentContext());
- return OSMesaGetProcAddress(name);
-}
-
-static const GrGLInterface* create_mesa_interface() {
- if (nullptr == OSMesaGetCurrentContext()) {
- return nullptr;
- }
- return GrGLAssembleInterface(nullptr, osmesa_get);
-}
-
-static const GrGLint gBOGUS_SIZE = 16;
-
-class MesaGLContext : public sk_gpu_test::GLTestContext {
-private:
- typedef intptr_t Context;
-
-public:
- MesaGLContext(MesaGLContext* shareContext);
- ~MesaGLContext() override;
-
-private:
- void destroyGLContext();
-
- void onPlatformMakeCurrent() const override;
-
- void onPlatformSwapBuffers() const override;
-
- GrGLFuncPtr onPlatformGetProcAddress(const char *) const override;
-
- Context fContext;
- GrGLubyte *fImage;
-};
-
-MesaGLContext::MesaGLContext(MesaGLContext* shareContext)
- : fContext(static_cast<Context>(0))
- , fImage(nullptr) {
- GR_STATIC_ASSERT(sizeof(Context) == sizeof(OSMesaContext));
- OSMesaContext mesaShareContext = shareContext ? (OSMesaContext)(shareContext->fContext)
- : nullptr;
-
- /* Create an RGBA-mode context */
-#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
- /* specify Z, stencil, accum sizes */
- fContext = (Context)OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, mesaShareContext);
-#else
- fContext = (Context) OSMesaCreateContext(OSMESA_BGRA, mesaShareContext);
-#endif
- if (!fContext) {
- SkDebugf("OSMesaCreateContext failed!\n");
- this->destroyGLContext();
- return;
- }
- // Allocate the image buffer
- fImage = (GrGLubyte *) sk_malloc_throw(gBOGUS_SIZE * gBOGUS_SIZE *
- 4 * sizeof(GrGLubyte));
- if (!fImage) {
- SkDebugf("Alloc image buffer failed!\n");
- this->destroyGLContext();
- return;
- }
-
- // Bind the buffer to the context and make it current
- if (!OSMesaMakeCurrent((OSMesaContext) fContext,
- fImage,
- GR_GL_UNSIGNED_BYTE,
- gBOGUS_SIZE,
- gBOGUS_SIZE)) {
- SkDebugf("OSMesaMakeCurrent failed!\n");
- this->destroyGLContext();
- return;
- }
-
- sk_sp<const GrGLInterface> gl(create_mesa_interface());
- if (nullptr == gl.get()) {
- SkDebugf("Could not create GL interface!\n");
- this->destroyGLContext();
- return;
- }
-
- if (!gl->validate()) {
- SkDebugf("Could not validate GL interface!\n");
- this->destroyGLContext();
- return;
- }
-
- this->init(gl.release());
-}
-
-MesaGLContext::~MesaGLContext() {
- this->teardown();
- this->destroyGLContext();
-}
-
-void MesaGLContext::destroyGLContext() {
- if (fImage) {
- sk_free(fImage);
- fImage = nullptr;
- }
-
- if (fContext) {
- OSMesaDestroyContext((OSMesaContext) fContext);
- fContext = static_cast<Context>(0);
- }
-}
-
-
-void MesaGLContext::onPlatformMakeCurrent() const {
- if (fContext) {
- if (!OSMesaMakeCurrent((OSMesaContext) fContext, fImage,
- GR_GL_UNSIGNED_BYTE, gBOGUS_SIZE, gBOGUS_SIZE)) {
- SkDebugf("Could not make MESA context current.");
- }
- }
-}
-
-void MesaGLContext::onPlatformSwapBuffers() const { }
-
-GrGLFuncPtr MesaGLContext::onPlatformGetProcAddress(const char *procName) const {
- return OSMesaGetProcAddress(procName);
-}
-} // anonymous namespace
-
-
-namespace sk_gpu_test {
-GLTestContext *CreateMesaGLTestContext(GLTestContext* shareContext) {
- MesaGLContext* mesaShareContext = reinterpret_cast<MesaGLContext*>(shareContext);
- MesaGLContext *ctx = new MesaGLContext(mesaShareContext);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-} // sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h b/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h
deleted file mode 100644
index 40184aa..0000000
--- a/src/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLTestContext_mesa_DEFINED
-#define GLTestContext_mesa_DEFINED
-
-#include "gl/GLTestContext.h"
-
-namespace sk_gpu_test {
-GLTestContext* CreateMesaGLTestContext(GLTestContext* shareContext);
-} // namespace sk_gpu_test
-
-#endif
diff --git a/src/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h b/src/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h
deleted file mode 100644
index 70de993..0000000
--- a/src/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Older versions of XQuartz have a bug where a header included by osmesa.h
-// defines GL_GLEXT_PROTOTYPES. This will cause a redefinition warning if
-// the file that includes osmesa.h already defined it. XCode 3 uses a version
-// of gcc (4.2.1) that does not support the diagnostic pragma to disable a
-// warning (added in 4.2.4). So we use the system_header pragma to shut GCC
-// up about warnings in osmesa.h
-#pragma GCC system_header
-#include <GL/osmesa.h>
diff --git a/src/third_party/skia/tools/gpu/gl/none/CreatePlatformGLTestContext_none.cpp b/src/third_party/skia/tools/gpu/gl/none/CreatePlatformGLTestContext_none.cpp
index 25343b0..de2f935 100644
--- a/src/third_party/skia/tools/gpu/gl/none/CreatePlatformGLTestContext_none.cpp
+++ b/src/third_party/skia/tools/gpu/gl/none/CreatePlatformGLTestContext_none.cpp
@@ -6,7 +6,7 @@
* found in the LICENSE file.
*/
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
namespace sk_gpu_test {
GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
diff --git a/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp b/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp
deleted file mode 100644
index 894de07..0000000
--- a/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "NullGLTestContext.h"
-#include "gl/GrGLTestInterface.h"
-#include "gl/GrGLDefines.h"
-#include "gl/GrGLInterface.h"
-#include "gl/GrGLTypes.h"
-#include "SkMutex.h"
-#include "SkTDArray.h"
-
-namespace {
-class NullGLContext : public sk_gpu_test::GLTestContext {
-public:
- NullGLContext(bool enableNVPR) { this->init(GrGLCreateNullInterface(enableNVPR)); }
- ~NullGLContext() override { this->teardown(); }
-
-private:
- void onPlatformMakeCurrent() const override {}
- void onPlatformSwapBuffers() const override {}
- GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
-};
-
-} // anonymous namespace
-
-namespace sk_gpu_test {
-GLTestContext* CreateNullGLTestContext(bool enableNVPR, GLTestContext* shareContext) {
- if (shareContext) {
- return nullptr;
- }
- GLTestContext* ctx = new NullGLContext(enableNVPR);
- if (ctx->isValid()) {
- return ctx;
- }
- delete ctx;
- return nullptr;
-}
-} // namespace sk_gpu_test
-
diff --git a/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.h b/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.h
deleted file mode 100644
index 9062e88..0000000
--- a/src/third_party/skia/tools/gpu/gl/null/NullGLTestContext.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef NullGLContext_DEFINED
-#define NullGLContext_DEFINED
-
-#include "gl/GLTestContext.h"
-
-namespace sk_gpu_test {
-GLTestContext* CreateNullGLTestContext(bool enableNVPR, GLTestContext* shareContext);
-} // namespace sk_gpu_test
-
-#endif
diff --git a/src/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp b/src/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
index 49d7743..7159c13 100644
--- a/src/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
+++ b/src/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
@@ -6,16 +6,32 @@
* found in the LICENSE file.
*/
-#include "gl/GLTestContext.h"
+#include "tools/gpu/gl/GLTestContext.h"
+
+#if defined(_M_ARM64)
+
+namespace sk_gpu_test {
+
+GLTestContext* CreatePlatformGLTestContext(GrGLStandard, GLTestContext*) { return nullptr; }
+
+} // namespace sk_gpu_test
+
+#else
#include <windows.h>
#include <GL/GL.h>
-#include "win/SkWGL.h"
+#include "src/utils/win/SkWGL.h"
#include <windows.h>
namespace {
+std::function<void()> context_restorer() {
+ auto glrc = wglGetCurrentContext();
+ auto dc = wglGetCurrentDC();
+ return [glrc, dc] { wglMakeCurrent(dc, glrc); };
+}
+
class WinGLTestContext : public sk_gpu_test::GLTestContext {
public:
WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
@@ -25,6 +41,7 @@
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
@@ -32,7 +49,7 @@
HDC fDeviceContext;
HGLRC fGlRenderContext;
static ATOM gWC;
- SkWGLPbufferContext* fPbufferContext;
+ sk_sp<SkWGLPbufferContext> fPbufferContext;
};
ATOM WinGLTestContext::gWC = 0;
@@ -90,7 +107,7 @@
winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC()
: shareContext->fGlRenderContext;
}
- fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType, winShareContext);
+ fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, contextType, winShareContext);
HDC dc;
HGLRC glrc;
@@ -113,14 +130,15 @@
glrc = fPbufferContext->getGLRC();
}
+ SkScopeExit restorer(context_restorer());
if (!(wglMakeCurrent(dc, glrc))) {
SkDebugf("Could not set the context.\n");
this->destroyGLContext();
return;
}
- sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
- if (nullptr == gl.get()) {
+ auto gl = GrGLMakeNativeInterface();
+ if (!gl) {
SkDebugf("Could not create GL interface.\n");
this->destroyGLContext();
return;
@@ -131,7 +149,7 @@
return;
}
- this->init(gl.release());
+ this->init(std::move(gl));
}
WinGLTestContext::~WinGLTestContext() {
@@ -140,8 +158,9 @@
}
void WinGLTestContext::destroyGLContext() {
- SkSafeSetNull(fPbufferContext);
+ fPbufferContext = nullptr;
if (fGlRenderContext) {
+ // This deletes the context immediately even if it is current.
wglDeleteContext(fGlRenderContext);
fGlRenderContext = 0;
}
@@ -172,6 +191,13 @@
}
}
+std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (wglGetCurrentContext() == fGlRenderContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void WinGLTestContext::onPlatformSwapBuffers() const {
HDC dc;
@@ -204,3 +230,4 @@
}
} // namespace sk_gpu_test
+#endif
diff --git a/src/third_party/skia/tools/gpu/mock/MockTestContext.cpp b/src/third_party/skia/tools/gpu/mock/MockTestContext.cpp
index 56cd68c..f892714 100644
--- a/src/third_party/skia/tools/gpu/mock/MockTestContext.cpp
+++ b/src/third_party/skia/tools/gpu/mock/MockTestContext.cpp
@@ -8,7 +8,9 @@
#ifndef GLTestContext_DEFINED
#define GLTestContext_DEFINED
-#include "MockTestContext.h"
+#include "tools/gpu/mock/MockTestContext.h"
+
+#include "include/gpu/GrContext.h"
namespace {
@@ -17,17 +19,20 @@
MockTestContext() {}
~MockTestContext() override {}
- virtual GrBackend backend() override { return kMock_GrBackend; }
- virtual GrBackendContext backendContext() override {
- return reinterpret_cast<GrBackendContext>(nullptr);
- }
+ virtual GrBackendApi backend() override { return GrBackendApi::kMock; }
+
void testAbandon() override {}
void submit() override {}
void finish() override {}
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
+ return GrContext::MakeMock(nullptr, options);
+ }
+
protected:
void teardown() override {}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
private:
diff --git a/src/third_party/skia/tools/gpu/mock/MockTestContext.h b/src/third_party/skia/tools/gpu/mock/MockTestContext.h
index 4aac248..aae7fad 100644
--- a/src/third_party/skia/tools/gpu/mock/MockTestContext.h
+++ b/src/third_party/skia/tools/gpu/mock/MockTestContext.h
@@ -8,12 +8,12 @@
#ifndef MockTestContext_DEFINED
#define MockTestContext_DEFINED
-#include "TestContext.h"
+#include "tools/gpu/TestContext.h"
namespace sk_gpu_test {
/**
- * Creates mock context object for use with GrContexts created with kMock_GrBackend. It will
+ * Creates mock context object for use with GrContexts created with GrBackendApi::kMock. It will
* trivially succeed at everything.
*/
TestContext* CreateMockTestContext(TestContext* shareContext = nullptr);
diff --git a/src/third_party/skia/tools/gpu/mtl/MtlTestContext.h b/src/third_party/skia/tools/gpu/mtl/MtlTestContext.h
index f703238..dbda09d 100644
--- a/src/third_party/skia/tools/gpu/mtl/MtlTestContext.h
+++ b/src/third_party/skia/tools/gpu/mtl/MtlTestContext.h
@@ -8,15 +8,29 @@
#ifndef MtlTestContext_h
#define MtlTestContext_h
-#include "TestContext.h"
+#include "tools/gpu/TestContext.h"
#ifdef SK_METAL
namespace sk_gpu_test {
-TestContext* CreatePlatformMtlTestContext(TestContext*);
+class MtlTestContext : public TestContext {
+public:
+ GrBackendApi backend() override { return GrBackendApi::kMetal; }
+
+protected:
+ MtlTestContext() {}
+
+private:
+ typedef TestContext INHERITED;
+};
+
+/**
+ * Creates Metal context object bound to the native Metal library.
+ */
+MtlTestContext* CreatePlatformMtlTestContext(MtlTestContext*);
+
} // namespace sk_gpu_test
#endif
-
#endif /* MtlTestContext_h */
diff --git a/src/third_party/skia/tools/gpu/mtl/MtlTestContext.mm b/src/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
index 4014e2b..367051f 100644
--- a/src/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
+++ b/src/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
@@ -5,160 +5,127 @@
* found in the LICENSE file.
*/
-#include "MtlTestContext.h"
+#include "tools/gpu/mtl/MtlTestContext.h"
-#include "GrContext.h"
-#include "GrContextOptions.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/GrContextOptions.h"
-#import <Metal/Metal.h>
+#include "src/gpu/mtl/GrMtlUtil.h"
#ifdef SK_METAL
+#import <Metal/Metal.h>
+
namespace {
/**
* Implements sk_gpu_test::FenceSync for Metal.
+ *
+ * Fences as MTLSharedEvents are not supported across all Metal platforms, so we do
+ * the next best thing and submit an empty MTLCommandBuffer and track when it's complete.
*/
-
-// TODO
-#if 0
class MtlFenceSync : public sk_gpu_test::FenceSync {
public:
- MtlFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue,
- uint32_t queueFamilyIndex)
- : fVk(std::move(vk))
- , fDevice(device)
- , fQueue(queue) {
+ MtlFenceSync(id<MTLCommandQueue> queue)
+ : fQueue(queue) {
SkDEBUGCODE(fUnfinishedSyncs = 0;)
- VkCommandPoolCreateInfo createInfo;
- createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- createInfo.pNext = nullptr;
- createInfo.flags = 0;
- createInfo.queueFamilyIndex = queueFamilyIndex;
- GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool));
-
- VkCommandBufferAllocateInfo allocateInfo;
- allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocateInfo.pNext = nullptr;
- allocateInfo.commandBufferCount = 1;
- allocateInfo.commandPool = fCommandPool;
- allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer));
-
- VkCommandBufferBeginInfo beginInfo;
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.pNext = nullptr;
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
- beginInfo.pInheritanceInfo = nullptr;
- GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo));
- GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer));
}
- ~VkFenceSync() override {
+ ~MtlFenceSync() override {
SkASSERT(!fUnfinishedSyncs);
- // If the above assertion is true then the command buffer should not be in flight.
- GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer));
- GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr));
}
sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
- VkFence fence;
- VkFenceCreateInfo info;
- info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- info.pNext = nullptr;
- info.flags = 0;
- GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence));
- VkSubmitInfo submitInfo;
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.pNext = nullptr;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitSemaphores = nullptr;
- submitInfo.pWaitDstStageMask = nullptr;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &fCommandBuffer;
- submitInfo.signalSemaphoreCount = 0;
- submitInfo.pSignalSemaphores = nullptr;
- GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence));
+ id<MTLCommandBuffer> cmdBuffer = [fQueue commandBuffer];
+ cmdBuffer.label = @"Fence";
+ [cmdBuffer commit];
+
SkDEBUGCODE(++fUnfinishedSyncs;)
- return (sk_gpu_test::PlatformFence)fence;
+
+ void* cfCmdBuffer = (__bridge_retained void*)cmdBuffer;
+ return (sk_gpu_test::PlatformFence)cfCmdBuffer;
}
bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
- VkFence fence = (VkFence)opaqueFence;
- static constexpr uint64_t kForever = ~((uint64_t)0);
- auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever));
- return result != VK_TIMEOUT;
+ void* cfCmdBuffer = (void*) opaqueFence;
+ id<MTLCommandBuffer> cmdBuffer = (__bridge id<MTLCommandBuffer>) cfCmdBuffer;
+
+ [cmdBuffer waitUntilCompleted];
+
+ return (MTLCommandBufferStatusError != cmdBuffer.status);
}
void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
- VkFence fence = (VkFence)opaqueFence;
- GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr));
+ CFRelease((void*) opaqueFence);
SkDEBUGCODE(--fUnfinishedSyncs;)
}
private:
- sk_sp<const GrVkInterface> fVk;
- VkDevice fDevice;
- VkQueue fQueue;
- VkCommandPool fCommandPool;
- VkCommandBuffer fCommandBuffer;
+ id<MTLCommandQueue> fQueue;
SkDEBUGCODE(mutable int fUnfinishedSyncs;)
typedef sk_gpu_test::FenceSync INHERITED;
};
-GR_STATIC_ASSERT(sizeof(VkFence) <= sizeof(sk_gpu_test::PlatformFence));
-#endif
+GR_STATIC_ASSERT(sizeof(uint64_t) <= sizeof(sk_gpu_test::PlatformFence));
-class MtlTestContext : public sk_gpu_test::TestContext {
+class MtlTestContextImpl : public sk_gpu_test::MtlTestContext {
public:
- static MtlTestContext* Create(TestContext* sharedContext) {
- SkASSERT(!sharedContext);
- id<MTLDevice> device = MTLCreateSystemDefaultDevice();
- id<MTLCommandQueue> queue = [device newCommandQueue];
+ static MtlTestContext* Create(MtlTestContext* sharedContext) {
+ id<MTLDevice> device;
+ id<MTLCommandQueue> queue;
+ if (sharedContext) {
+ MtlTestContextImpl* sharedContextImpl = (MtlTestContextImpl*) sharedContext;
+ device = sharedContextImpl->device();
+ queue = sharedContextImpl->queue();
+ } else {
+ device = MTLCreateSystemDefaultDevice();
+ queue = [device newCommandQueue];
+ }
- return new MtlTestContext(device, queue);
+ return new MtlTestContextImpl(device, queue);
}
- ~MtlTestContext() override { this->teardown(); }
-
- GrBackend backend() override { return kMetal_GrBackend; }
-
- GrBackendContext backendContext() override { return 0; }
+ ~MtlTestContextImpl() override { this->teardown(); }
void testAbandon() override {}
- // There is really nothing to here since we don't own any unqueued command buffers here.
+ // There is really nothing to do here since we don't own any unqueued command buffers here.
void submit() override {}
void finish() override {}
sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
- return GrContext::MakeMetal((__bridge_retained void*)fDevice,
- (__bridge_retained void*)fQueue,
+ return GrContext::MakeMetal((__bridge void*)fDevice,
+ (__bridge void*)fQueue,
options);
}
+ id<MTLDevice> device() { return fDevice; }
+ id<MTLCommandQueue> queue() { return fQueue; }
+
private:
- MtlTestContext(id<MTLDevice> device, id<MTLCommandQueue> queue)
- : fDevice(device), fQueue(queue) {
- fFenceSync.reset(nullptr);
+ MtlTestContextImpl(id<MTLDevice> device, id<MTLCommandQueue> queue)
+ : INHERITED(), fDevice(device), fQueue(queue) {
+ fFenceSync.reset(new MtlFenceSync(queue));
}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
- id<MTLDevice> fDevice;
+ id<MTLDevice> fDevice;
id<MTLCommandQueue> fQueue;
- typedef sk_gpu_test::TestContext INHERITED;
+ typedef sk_gpu_test::MtlTestContext INHERITED;
};
} // anonymous namespace
namespace sk_gpu_test {
-TestContext* CreatePlatformMtlTestContext(TestContext* sharedContext) {
- return MtlTestContext::Create(sharedContext);
+MtlTestContext* CreatePlatformMtlTestContext(MtlTestContext* sharedContext) {
+ return MtlTestContextImpl::Create(sharedContext);
}
+
} // namespace sk_gpu_test
diff --git a/src/third_party/skia/tools/gpu/vk/GrVulkanDefines.h b/src/third_party/skia/tools/gpu/vk/GrVulkanDefines.h
new file mode 100644
index 0000000..ad65a84
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/vk/GrVulkanDefines.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrVulkanDefines_DEFINED
+#define GrVulkanDefines_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+# if !defined(VK_USE_PLATFORM_WIN32_KHR)
+# define VK_USE_PLATFORM_WIN32_KHR
+# endif
+#elif defined(SK_BUILD_FOR_ANDROID)
+# if !defined(VK_USE_PLATFORM_ANDROID_KHR)
+# define VK_USE_PLATFORM_ANDROID_KHR
+# endif
+#elif defined(SK_BUILD_FOR_UNIX)
+# if !defined(VK_USE_PLATFORM_XCB_KHR)
+# define VK_USE_PLATFORM_XCB_KHR
+# endif
+#elif defined(SK_BUILD_FOR_MAC)
+# if !defined(VK_USE_PLATFORM_MACOS_MVK)
+# define VK_USE_PLATFORM_MACOS_MVK
+# endif
+#elif defined(SK_BUILD_FOR_IOS)
+# if !defined(VK_USE_PLATFORM_IOS_MVK)
+# define VK_USE_PLATFORM_IOS_MVK
+# endif
+#endif
+
+// We create our own function table and never directly call any functions via vk*(). So no
+// need to include the prototype functions. We do them for molten vk however.
+#if !defined(SK_MOLTENVK) && !defined(VK_NO_PROTOTYPES)
+ #define VK_NO_PROTOTYPES
+#endif
+
+#include <vulkan/vulkan.h> // IWYU pragma: export
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/vk/VkTestContext.cpp b/src/third_party/skia/tools/gpu/vk/VkTestContext.cpp
index 125ead2..6215efe 100644
--- a/src/third_party/skia/tools/gpu/vk/VkTestContext.cpp
+++ b/src/third_party/skia/tools/gpu/vk/VkTestContext.cpp
@@ -5,15 +5,20 @@
* found in the LICENSE file.
*/
-#include "VkTestContext.h"
+#include "tools/gpu/vk/VkTestContext.h"
#ifdef SK_VULKAN
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
-#include <vulkan/vulkan.h>
+#include "include/gpu/GrContext.h"
+#include "include/gpu/vk/GrVkExtensions.h"
+#include "tools/gpu/vk/VkTestUtils.h"
namespace {
+
+#define ACQUIRE_VK_PROC(name, device) \
+ f##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, nullptr, device)); \
+ SkASSERT(f##name)
+
/**
* Implements sk_gpu_test::FenceSync for Vulkan. It creates a single command
* buffer with USAGE_SIMULTANEOUS with no content . On every insertFence request
@@ -21,18 +26,30 @@
*/
class VkFenceSync : public sk_gpu_test::FenceSync {
public:
- VkFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue,
+ VkFenceSync(GrVkGetProc getProc, VkDevice device, VkQueue queue,
uint32_t queueFamilyIndex)
- : fVk(std::move(vk))
- , fDevice(device)
+ : fDevice(device)
, fQueue(queue) {
+ ACQUIRE_VK_PROC(CreateCommandPool, device);
+ ACQUIRE_VK_PROC(DestroyCommandPool, device);
+ ACQUIRE_VK_PROC(AllocateCommandBuffers, device);
+ ACQUIRE_VK_PROC(FreeCommandBuffers, device);
+ ACQUIRE_VK_PROC(BeginCommandBuffer, device);
+ ACQUIRE_VK_PROC(EndCommandBuffer, device);
+ ACQUIRE_VK_PROC(CreateFence, device);
+ ACQUIRE_VK_PROC(DestroyFence, device);
+ ACQUIRE_VK_PROC(WaitForFences, device);
+ ACQUIRE_VK_PROC(QueueSubmit, device);
+
+ VkResult result;
SkDEBUGCODE(fUnfinishedSyncs = 0;)
VkCommandPoolCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.queueFamilyIndex = queueFamilyIndex;
- GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool));
+ result = fCreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool);
+ SkASSERT(VK_SUCCESS == result);
VkCommandBufferAllocateInfo allocateInfo;
allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@@ -40,31 +57,39 @@
allocateInfo.commandBufferCount = 1;
allocateInfo.commandPool = fCommandPool;
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer));
+ result = fAllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer);
+ SkASSERT(VK_SUCCESS == result);
VkCommandBufferBeginInfo beginInfo;
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.pNext = nullptr;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
beginInfo.pInheritanceInfo = nullptr;
- GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo));
- GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer));
+ result = fBeginCommandBuffer(fCommandBuffer, &beginInfo);
+ SkASSERT(VK_SUCCESS == result);
+ result = fEndCommandBuffer(fCommandBuffer);
+ SkASSERT(VK_SUCCESS == result);
+
}
~VkFenceSync() override {
SkASSERT(!fUnfinishedSyncs);
// If the above assertion is true then the command buffer should not be in flight.
- GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer));
- GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr));
+ fFreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer);
+ fDestroyCommandPool(fDevice, fCommandPool, nullptr);
}
sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
+ VkResult result;
+
VkFence fence;
VkFenceCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
- GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence));
+ result = fCreateFence(fDevice, &info, nullptr, &fence);
+ SkASSERT(VK_SUCCESS == result);
+
VkSubmitInfo submitInfo;
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
@@ -75,7 +100,9 @@
submitInfo.pCommandBuffers = &fCommandBuffer;
submitInfo.signalSemaphoreCount = 0;
submitInfo.pSignalSemaphores = nullptr;
- GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence));
+ result = fQueueSubmit(fQueue, 1, &submitInfo, fence);
+ SkASSERT(VK_SUCCESS == result);
+
SkDEBUGCODE(++fUnfinishedSyncs;)
return (sk_gpu_test::PlatformFence)fence;
}
@@ -83,22 +110,33 @@
bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
VkFence fence = (VkFence)opaqueFence;
static constexpr uint64_t kForever = ~((uint64_t)0);
- auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever));
+ auto result = fWaitForFences(fDevice, 1, &fence, true, kForever);
return result != VK_TIMEOUT;
}
void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
VkFence fence = (VkFence)opaqueFence;
- GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr));
+ fDestroyFence(fDevice, fence, nullptr);
SkDEBUGCODE(--fUnfinishedSyncs;)
}
private:
- sk_sp<const GrVkInterface> fVk;
VkDevice fDevice;
VkQueue fQueue;
VkCommandPool fCommandPool;
VkCommandBuffer fCommandBuffer;
+
+ PFN_vkCreateCommandPool fCreateCommandPool = nullptr;
+ PFN_vkDestroyCommandPool fDestroyCommandPool = nullptr;
+ PFN_vkAllocateCommandBuffers fAllocateCommandBuffers = nullptr;
+ PFN_vkFreeCommandBuffers fFreeCommandBuffers = nullptr;
+ PFN_vkBeginCommandBuffer fBeginCommandBuffer = nullptr;
+ PFN_vkEndCommandBuffer fEndCommandBuffer = nullptr;
+ PFN_vkCreateFence fCreateFence = nullptr;
+ PFN_vkDestroyFence fDestroyFence = nullptr;
+ PFN_vkWaitForFences fWaitForFences = nullptr;
+ PFN_vkQueueSubmit fQueueSubmit = nullptr;
+
SkDEBUGCODE(mutable int fUnfinishedSyncs;)
typedef sk_gpu_test::FenceSync INHERITED;
};
@@ -109,17 +147,49 @@
class VkTestContextImpl : public sk_gpu_test::VkTestContext {
public:
static VkTestContext* Create(VkTestContext* sharedContext) {
- sk_sp<const GrVkBackendContext> backendContext;
+ GrVkBackendContext backendContext;
+ GrVkExtensions* extensions;
+ VkPhysicalDeviceFeatures2* features;
+ bool ownsContext = true;
+ VkDebugReportCallbackEXT debugCallback = VK_NULL_HANDLE;
+ PFN_vkDestroyDebugReportCallbackEXT destroyCallback = nullptr;
if (sharedContext) {
backendContext = sharedContext->getVkBackendContext();
+ extensions = const_cast<GrVkExtensions*>(sharedContext->getVkExtensions());
+ features = const_cast<VkPhysicalDeviceFeatures2*>(sharedContext->getVkFeatures());
+ // We always delete the parent context last so make sure the child does not think they
+ // own the vulkan context.
+ ownsContext = false;
} else {
- backendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr,
- vkGetDeviceProcAddr));
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+ auto getProc = [instProc, devProc](const char* proc_name,
+ VkInstance instance, VkDevice device) {
+ if (device != VK_NULL_HANDLE) {
+ return devProc(device, proc_name);
+ }
+ return instProc(instance, proc_name);
+ };
+ extensions = new GrVkExtensions();
+ features = new VkPhysicalDeviceFeatures2;
+ memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
+ if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, extensions,
+ features, &debugCallback)) {
+ sk_gpu_test::FreeVulkanFeaturesStructs(features);
+ delete features;
+ delete extensions;
+ return nullptr;
+ }
+ if (debugCallback != VK_NULL_HANDLE) {
+ destroyCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
+ backendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
+ }
}
- if (!backendContext) {
- return nullptr;
- }
- return new VkTestContextImpl(std::move(backendContext));
+ return new VkTestContextImpl(backendContext, extensions, features, ownsContext,
+ debugCallback, destroyCallback);
}
~VkTestContextImpl() override { this->teardown(); }
@@ -131,20 +201,56 @@
void finish() override {}
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
+ return GrContext::MakeVulkan(fVk, options);
+ }
+
protected:
+#define ACQUIRE_VK_PROC_LOCAL(name, inst) \
+ PFN_vk##name grVk##name = \
+ reinterpret_cast<PFN_vk##name>(fVk.fGetProc("vk" #name, inst, nullptr)); \
+ do { \
+ if (grVk##name == nullptr) { \
+ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
+ return; \
+ } \
+ } while (0)
+
void teardown() override {
INHERITED::teardown();
- fVk.reset(nullptr);
+ fVk.fMemoryAllocator.reset();
+ if (fOwnsContext) {
+ ACQUIRE_VK_PROC_LOCAL(DeviceWaitIdle, fVk.fInstance);
+ ACQUIRE_VK_PROC_LOCAL(DestroyDevice, fVk.fInstance);
+ ACQUIRE_VK_PROC_LOCAL(DestroyInstance, fVk.fInstance);
+ grVkDeviceWaitIdle(fVk.fDevice);
+ grVkDestroyDevice(fVk.fDevice, nullptr);
+#ifdef SK_ENABLE_VK_LAYERS
+ if (fDebugCallback != VK_NULL_HANDLE) {
+ fDestroyDebugReportCallbackEXT(fVk.fInstance, fDebugCallback, nullptr);
+ }
+#endif
+ grVkDestroyInstance(fVk.fInstance, nullptr);
+ delete fExtensions;
+
+ sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
+ delete fFeatures;
+ }
}
private:
- VkTestContextImpl(sk_sp<const GrVkBackendContext> backendContext)
- : VkTestContext(std::move(backendContext)) {
- fFenceSync.reset(new VkFenceSync(fVk->fInterface, fVk->fDevice, fVk->fQueue,
- fVk->fGraphicsQueueIndex));
+ VkTestContextImpl(const GrVkBackendContext& backendContext, const GrVkExtensions* extensions,
+ VkPhysicalDeviceFeatures2* features, bool ownsContext,
+ VkDebugReportCallbackEXT debugCallback,
+ PFN_vkDestroyDebugReportCallbackEXT destroyCallback)
+ : VkTestContext(backendContext, extensions, features, ownsContext, debugCallback,
+ destroyCallback) {
+ fFenceSync.reset(new VkFenceSync(fVk.fGetProc, fVk.fDevice, fVk.fQueue,
+ fVk.fGraphicsQueueIndex));
}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
typedef sk_gpu_test::VkTestContext INHERITED;
diff --git a/src/third_party/skia/tools/gpu/vk/VkTestContext.h b/src/third_party/skia/tools/gpu/vk/VkTestContext.h
index 5090f55..fd4d8d2 100644
--- a/src/third_party/skia/tools/gpu/vk/VkTestContext.h
+++ b/src/third_party/skia/tools/gpu/vk/VkTestContext.h
@@ -8,30 +8,50 @@
#ifndef VkTestContext_DEFINED
#define VkTestContext_DEFINED
-#include "TestContext.h"
+#include "tools/gpu/TestContext.h"
#ifdef SK_VULKAN
-#include "vk/GrVkBackendContext.h"
+#include "include/gpu/vk/GrVkBackendContext.h"
+#include "tools/gpu/vk/GrVulkanDefines.h"
+
+class GrVkExtensions;
namespace sk_gpu_test {
class VkTestContext : public TestContext {
public:
- virtual GrBackend backend() override { return kVulkan_GrBackend; }
- virtual GrBackendContext backendContext() override {
- return reinterpret_cast<GrBackendContext>(fVk.get());
- }
+ virtual GrBackendApi backend() override { return GrBackendApi::kVulkan; }
- sk_sp<const GrVkBackendContext> getVkBackendContext() {
+ const GrVkBackendContext& getVkBackendContext() const {
return fVk;
}
- const GrVkInterface* vk() const { return fVk->fInterface.get(); }
+ const GrVkExtensions* getVkExtensions() const {
+ return fExtensions;
+ }
+
+ const VkPhysicalDeviceFeatures2* getVkFeatures() const {
+ return fFeatures;
+ }
protected:
- VkTestContext(sk_sp<const GrVkBackendContext> vk) : fVk(std::move(vk)) {}
+ VkTestContext(const GrVkBackendContext& vk, const GrVkExtensions* extensions,
+ const VkPhysicalDeviceFeatures2* features, bool ownsContext,
+ VkDebugReportCallbackEXT debugCallback,
+ PFN_vkDestroyDebugReportCallbackEXT destroyCallback)
+ : fVk(vk)
+ , fExtensions(extensions)
+ , fFeatures(features)
+ , fOwnsContext(ownsContext)
+ , fDebugCallback(debugCallback)
+ , fDestroyDebugReportCallbackEXT(destroyCallback) {}
- sk_sp<const GrVkBackendContext> fVk;
+ GrVkBackendContext fVk;
+ const GrVkExtensions* fExtensions;
+ const VkPhysicalDeviceFeatures2* fFeatures;
+ bool fOwnsContext;
+ VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
+ PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugReportCallbackEXT = nullptr;
private:
typedef TestContext INHERITED;
diff --git a/src/third_party/skia/tools/gpu/vk/VkTestUtils.cpp b/src/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
new file mode 100644
index 0000000..5b7e8c2
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
@@ -0,0 +1,775 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/gpu/vk/VkTestUtils.h"
+
+#ifdef SK_VULKAN
+
+#ifndef SK_GPU_TOOLS_VK_LIBRARY_NAME
+ #if defined _WIN32
+ #define SK_GPU_TOOLS_VK_LIBRARY_NAME "vulkan-1.dll"
+ #else
+ #define SK_GPU_TOOLS_VK_LIBRARY_NAME "libvulkan.so"
+ #endif
+#endif
+
+#include "include/gpu/vk/GrVkBackendContext.h"
+#include "include/gpu/vk/GrVkExtensions.h"
+#include "src/core/SkAutoMalloc.h"
+#include "src/ports/SkOSLibrary.h"
+
+#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
+#include <sanitizer/lsan_interface.h>
+#endif
+
+namespace sk_gpu_test {
+
+bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc,
+ PFN_vkGetDeviceProcAddr* devProc) {
+#ifdef SK_MOLTENVK
+ // MoltenVK is a statically linked framework, so there is no Vulkan library to load.
+ *instProc = &vkGetInstanceProcAddr;
+ *devProc = &vkGetDeviceProcAddr;
+ return true;
+#else
+ static void* vkLib = nullptr;
+ static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
+ static PFN_vkGetDeviceProcAddr localDevProc = nullptr;
+ if (!vkLib) {
+ vkLib = DynamicLoadLibrary(SK_GPU_TOOLS_VK_LIBRARY_NAME);
+ if (!vkLib) {
+ return false;
+ }
+ localInstProc = (PFN_vkGetInstanceProcAddr) GetProcedureAddress(vkLib,
+ "vkGetInstanceProcAddr");
+ localDevProc = (PFN_vkGetDeviceProcAddr) GetProcedureAddress(vkLib,
+ "vkGetDeviceProcAddr");
+ }
+ if (!localInstProc || !localDevProc) {
+ return false;
+ }
+ *instProc = localInstProc;
+ *devProc = localDevProc;
+ return true;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper code to set up Vulkan context objects
+
+#ifdef SK_ENABLE_VK_LAYERS
+const char* kDebugLayerNames[] = {
+ // elements of VK_LAYER_LUNARG_standard_validation
+ "VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
+ "VK_LAYER_LUNARG_object_tracker",
+ "VK_LAYER_LUNARG_core_validation",
+ "VK_LAYER_GOOGLE_unique_objects",
+ // not included in standard_validation
+ //"VK_LAYER_LUNARG_api_dump",
+ //"VK_LAYER_LUNARG_vktrace",
+ //"VK_LAYER_LUNARG_screenshot",
+};
+
+static uint32_t remove_patch_version(uint32_t specVersion) {
+ return (specVersion >> 12) << 12;
+}
+
+// Returns the index into layers array for the layer we want. Returns -1 if not supported.
+static int should_include_debug_layer(const char* layerName,
+ uint32_t layerCount, VkLayerProperties* layers,
+ uint32_t version) {
+ for (uint32_t i = 0; i < layerCount; ++i) {
+ if (!strcmp(layerName, layers[i].layerName)) {
+ // Since the layers intercept the vulkan calls and forward them on, we need to make sure
+ // layer was written against a version that isn't older than the version of Vulkan we're
+ // using so that it has all the api entry points.
+ if (version <= remove_patch_version(layers[i].specVersion)) {
+ return i;
+ }
+ return -1;
+ }
+
+ }
+ return -1;
+}
+
+VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage,
+ void* pUserData) {
+ if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
+ return VK_TRUE; // skip further layers
+ } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ // There is currently a bug in the spec which doesn't have
+ // VK_STRUCTURE_TYPE_BLEND_OPERATION_ADVANCED_FEATURES_EXT as an allowable pNext struct in
+ // VkDeviceCreateInfo. So we ignore that warning since it is wrong.
+ if (!strstr(pMessage,
+ "pCreateInfo->pNext chain includes a structure with unexpected VkStructureType "
+ "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT")) {
+ SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
+ }
+ } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+ SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
+ } else {
+ SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
+ }
+ return VK_FALSE;
+}
+#endif
+
+#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
+
+static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
+ uint32_t specVersion,
+ SkTArray<VkExtensionProperties>* instanceExtensions,
+ SkTArray<VkLayerProperties>* instanceLayers) {
+ if (getProc == nullptr) {
+ return false;
+ }
+
+ GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
+ GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
+
+ if (!EnumerateInstanceExtensionProperties ||
+ !EnumerateInstanceLayerProperties) {
+ return false;
+ }
+
+ VkResult res;
+ uint32_t layerCount = 0;
+#ifdef SK_ENABLE_VK_LAYERS
+ // instance layers
+ res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkLayerProperties* layers = new VkLayerProperties[layerCount];
+ res = EnumerateInstanceLayerProperties(&layerCount, layers);
+ if (VK_SUCCESS != res) {
+ delete[] layers;
+ return false;
+ }
+
+ uint32_t nonPatchVersion = remove_patch_version(specVersion);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
+ int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
+ nonPatchVersion);
+ if (idx != -1) {
+ instanceLayers->push_back() = layers[idx];
+ }
+ }
+ delete[] layers;
+#endif
+
+ // instance extensions
+ // via Vulkan implementation and implicitly enabled layers
+ uint32_t extensionCount = 0;
+ res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+ res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
+ if (VK_SUCCESS != res) {
+ delete[] extensions;
+ return false;
+ }
+ for (uint32_t i = 0; i < extensionCount; ++i) {
+ instanceExtensions->push_back() = extensions[i];
+ }
+ delete [] extensions;
+
+ // via explicitly enabled layers
+ layerCount = instanceLayers->count();
+ for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
+ uint32_t extensionCount = 0;
+ res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
+ &extensionCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+ res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
+ &extensionCount, extensions);
+ if (VK_SUCCESS != res) {
+ delete[] extensions;
+ return false;
+ }
+ for (uint32_t i = 0; i < extensionCount; ++i) {
+ instanceExtensions->push_back() = extensions[i];
+ }
+ delete[] extensions;
+ }
+
+ return true;
+}
+
+static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion,
+ VkInstance inst, VkPhysicalDevice physDev,
+ SkTArray<VkExtensionProperties>* deviceExtensions,
+ SkTArray<VkLayerProperties>* deviceLayers) {
+ if (getProc == nullptr) {
+ return false;
+ }
+
+ GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
+ GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
+
+ if (!EnumerateDeviceExtensionProperties ||
+ !EnumerateDeviceLayerProperties) {
+ return false;
+ }
+
+ VkResult res;
+ // device layers
+ uint32_t layerCount = 0;
+#ifdef SK_ENABLE_VK_LAYERS
+ res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkLayerProperties* layers = new VkLayerProperties[layerCount];
+ res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
+ if (VK_SUCCESS != res) {
+ delete[] layers;
+ return false;
+ }
+
+ uint32_t nonPatchVersion = remove_patch_version(specVersion);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
+ int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
+ nonPatchVersion);
+ if (idx != -1) {
+ deviceLayers->push_back() = layers[idx];
+ }
+ }
+ delete[] layers;
+#endif
+
+ // device extensions
+ // via Vulkan implementation and implicitly enabled layers
+ uint32_t extensionCount = 0;
+ res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+ res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
+ if (VK_SUCCESS != res) {
+ delete[] extensions;
+ return false;
+ }
+ for (uint32_t i = 0; i < extensionCount; ++i) {
+ deviceExtensions->push_back() = extensions[i];
+ }
+ delete[] extensions;
+
+ // via explicitly enabled layers
+ layerCount = deviceLayers->count();
+ for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
+ uint32_t extensionCount = 0;
+ res = EnumerateDeviceExtensionProperties(physDev,
+ (*deviceLayers)[layerIndex].layerName,
+ &extensionCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+ VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+ res = EnumerateDeviceExtensionProperties(physDev,
+ (*deviceLayers)[layerIndex].layerName,
+ &extensionCount, extensions);
+ if (VK_SUCCESS != res) {
+ delete[] extensions;
+ return false;
+ }
+ for (uint32_t i = 0; i < extensionCount; ++i) {
+ deviceExtensions->push_back() = extensions[i];
+ }
+ delete[] extensions;
+ }
+
+ return true;
+}
+
+#define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
+ PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device))
+
+#define ACQUIRE_VK_PROC(name, instance, device) \
+ PFN_vk##name grVk##name = \
+ reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
+ do { \
+ if (grVk##name == nullptr) { \
+ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
+ if (device != VK_NULL_HANDLE) { \
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \
+ } \
+ return false; \
+ } \
+ } while (0)
+
+#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \
+ PFN_vk##name grVk##name = \
+ reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
+ do { \
+ if (grVk##name == nullptr) { \
+ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
+ return false; \
+ } \
+ } while (0)
+
+static bool destroy_instance(GrVkGetProc getProc, VkInstance inst,
+ VkDebugReportCallbackEXT* debugCallback,
+ bool hasDebugExtension) {
+ if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
+ ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
+ grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
+ *debugCallback = VK_NULL_HANDLE;
+ }
+ ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE);
+ grVkDestroyInstance(inst, nullptr);
+ return true;
+}
+
+static bool setup_features(GrVkGetProc getProc, VkInstance inst, VkPhysicalDevice physDev,
+ uint32_t physDeviceVersion, GrVkExtensions* extensions,
+ VkPhysicalDeviceFeatures2* features, bool isProtected) {
+ SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
+ extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1));
+
+ // Setup all extension feature structs we may want to use.
+ void** tailPNext = &features->pNext;
+
+ // If |isProtected| is given, attach that first
+ VkPhysicalDeviceProtectedMemoryFeatures* protectedMemoryFeatures = nullptr;
+ if (isProtected) {
+ SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0));
+ protectedMemoryFeatures =
+ (VkPhysicalDeviceProtectedMemoryFeatures*)sk_malloc_throw(
+ sizeof(VkPhysicalDeviceProtectedMemoryFeatures));
+ protectedMemoryFeatures->sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
+ protectedMemoryFeatures->pNext = nullptr;
+ *tailPNext = protectedMemoryFeatures;
+ tailPNext = &protectedMemoryFeatures->pNext;
+ }
+
+ VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend = nullptr;
+ if (extensions->hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
+ blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) sk_malloc_throw(
+ sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
+ blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
+ blend->pNext = nullptr;
+ *tailPNext = blend;
+ tailPNext = &blend->pNext;
+ }
+
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature = nullptr;
+ if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
+ extensions->hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1)) {
+ ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) sk_malloc_throw(
+ sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
+ ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
+ ycbcrFeature->pNext = nullptr;
+ ycbcrFeature->samplerYcbcrConversion = VK_TRUE;
+ *tailPNext = ycbcrFeature;
+ tailPNext = &ycbcrFeature->pNext;
+ }
+
+ if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2, inst, VK_NULL_HANDLE);
+ grVkGetPhysicalDeviceFeatures2(physDev, features);
+ } else {
+ SkASSERT(extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ 1));
+ ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2KHR, inst, VK_NULL_HANDLE);
+ grVkGetPhysicalDeviceFeatures2KHR(physDev, features);
+ }
+
+ if (isProtected) {
+ if (!protectedMemoryFeatures->protectedMemory) {
+ return false;
+ }
+ }
+ return true;
+ // If we want to disable any extension features do so here.
+}
+
+bool CreateVkBackendContext(GrVkGetProc getProc,
+ GrVkBackendContext* ctx,
+ GrVkExtensions* extensions,
+ VkPhysicalDeviceFeatures2* features,
+ VkDebugReportCallbackEXT* debugCallback,
+ uint32_t* presentQueueIndexPtr,
+ CanPresentFn canPresent,
+ bool isProtected) {
+ VkResult err;
+
+ ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE);
+ uint32_t instanceVersion = 0;
+ if (!grVkEnumerateInstanceVersion) {
+ instanceVersion = VK_MAKE_VERSION(1, 0, 0);
+ } else {
+ err = grVkEnumerateInstanceVersion(&instanceVersion);
+ if (err) {
+ SkDebugf("failed to enumerate instance version. Err: %d\n", err);
+ return false;
+ }
+ }
+ SkASSERT(instanceVersion >= VK_MAKE_VERSION(1, 0, 0));
+ if (isProtected && instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
+ SkDebugf("protected requires vk instance version 1.1\n");
+ return false;
+ }
+
+ uint32_t apiVersion = VK_MAKE_VERSION(1, 0, 0);
+ if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ // If the instance version is 1.0 we must have the apiVersion also be 1.0. However, if the
+ // instance version is 1.1 or higher, we can set the apiVersion to be whatever the highest
+ // api we may use in skia (technically it can be arbitrary). So for now we set it to 1.1
+ // since that is the highest vulkan version.
+ apiVersion = VK_MAKE_VERSION(1, 1, 0);
+ }
+
+ instanceVersion = SkTMin(instanceVersion, apiVersion);
+
+ VkPhysicalDevice physDev;
+ VkDevice device;
+ VkInstance inst;
+
+ const VkApplicationInfo app_info = {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
+ nullptr, // pNext
+ "vktest", // pApplicationName
+ 0, // applicationVersion
+ "vktest", // pEngineName
+ 0, // engineVerison
+ apiVersion, // apiVersion
+ };
+
+ SkTArray<VkLayerProperties> instanceLayers;
+ SkTArray<VkExtensionProperties> instanceExtensions;
+
+ if (!init_instance_extensions_and_layers(getProc, instanceVersion,
+ &instanceExtensions,
+ &instanceLayers)) {
+ return false;
+ }
+
+ SkTArray<const char*> instanceLayerNames;
+ SkTArray<const char*> instanceExtensionNames;
+ for (int i = 0; i < instanceLayers.count(); ++i) {
+ instanceLayerNames.push_back(instanceLayers[i].layerName);
+ }
+ for (int i = 0; i < instanceExtensions.count(); ++i) {
+ if (strncmp(instanceExtensions[i].extensionName, "VK_KHX", 6)) {
+ instanceExtensionNames.push_back(instanceExtensions[i].extensionName);
+ }
+ }
+
+ const VkInstanceCreateInfo instance_create = {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
+ nullptr, // pNext
+ 0, // flags
+ &app_info, // pApplicationInfo
+ (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
+ instanceLayerNames.begin(), // ppEnabledLayerNames
+ (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
+ instanceExtensionNames.begin(), // ppEnabledExtensionNames
+ };
+
+ bool hasDebugExtension = false;
+
+ ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
+ err = grVkCreateInstance(&instance_create, nullptr, &inst);
+ if (err < 0) {
+ SkDebugf("vkCreateInstance failed: %d\n", err);
+ return false;
+ }
+
+#ifdef SK_ENABLE_VK_LAYERS
+ *debugCallback = VK_NULL_HANDLE;
+ for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
+ if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
+ hasDebugExtension = true;
+ }
+ }
+ if (hasDebugExtension) {
+ // Setup callback creation information
+ VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
+ callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ callbackCreateInfo.pNext = nullptr;
+ callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
+ VK_DEBUG_REPORT_WARNING_BIT_EXT |
+ // VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
+ // VK_DEBUG_REPORT_DEBUG_BIT_EXT |
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ callbackCreateInfo.pfnCallback = &DebugReportCallback;
+ callbackCreateInfo.pUserData = nullptr;
+
+ ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
+ // Register the callback
+ grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
+ }
+#endif
+
+ ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
+ ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
+
+ uint32_t gpuCount;
+ err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
+ if (err) {
+ SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+ if (!gpuCount) {
+ SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+ // Just returning the first physical device instead of getting the whole array.
+ // TODO: find best match for our needs
+ gpuCount = 1;
+ err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
+ // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
+ if (err && VK_INCOMPLETE != err) {
+ SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ VkPhysicalDeviceProperties physDeviceProperties;
+ grVkGetPhysicalDeviceProperties(physDev, &physDeviceProperties);
+ int physDeviceVersion = SkTMin(physDeviceProperties.apiVersion, apiVersion);
+
+ if (isProtected && physDeviceVersion < VK_MAKE_VERSION(1, 1, 0)) {
+ SkDebugf("protected requires vk physical device version 1.1\n");
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ // query to get the initial queue props size
+ uint32_t queueCount;
+ grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
+ if (!queueCount) {
+ SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
+ // now get the actual queue props
+ VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
+
+ grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
+
+ // iterate to find the graphics queue
+ uint32_t graphicsQueueIndex = queueCount;
+ for (uint32_t i = 0; i < queueCount; i++) {
+ if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ graphicsQueueIndex = i;
+ break;
+ }
+ }
+ if (graphicsQueueIndex == queueCount) {
+ SkDebugf("Could not find any supported graphics queues.\n");
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ // iterate to find the present queue, if needed
+ uint32_t presentQueueIndex = queueCount;
+ if (presentQueueIndexPtr && canPresent) {
+ for (uint32_t i = 0; i < queueCount; i++) {
+ if (canPresent(inst, physDev, i)) {
+ presentQueueIndex = i;
+ break;
+ }
+ }
+ if (presentQueueIndex == queueCount) {
+ SkDebugf("Could not find any supported present queues.\n");
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+ *presentQueueIndexPtr = presentQueueIndex;
+ } else {
+ // Just setting this so we end up make a single queue for graphics since there was no
+ // request for a present queue.
+ presentQueueIndex = graphicsQueueIndex;
+ }
+
+ SkTArray<VkLayerProperties> deviceLayers;
+ SkTArray<VkExtensionProperties> deviceExtensions;
+ if (!init_device_extensions_and_layers(getProc, physDeviceVersion,
+ inst, physDev,
+ &deviceExtensions,
+ &deviceLayers)) {
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ SkTArray<const char*> deviceLayerNames;
+ SkTArray<const char*> deviceExtensionNames;
+ for (int i = 0; i < deviceLayers.count(); ++i) {
+ deviceLayerNames.push_back(deviceLayers[i].layerName);
+ }
+ for (int i = 0; i < deviceExtensions.count(); ++i) {
+ // Don't use experimental extensions since they typically don't work with debug layers and
+ // often are missing dependecy requirements for other extensions. Additionally, these are
+ // often left behind in the driver even after they've been promoted to real extensions.
+ if (strncmp(deviceExtensions[i].extensionName, "VK_KHX", 6) &&
+ strncmp(deviceExtensions[i].extensionName, "VK_NVX", 6)) {
+ deviceExtensionNames.push_back(deviceExtensions[i].extensionName);
+ }
+ }
+
+ extensions->init(getProc, inst, physDev,
+ (uint32_t) instanceExtensionNames.count(),
+ instanceExtensionNames.begin(),
+ (uint32_t) deviceExtensionNames.count(),
+ deviceExtensionNames.begin());
+
+ memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
+ features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ features->pNext = nullptr;
+
+ VkPhysicalDeviceFeatures* deviceFeatures = &features->features;
+ void* pointerToFeatures = nullptr;
+ if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
+ extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
+ if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features,
+ isProtected)) {
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ // If we set the pNext of the VkDeviceCreateInfo to our VkPhysicalDeviceFeatures2 struct,
+ // the device creation will use that instead of the ppEnabledFeatures.
+ pointerToFeatures = features;
+ } else {
+ grVkGetPhysicalDeviceFeatures(physDev, deviceFeatures);
+ }
+
+ // this looks like it would slow things down,
+ // and we can't depend on it on all platforms
+ deviceFeatures->robustBufferAccess = VK_FALSE;
+
+ VkDeviceQueueCreateFlags flags = isProtected ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
+ float queuePriorities[1] = { 0.0 };
+ // Here we assume no need for swapchain queue
+ // If one is needed, the client will need its own setup code
+ const VkDeviceQueueCreateInfo queueInfo[2] = {
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
+ nullptr, // pNext
+ flags, // VkDeviceQueueCreateFlags
+ graphicsQueueIndex, // queueFamilyIndex
+ 1, // queueCount
+ queuePriorities, // pQueuePriorities
+
+ },
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
+ nullptr, // pNext
+ 0, // VkDeviceQueueCreateFlags
+ presentQueueIndex, // queueFamilyIndex
+ 1, // queueCount
+ queuePriorities, // pQueuePriorities
+ }
+ };
+ uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
+
+ const VkDeviceCreateInfo deviceInfo = {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
+ pointerToFeatures, // pNext
+ 0, // VkDeviceCreateFlags
+ queueInfoCount, // queueCreateInfoCount
+ queueInfo, // pQueueCreateInfos
+ (uint32_t) deviceLayerNames.count(), // layerCount
+ deviceLayerNames.begin(), // ppEnabledLayerNames
+ (uint32_t) deviceExtensionNames.count(), // extensionCount
+ deviceExtensionNames.begin(), // ppEnabledExtensionNames
+ pointerToFeatures ? nullptr : deviceFeatures // ppEnabledFeatures
+ };
+
+ {
+#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
+ // skia:8712
+ __lsan::ScopedDisabler lsanDisabler;
+#endif
+ err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
+ }
+ if (err) {
+ SkDebugf("CreateDevice failed: %d\n", err);
+ destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
+ return false;
+ }
+
+ VkQueue queue;
+ if (isProtected) {
+ ACQUIRE_VK_PROC(GetDeviceQueue2, inst, device);
+ SkASSERT(grVkGetDeviceQueue2 != nullptr);
+ VkDeviceQueueInfo2 queue_info2 = {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, // sType
+ nullptr, // pNext
+ VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT, // flags
+ graphicsQueueIndex, // queueFamilyIndex
+ 0 // queueIndex
+ };
+ grVkGetDeviceQueue2(device, &queue_info2, &queue);
+ } else {
+ grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
+ }
+
+ ctx->fInstance = inst;
+ ctx->fPhysicalDevice = physDev;
+ ctx->fDevice = device;
+ ctx->fQueue = queue;
+ ctx->fGraphicsQueueIndex = graphicsQueueIndex;
+ ctx->fMaxAPIVersion = apiVersion;
+ ctx->fVkExtensions = extensions;
+ ctx->fDeviceFeatures2 = features;
+ ctx->fGetProc = getProc;
+ ctx->fOwnsInstanceAndDevice = false;
+ ctx->fProtectedContext = isProtected ? GrProtected::kYes : GrProtected::kNo;
+
+ return true;
+}
+
+void FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2* features) {
+ // All Vulkan structs that could be part of the features chain will start with the
+ // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
+ // so we can get access to the pNext for the next struct.
+ struct CommonVulkanHeader {
+ VkStructureType sType;
+ void* pNext;
+ };
+
+ void* pNext = features->pNext;
+ while (pNext) {
+ void* current = pNext;
+ pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
+ sk_free(current);
+ }
+}
+
+}
+
+#endif
diff --git a/src/third_party/skia/tools/gpu/vk/VkTestUtils.h b/src/third_party/skia/tools/gpu/vk/VkTestUtils.h
new file mode 100644
index 0000000..ab7281d
--- /dev/null
+++ b/src/third_party/skia/tools/gpu/vk/VkTestUtils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef VkTestUtils_DEFINED
+#define VkTestUtils_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#ifdef SK_VULKAN
+
+#include "include/gpu/vk/GrVkBackendContext.h"
+#include "include/gpu/vk/GrVkTypes.h"
+#include "tools/gpu/vk/GrVulkanDefines.h"
+#include <functional>
+
+class GrVkExtensions;
+struct GrVkBackendContext;
+
+namespace sk_gpu_test {
+ bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr*, PFN_vkGetDeviceProcAddr*);
+
+ using CanPresentFn = std::function<bool(VkInstance, VkPhysicalDevice,
+ uint32_t queueFamilyIndex)>;
+
+ bool CreateVkBackendContext(GrVkGetProc getProc,
+ GrVkBackendContext* ctx,
+ GrVkExtensions*,
+ VkPhysicalDeviceFeatures2*,
+ VkDebugReportCallbackEXT* debugCallback,
+ uint32_t* presentQueueIndexPtr = nullptr,
+ CanPresentFn canPresent = CanPresentFn(),
+ bool isProtected = false);
+
+ void FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2*);
+}
+
+#endif
+#endif
+
diff --git a/src/third_party/skia/tools/gpuveto.cpp b/src/third_party/skia/tools/gpuveto.cpp
deleted file mode 100644
index cc33721..0000000
--- a/src/third_party/skia/tools/gpuveto.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCommandLineFlags.h"
-#include "SkPicture.h"
-#include "SkPictureAnalyzer.h"
-#include "SkPictureRecorder.h"
-#include "SkStream.h"
-
-DEFINE_string2(readFile, r, "", "skp file to process.");
-DEFINE_bool2(quiet, q, false, "quiet");
-
-// This tool just loads a single skp, replays into a new SkPicture (to
-// regenerate the GPU-specific tracking information) and reports
-// the value of the suitableForGpuRasterization method.
-// Return codes:
-static const int kSuccess = 0;
-static const int kError = 1;
-
-int main(int argc, char** argv) {
-#if SK_SUPPORT_GPU
- SkCommandLineFlags::SetUsage("Reports on an skp file's suitability for GPU rasterization");
- SkCommandLineFlags::Parse(argc, argv);
-
- if (FLAGS_readFile.count() != 1) {
- if (!FLAGS_quiet) {
- SkDebugf("Missing input file\n");
- }
- return kError;
- }
-
- SkFILEStream inputStream(FLAGS_readFile[0]);
- if (!inputStream.isValid()) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't open file\n");
- }
- return kError;
- }
-
- sk_sp<SkPicture> picture(SkPicture::MakeFromStream(&inputStream));
- if (nullptr == picture) {
- if (!FLAGS_quiet) {
- SkDebugf("Could not read the SkPicture\n");
- }
- return kError;
- }
-
- // The SkPicture tracking information is only generated during recording
- // an isn't serialized. Replay the picture to regenerated the tracking data.
- SkPictureRecorder recorder;
- picture->playback(recorder.beginRecording(picture->cullRect().width(),
- picture->cullRect().height(),
- nullptr, 0));
- sk_sp<SkPicture> recorded(recorder.finishRecordingAsPicture());
-
- if (SkPictureGpuAnalyzer(recorded).suitableForGpuRasterization(nullptr)) {
- SkDebugf("suitable\n");
- } else {
- SkDebugf("unsuitable\n");
- }
-
- return kSuccess;
-#else
- SkDebugf("gpuveto is only useful when GPU rendering is enabled\n");
- return kError;
-#endif
-}
diff --git a/src/third_party/skia/tools/gyp b/src/third_party/skia/tools/gyp
deleted file mode 120000
index d871f5b..0000000
--- a/src/third_party/skia/tools/gyp
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/externals/gyp/
\ No newline at end of file
diff --git a/src/third_party/skia/tools/hello-opencl.cpp b/src/third_party/skia/tools/hello-opencl.cpp
new file mode 100644
index 0000000..12b51f5
--- /dev/null
+++ b/src/third_party/skia/tools/hello-opencl.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// This is a simple OpenCL Hello World that tests you have a functioning OpenCL setup.
+
+#include "cl.hpp"
+#include <initializer_list>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+static inline void assert_cl(cl_int rc, const char* file, int line) {
+ if (rc != CL_SUCCESS) {
+ fprintf(stderr, "%s:%d, got OpenCL error code %d\n", file,line,rc);
+ exit(1);
+ }
+}
+#define cl_ok(err) assert_cl(err, __FILE__, __LINE__)
+
+int main(int, char**) {
+ std::vector<cl::Platform> platforms;
+ cl_ok(cl::Platform::get(&platforms));
+
+ std::vector<cl::Device> devices;
+ for (cl::Platform platform : platforms) {
+ std::vector<cl::Device> platform_devices;
+ cl_ok(platform.getDevices(CL_DEVICE_TYPE_ALL, &platform_devices));
+ devices.insert(devices.end(), platform_devices.begin(), platform_devices.end());
+ }
+
+ if (devices.empty()) {
+ fprintf(stderr, "No OpenCL devices available. :(\n");
+ return 1;
+ }
+
+ // To keep things simple we'll only create single-device cl::Contexts.
+ for (cl::Device device : devices) {
+ std::string name,
+ version,
+ driver,
+ vendor,
+ extensions;
+ cl_ok(device.getInfo(CL_DEVICE_NAME, &name));
+ cl_ok(device.getInfo(CL_DEVICE_VERSION, &version));
+ cl_ok(device.getInfo(CL_DEVICE_VENDOR, &vendor));
+ cl_ok(device.getInfo(CL_DEVICE_EXTENSIONS, &extensions));
+ cl_ok(device.getInfo(CL_DRIVER_VERSION, &driver));
+
+ fprintf(stdout, "Using %s%s, vendor %s, version %s, extensions:\n%s\n",
+ version.c_str(), name.c_str(), vendor.c_str(), driver.c_str(), extensions.c_str());
+
+ std::vector<cl::Device> devices = { device };
+
+ // Some APIs can't return their cl_int error but might still fail,
+ // so they take a pointer. cl_ok() is really handy here too.
+ cl_int ok;
+ cl::Context ctx(devices,
+ nullptr/*optional cl_context_properties*/,
+ nullptr/*optional error reporting callback*/,
+ nullptr/*context argument for error reporting callback*/,
+ &ok);
+ cl_ok(ok);
+
+ cl::Program program(ctx,
+ "__kernel void mul(__global const float* a, "
+ " __global const float* b, "
+ " __global float* dst) {"
+ " int i = get_global_id(0); "
+ " dst[i] = a[i] * b[i]; "
+ "} ",
+ /*and build now*/true,
+ &ok);
+ cl_ok(ok);
+
+ std::vector<float> a,b,p;
+ for (int i = 0; i < 1000; i++) {
+ a.push_back(+i);
+ b.push_back(-i);
+ p.push_back( 0);
+ }
+
+ cl::Buffer
+ A(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , sizeof(float)*a.size(), a.data()),
+ B(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , sizeof(float)*b.size(), b.data()),
+ P(ctx, CL_MEM_WRITE_ONLY| CL_MEM_HOST_READ_ONLY, sizeof(float)*p.size());
+
+ cl::Kernel mul(program, "mul", &ok);
+ cl_ok(ok);
+ cl_ok(mul.setArg(0, A));
+ cl_ok(mul.setArg(1, B));
+ cl_ok(mul.setArg(2, P));
+
+ cl::CommandQueue queue(ctx, device);
+
+ cl_ok(queue.enqueueNDRangeKernel(mul, cl::NDRange(0) /*offset*/
+ , cl::NDRange(1000) /*size*/));
+
+ cl_ok(queue.enqueueReadBuffer(P, true/*block until read is done*/
+ , 0 /*offset in bytes*/
+ , sizeof(float)*p.size() /*size in bytes*/
+ , p.data()));
+
+ fprintf(stdout, "OpenCL sez: %g x %g = %g\n", a[42], b[42], p[42]);
+ for (int i = 0; i < 1000; i++) {
+ if (p[i] != a[i]*b[i]) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/third_party/skia/tools/iOSShell.cpp b/src/third_party/skia/tools/iOSShell.cpp
deleted file mode 100644
index 02884c8..0000000
--- a/src/third_party/skia/tools/iOSShell.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "iOSShell.h"
-
-#include "Resources.h"
-#include "SkApplication.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkGraphics.h"
-#include "SkWindow.h"
-#include "sk_tool_utils.h"
-
-//////////////////////////////////////////////////////////////////////////////
-
-static SkView* curr_view(SkWindow* wind) {
- SkView::F2BIter iter(wind);
- return iter.next();
-}
-
-ShellWindow::ShellWindow(void* hwnd, int argc, char** argv)
- : INHERITED(hwnd) {
- SkCommandLineFlags::Parse(argc, argv);
-}
-
-ShellWindow::~ShellWindow() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool ShellWindow::onDispatchClick(int x, int y, Click::State state,
- void* owner, unsigned modi) {
- int w = SkScalarRoundToInt(this->width());
- int h = SkScalarRoundToInt(this->height());
-
- // check for the resize-box
- if (w - x < 16 && h - y < 16) {
- return false; // let the OS handle the click
- } else {
- return this->INHERITED::onDispatchClick(x, y, state, owner, modi);
- }
-}
-
-void ShellWindow::onSizeChange() {
- this->INHERITED::onSizeChange();
-
- SkView::F2BIter iter(this);
- SkView* view = iter.next();
- view->setSize(this->width(), this->height());
-}
-
-DEFINE_bool(dm, false, "run dm");
-DEFINE_bool(nanobench, false, "run nanobench");
-
-int nanobench_main();
-int dm_main();
-
-IOS_launch_type set_cmd_line_args(int argc, char *argv[], const char* resourceDir) {
- SkCommandLineFlags::Parse(argc, argv);
- if (FLAGS_nanobench) {
- return nanobench_main() ? kError_iOSLaunchType : kTool_iOSLaunchType;
- }
- if (FLAGS_dm) {
- return dm_main() ? kError_iOSLaunchType : kTool_iOSLaunchType;
- }
- return kError_iOSLaunchType;
-}
-
-// FIXME: this should be in a header
-SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv);
-SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
- return new ShellWindow(hwnd, argc, argv);
-}
-
-// FIXME: this should be in a header
-void get_preferred_size(int* x, int* y, int* width, int* height);
-void get_preferred_size(int* x, int* y, int* width, int* height) {
- *x = 10;
- *y = 50;
- *width = 640;
- *height = 480;
-}
-
-// FIXME: this should be in a header
-void application_init();
-void application_init() {
- SkGraphics::Init();
- SkEvent::Init();
-}
-
-// FIXME: this should be in a header
-void application_term();
-void application_term() {
- SkEvent::Term();
-}
diff --git a/src/third_party/skia/tools/iOSShell.h b/src/third_party/skia/tools/iOSShell.h
deleted file mode 100644
index eaecba5..0000000
--- a/src/third_party/skia/tools/iOSShell.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2014 Skia
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef iOSShell_DEFINED
-#define iOSShell_DEFINED
-
-#include "SkWindow.h"
-
-class SkCanvas;
-class SkEvent;
-class SkViewFactory;
-
-class ShellWindow : public SkOSWindow {
-public:
- ShellWindow(void* hwnd, int argc, char** argv);
- virtual ~ShellWindow();
-
-protected:
- void onSizeChange() override;
-
- virtual bool onDispatchClick(int x, int y, Click::State, void* owner,
- unsigned modi) override;
-
-private:
- typedef SkOSWindow INHERITED;
-};
-
-#endif
diff --git a/src/third_party/skia/tools/image_diff_metric.cpp b/src/third_party/skia/tools/image_diff_metric.cpp
new file mode 100644
index 0000000..b690c72
--- /dev/null
+++ b/src/third_party/skia/tools/image_diff_metric.cpp
@@ -0,0 +1,54 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+// Image Diff: Provides a metric for measuring the difference between two encoded images. Prints
+// out a single floating-point number between 0.0 and 1.0; 0 means that the images are identical; 1
+// means that each pixel is maximally different in each channel. A non-zero return value indicates
+// that something went wrong.
+
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkSize.h"
+
+#include <cmath>
+#include <cstdio>
+
+int main(int argc, char** argv) {
+ if (argc != 3) {
+ const char usage[] = "\nUsage:\n %s {FILE1}.png {FILE2}.png\n\n";
+ fprintf(stderr, usage, argv[0]);
+ return 1;
+ }
+ SkBitmap bm[2];
+ for (int i = 0; i < 2; ++i) {
+ const char* path = argv[i + 1];
+ if (std::unique_ptr<SkCodec> codec =
+ SkCodec::MakeFromData(SkData::MakeFromFileName(path))) {
+ bm[i].allocN32Pixels(codec->dimensions().fWidth, codec->dimensions().fHeight);
+ if (SkCodec::kSuccess == codec->getPixels(bm[i].pixmap())) {
+ continue;
+ }
+ }
+ fprintf(stderr, "\nBad file: '%s'.\n\n", path);
+ return 2;
+ }
+ SkISize dim = bm[0].dimensions();
+ if (dim != bm[1].dimensions()) {
+ fprintf(stderr, "\nImages must be same size: (%d,%d) != (%d,%d)\n\n",
+ dim.fWidth, dim.fHeight, bm[1].dimensions().fWidth, bm[1].dimensions().fHeight);
+ return 3;
+ }
+ int64_t totalDiffs = 0; // Manhattan distance in ARGB color-space.
+ for (int y = 0; y < dim.fHeight; ++y) {
+ const uint8_t* row1 = reinterpret_cast<const uint8_t*>(bm[0].pixmap().addr32(0, y));
+ const uint8_t* row2 = reinterpret_cast<const uint8_t*>(bm[1].pixmap().addr32(0, y));
+ for (size_t i = 0; i < (size_t)dim.fWidth * (size_t)4; ++i) {
+ totalDiffs += std::abs((int)row1[i] - (int)row2[i]);
+ }
+ }
+ printf("%g\n", (double)totalDiffs /
+ ((uint64_t)255 * 4 * (uint64_t)dim.fWidth * (uint64_t)dim.fHeight));
+ return 0;
+}
diff --git a/src/third_party/skia/tools/imgblur.cpp b/src/third_party/skia/tools/imgblur.cpp
deleted file mode 100644
index 20d3684..0000000
--- a/src/third_party/skia/tools/imgblur.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmap.h"
-#include "SkCommandLineFlags.h"
-#include "SkCommonFlags.h"
-#include "SkData.h"
-#include "SkImage.h"
-#include "SkStream.h"
-#include "SkTypes.h"
-
-#include "sk_tool_utils.h"
-
-DEFINE_string(in, "input.png", "Input image");
-DEFINE_string(out, "blurred.png", "Output image");
-DEFINE_double(sigma, 1, "Sigma to be used for blur (> 0.0f)");
-
-
-// This tool just performs a blur on an input image
-// Return codes:
-static const int kSuccess = 0;
-static const int kError = 1;
-
-int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Brute force blur of an image.");
- SkCommandLineFlags::Parse(argc, argv);
-
- if (FLAGS_sigma <= 0) {
- if (!FLAGS_quiet) {
- SkDebugf("Sigma must be greater than zero (it is %f).\n", FLAGS_sigma);
- }
- return kError;
- }
-
- sk_sp<SkData> data(SkData::MakeFromFileName(FLAGS_in[0]));
- if (nullptr == data) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't open file: %s\n", FLAGS_in[0]);
- }
- return kError;
- }
-
- sk_sp<SkImage> image(SkImage::MakeFromEncoded(data));
- if (!image) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't create image for: %s.\n", FLAGS_in[0]);
- }
- return kError;
- }
-
- SkBitmap src;
- if (!image->asLegacyBitmap(&src, SkImage::kRW_LegacyBitmapMode)) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't create bitmap for: %s.\n", FLAGS_in[0]);
- }
- return kError;
- }
-
- SkBitmap dst = sk_tool_utils::slow_blur(src, (float) FLAGS_sigma);
-
- if (!sk_tool_utils::EncodeImageToFile(FLAGS_out[0], dst, SkEncodedImageFormat::kPNG, 100)) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't write to file: %s\n", FLAGS_out[0]);
- }
- return kError;
- }
-
- return kSuccess;
-}
diff --git a/src/third_party/skia/tools/imgcvt.cpp b/src/third_party/skia/tools/imgcvt.cpp
new file mode 100644
index 0000000..5c024f0
--- /dev/null
+++ b/src/third_party/skia/tools/imgcvt.cpp
@@ -0,0 +1,166 @@
+/*
+* Copyright 2018 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkData.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/third_party/skcms/skcms.h"
+#include "src/core/SkColorSpacePriv.h"
+
+static void write_png(const char* path, sk_sp<SkImage> img) {
+ sk_sp<SkData> png = img->encodeToData();
+ SkFILEWStream(path).write(png->data(), png->size());
+}
+
+int main(int argc, char** argv) {
+ const char* source_path = argc > 1 ? argv[1] : nullptr;
+ if (!source_path) {
+ SkDebugf("Please pass an image or profile to convert"
+ " as the first argument to this program.\n");
+ return 1;
+ }
+
+ const char* dst_profile_path = argc > 2 ? argv[2] : nullptr;
+ skcms_ICCProfile dst_profile = *skcms_sRGB_profile();
+ sk_sp<SkData> dst_blob;
+ if (dst_profile_path) {
+ dst_blob = SkData::MakeFromFileName(dst_profile_path);
+ if (!skcms_Parse(dst_blob->data(), dst_blob->size(), &dst_profile)) {
+ SkDebugf("Can't parse %s as an ICC profile.\n", dst_profile_path);
+ return 1;
+ }
+ }
+
+ auto blob = SkData::MakeFromFileName(source_path);
+
+ skcms_ICCProfile src_profile;
+ if (skcms_Parse(blob->data(), blob->size(), &src_profile)) {
+ // Transform white, black, primaries, and primary complements.
+ float src[] = {
+ 0,0,0,
+ 1,1,1,
+
+ 1,0,0,
+ 0,1,0,
+ 0,0,1,
+
+ 0,1,1,
+ 1,0,1,
+ 1,1,0,
+ };
+ float dst[24] = {0};
+
+ if (!skcms_Transform(
+ src, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &src_profile,
+ dst, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &dst_profile,
+ 8)) {
+ SkDebugf("Cannot transform.\n");
+ return 1;
+ }
+ for (int i = 0; i < 8; i++) {
+ SkDebugf("(%g, %g, %g) --> (%+.4f, %+.4f, %+.4f)\n",
+ src[3*i+0], src[3*i+1], src[3*i+2],
+ dst[3*i+0], dst[3*i+1], dst[3*i+2]);
+ }
+ return 0;
+ }
+
+ sk_sp<SkImage> image = SkImage::MakeFromEncoded(blob);
+ if (!image) {
+ SkDebugf("Couldn't decode %s as an SkImage or an ICC profile.\n", source_path);
+ return 1;
+ }
+
+ image = image->makeRasterImage();
+ if (!image) {
+ SkDebugf("Converting to raster image failed.\n");
+ return 1;
+ }
+
+ SkPixmap pixmap;
+ if (!image->peekPixels(&pixmap)) {
+ SkDebugf("We really should be able to peek raster pixels.\n");
+ return 1;
+ }
+
+ sk_sp<SkColorSpace> dst_cs = SkColorSpace::Make(dst_profile);
+ if (!dst_cs) {
+ SkDebugf("We can't convert to this destination profile as-is. Coercing it.\n");
+ if (skcms_MakeUsableAsDestinationWithSingleCurve(&dst_profile)) {
+ dst_cs = SkColorSpace::Make(dst_profile);
+ }
+ if (!dst_cs) {
+ SkDebugf("We can't convert to this destination profile at all.\n");
+ return 1;
+ }
+ }
+
+ { // transform with skcms
+ SkColorSpace* src_cs = image->colorSpace() ? image->colorSpace()
+ : sk_srgb_singleton();
+ src_cs->toProfile(&src_profile);
+
+ skcms_PixelFormat fmt;
+ switch (pixmap.colorType()) {
+ case kRGBA_8888_SkColorType: fmt = skcms_PixelFormat_RGBA_8888; break;
+ case kBGRA_8888_SkColorType: fmt = skcms_PixelFormat_BGRA_8888; break;
+ default:
+ SkDebugf("color type %d not yet supported, imgcvt.cpp needs an update.\n",
+ pixmap.colorType());
+ return 1;
+ }
+
+ if (pixmap.alphaType() == kUnpremul_SkAlphaType) {
+ SkDebugf("not premul, that's weird.\n");
+ return 1;
+ }
+ auto alpha = skcms_AlphaFormat_PremulAsEncoded;
+
+ if (pixmap.rowBytes() != (size_t)pixmap.width() * pixmap.info().bytesPerPixel()) {
+ SkDebugf("not a tight pixmap, need a loop here\n");
+ return 1;
+ }
+
+ if (!skcms_Transform(pixmap.addr(), fmt,alpha, &src_profile,
+ pixmap.writable_addr(), fmt,alpha, &dst_profile,
+ pixmap.width() * pixmap.height())) {
+ SkDebugf("skcms_Transform() failed\n");
+ return 1;
+ }
+ pixmap.setColorSpace(dst_cs);
+
+ write_png("transformed-skcms.png", SkImage::MakeRasterCopy(pixmap));
+ }
+
+ { // transform with writePixels()
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(pixmap.info().makeColorSpace(dst_cs));
+ if (!surface) {
+ SkDebugf("couldn't create a surface\n");
+ return 1;
+ }
+
+ surface->writePixels(pixmap, 0,0);
+
+ write_png("transformed-writepixels.png", surface->makeImageSnapshot());
+ }
+
+ { // transform by drawing
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(pixmap.info().makeColorSpace(dst_cs));
+ if (!surface) {
+ SkDebugf("couldn't create a surface\n");
+ return 1;
+ }
+
+ surface->getCanvas()->drawImage(image, 0,0);
+
+ write_png("transformed-draw.png", surface->makeImageSnapshot());
+ }
+
+ return 0;
+}
diff --git a/src/third_party/skia/tools/imgslice.cpp b/src/third_party/skia/tools/imgslice.cpp
deleted file mode 100644
index 51aeef7..0000000
--- a/src/third_party/skia/tools/imgslice.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmap.h"
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkImage.h"
-#include "SkStream.h"
-
-DEFINE_bool(header, false, "Print an extra row of the min-max values");
-DEFINE_string2(label, l, "label", "Label printed as the first value");
-
-DEFINE_string2(image, i, "", "Input image");
-DEFINE_int32_2(row, r, -1, "Row to extract");
-DEFINE_int32_2(column, c, -1, "Column to extract");
-
-DEFINE_int32_2(min, n, 0, "Minimum row/column to extract - inclusive");
-DEFINE_int32_2(max, m, 100, "Maximum row/column to extract - inclusive");
-
-DEFINE_int32(rgb, 0, "Color channel to print (0->b, 1->g, 2->r, 3->a)");
-
-DEFINE_bool2(quiet, q, false, "Quiet");
-DEFINE_bool2(reverse, v, false, "Iterate from max to min");
-
-
-// This tool just loads a single image and prints out a comma-separated row or column
-// Return codes:
-static const int kSuccess = 0;
-static const int kError = 1;
-
-int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Print out a row or column of an image.");
- SkCommandLineFlags::Parse(argc, argv);
-
- if (FLAGS_rgb > 3 || FLAGS_rgb < 0) {
- if (!FLAGS_quiet) {
- SkDebugf("Channel (--rgb) must be between 0 and 3 (inclusive) - value is %d.\n",
- FLAGS_rgb);
- }
- return kError;
- }
-
- if (FLAGS_row >= 0 && FLAGS_column >= 0) {
- if (!FLAGS_quiet) {
- SkDebugf("Only one of '-c' or '-r' can be specified at at time.\n");
- }
- return kError;
- }
-
- if (FLAGS_row < 0 && FLAGS_column < 0) {
- if (!FLAGS_quiet) {
- SkDebugf("At least one of '-c' or '-r' need to be specified.\n");
- }
- return kError;
- }
-
- sk_sp<SkData> data(SkData::MakeFromFileName(FLAGS_image[0]));
- if (nullptr == data) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't open file: %s\n", FLAGS_image[0]);
- }
- return kError;
- }
-
- sk_sp<SkImage> image(SkImage::MakeFromEncoded(data));
- if (!image) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't create image for: %s.\n", FLAGS_image[0]);
- }
- return kError;
- }
-
- SkBitmap bitmap;
- if (!image->asLegacyBitmap(&bitmap, SkImage::kRW_LegacyBitmapMode)) {
- if (!FLAGS_quiet) {
- SkDebugf("Couldn't create bitmap for: %s.\n", FLAGS_image[0]);
- }
- return kError;
- }
-
- int top, bottom, left, right;
-
- if (-1 != FLAGS_row) {
- SkASSERT(-1 == FLAGS_column);
-
- top = bottom = SkTPin(FLAGS_row, 0, bitmap.height()-1);
- FLAGS_min = left = SkTPin(FLAGS_min, 0, bitmap.width()-1);
- FLAGS_max = right = SkTPin(FLAGS_max, left, bitmap.width()-1);
- } else {
- SkASSERT(-1 != FLAGS_column);
- left = right = SkTPin(FLAGS_column, 0, bitmap.width()-1);
- FLAGS_min = top = SkTPin(FLAGS_min, 0, bitmap.height()-1);
- FLAGS_max = bottom = SkTPin(FLAGS_max, top, bitmap.height()-1);
- }
-
- if (FLAGS_header) {
- SkDebugf("header");
- if (FLAGS_reverse) {
- for (int i = FLAGS_max; i >= FLAGS_min; --i) {
- SkDebugf(", %d", i);
- }
- } else {
- for (int i = FLAGS_min; i <= FLAGS_max; ++i) {
- SkDebugf(", %d", i);
- }
- }
- SkDebugf("\n");
- }
-
- SkDebugf("%s", FLAGS_label[0]);
- if (FLAGS_reverse) {
- for (int y = bottom; y >= top; --y) {
- for (int x = right; x >= left; --x) {
- SkColor c = bitmap.getColor(x, y);
-
- SkDebugf(", %d", ((c) >> (FLAGS_rgb*8)) & 0xFF);
- }
- }
- } else {
- for (int y = top; y <= bottom; ++y) {
- for (int x = left; x <= right; ++x) {
- SkColor c = bitmap.getColor(x, y);
-
- SkDebugf(", %d", ((c) >> (FLAGS_rgb*8)) & 0xFF);
- }
- }
- }
-
- SkDebugf("\n");
-
- return kSuccess;
-}
diff --git a/src/third_party/skia/tools/infra/__init__.py b/src/third_party/skia/tools/infra/__init__.py
new file mode 100644
index 0000000..d5cf199
--- /dev/null
+++ b/src/third_party/skia/tools/infra/__init__.py
@@ -0,0 +1,4 @@
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/src/third_party/skia/tools/infra/git.py b/src/third_party/skia/tools/infra/git.py
new file mode 100644
index 0000000..cc51d42
--- /dev/null
+++ b/src/third_party/skia/tools/infra/git.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import subprocess
+import sys
+
+
+GIT = 'git.bat' if sys.platform == 'win32' else 'git'
+
+
+def git(*args):
+ '''Run the given Git command, return the output.'''
+ return subprocess.check_output([GIT]+list(args))
diff --git a/src/third_party/skia/tools/infra/go.py b/src/third_party/skia/tools/infra/go.py
new file mode 100644
index 0000000..213fc75
--- /dev/null
+++ b/src/third_party/skia/tools/infra/go.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import os
+import subprocess
+import sys
+
+
+INFRA_GO = 'go.skia.org/infra'
+WHICH = 'where' if sys.platform == 'win32' else 'which'
+
+
+def check():
+ '''Verify that golang is properly installed. If not, exit with an error.'''
+ def _fail(msg):
+ print >> sys.stderr, msg
+ sys.exit(1)
+
+ try:
+ go_exe = subprocess.check_output([WHICH, 'go'])
+ except (subprocess.CalledProcessError, OSError):
+ go_exe = None
+ if not go_exe:
+ _fail('Unable to find Golang installation; see '
+ 'https://golang.org/doc/install')
+ if not os.environ.get('GOPATH'):
+ _fail('GOPATH environment variable is not set; is Golang properly '
+ 'installed?')
+ go_bin = os.path.join(os.environ['GOPATH'], 'bin')
+ for entry in os.environ.get('PATH', '').split(os.pathsep):
+ if entry == go_bin:
+ break
+ else:
+ _fail('%s not in PATH; is Golang properly installed?' % go_bin)
+
+
+def get(url):
+ '''Clone or update the given repo URL via "go get".'''
+ check()
+ subprocess.check_call(['go', 'get', '-u', url])
+
+
+def update_infra():
+ '''Update the local checkout of the Skia infra codebase.'''
+ get(INFRA_GO + '/...')
diff --git a/src/third_party/skia/tools/install_dependencies.sh b/src/third_party/skia/tools/install_dependencies.sh
index fd5c366..b011545 100755
--- a/src/third_party/skia/tools/install_dependencies.sh
+++ b/src/third_party/skia/tools/install_dependencies.sh
@@ -23,17 +23,20 @@
if command -v lsb_release > /dev/null ; then
case $(lsb_release -i -s) in
- Ubuntu)
+ Ubuntu|Debian)
PACKAGES=$(cat<<-EOF
build-essential
freeglut3-dev
libfontconfig-dev
libfreetype6-dev
libgif-dev
+ libgl1-mesa-dev
libglu1-mesa-dev
- libosmesa6-dev
- libpng12-dev
- libqt4-dev
+ libharfbuzz-dev
+ libicu-dev
+ libjpeg-dev
+ libpng-dev
+ libwebp-dev
EOF
)
if [ $(lsb_release -r -s) = '14.04' ] ; then
diff --git a/src/third_party/skia/tools/ios_utils.h b/src/third_party/skia/tools/ios_utils.h
index 0287dc1..579da07 100644
--- a/src/third_party/skia/tools/ios_utils.h
+++ b/src/third_party/skia/tools/ios_utils.h
@@ -14,7 +14,7 @@
// cd into the current app's Documents/ directory.
// (This is the only directory we can easily read and write.)
- void cd_Documents();
+ void cd_Documents(void);
#if defined(__cplusplus)
}
diff --git a/src/third_party/skia/tools/ios_utils.m b/src/third_party/skia/tools/ios_utils.m
index b88ab5b..faef5c5 100644
--- a/src/third_party/skia/tools/ios_utils.m
+++ b/src/third_party/skia/tools/ios_utils.m
@@ -6,7 +6,7 @@
*/
#import <Foundation/Foundation.h>
-#include "ios_utils.h"
+#include "tools/ios_utils.h"
#include <unistd.h>
void cd_Documents() {
diff --git a/src/third_party/skia/tools/jsondiff.py b/src/third_party/skia/tools/jsondiff.py
index 91e3e4b..ed4731a 100755
--- a/src/third_party/skia/tools/jsondiff.py
+++ b/src/third_party/skia/tools/jsondiff.py
@@ -130,7 +130,8 @@
if results_of_this_type:
for test_name in results_of_this_type.keys():
digest_pair = results_of_this_type[test_name]
- if digest_pair[0] != gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5:
+ if (digest_pair[0] !=
+ gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5):
raise ValueError(
'test %s has unsupported hashtype %s' % (
test_name, digest_pair[0]))
@@ -138,7 +139,7 @@
return result_dict
def _DictionaryDiff(self, old_dict, new_dict):
- """Generate a dictionary showing the diffs between old_dict and new_dict.
+ """Generate a dictionary showing diffs between old_dict and new_dict.
Any entries which are identical across them will be left out."""
diff_dict = {}
all_keys = set(old_dict.keys() + new_dict.keys())
@@ -158,8 +159,9 @@
If newfile is not specified, then 'new' is the actual results within
oldfile.
"""
- return self.GenerateDiffDictFromStrings(self._GetFileContentsAsString(oldfile),
- self._GetFileContentsAsString(newfile))
+ return self.GenerateDiffDictFromStrings(
+ self._GetFileContentsAsString(oldfile),
+ self._GetFileContentsAsString(newfile))
def GenerateDiffDictFromStrings(self, oldjson, newjson=None):
"""Generate a dictionary showing the diffs:
diff --git a/src/third_party/skia/tools/list_gms.cpp b/src/third_party/skia/tools/list_gms.cpp
new file mode 100644
index 0000000..6c3ebc5
--- /dev/null
+++ b/src/third_party/skia/tools/list_gms.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "gm/gm.h"
+
+int main() {
+ std::vector<std::string> gms;
+ for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
+ std::unique_ptr<skiagm::GM> gm(factory());
+ gms.push_back(std::string(gm->getName()));
+ }
+ std::sort(gms.begin(), gms.end());
+ for (const std::string& gm : gms) {
+ std::cout << gm << '\n';
+ }
+}
diff --git a/src/third_party/skia/tools/list_gpu_unit_tests.cpp b/src/third_party/skia/tools/list_gpu_unit_tests.cpp
new file mode 100644
index 0000000..a39a5f4
--- /dev/null
+++ b/src/third_party/skia/tools/list_gpu_unit_tests.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "tests/Test.h"
+
+int main() {
+ std::vector<std::string> tests;
+ for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
+ if (test.needsGpu) {
+ tests.push_back(std::string(test.name));
+ }
+ }
+ std::sort(tests.begin(), tests.end());
+ for (const std::string& test : tests) {
+ std::cout << test << '\n';
+ }
+}
diff --git a/src/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html b/src/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html
new file mode 100644
index 0000000..746c0bc
--- /dev/null
+++ b/src/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Lottie-Web Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+ <main>
+ <canvas id=canvas width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ (function () {
+ const PATH = '/res/lottie.json';
+ const RENDERER = 'canvas';
+ const MAX_FRAMES = 25;
+ const MAX_LOOPS = 3;
+
+ const cvs = document.getElementById("canvas");
+ const canvasContext = cvs.getContext('2d');
+
+ // Get total number of frames of the animation from the hash.
+ const hash = window.location.hash;
+ const totalFrames = hash.slice(1);
+ console.log("Lottie has " + totalFrames + "total frames");
+
+ // Load the animation with autoplay false. We will control which
+ // frame to seek to and then will measure performance.
+ let anim = lottie.loadAnimation({
+ container: document.querySelector('.anim'),
+ renderer: RENDERER,
+ loop: false,
+ autoplay: false,
+ path: PATH,
+ rendererSettings: {
+ context: canvasContext,
+ scaleMode: 'noScale',
+ clearCanvas: true,
+ preserveAspectRatio:'xMidYMid meet',
+ },
+ });
+
+ const t_rate = 1.0 / (MAX_FRAMES - 1);
+ let frame = 0;
+ let loop = 0;
+ const drawFrame = () => {
+ if (frame >= MAX_FRAMES) {
+ // Reached the end of one loop.
+ loop++;
+ if (loop == MAX_LOOPS) {
+ // These are global variables to talk with puppeteer.
+ window._lottieWebDone = true;
+ return;
+ }
+ // Reset frame to restart the loop.
+ frame = 0;
+ }
+
+ let t1 = Math.max(Math.min(t_rate * frame, 1.0), 0.0);
+ let seekToFrame = totalFrames * t1;
+ if (seekToFrame >= totalFrames-1) {
+ // bodymovin player sometimes draws blank when requesting
+ // to draw the very last frame. Subtracting a small value
+ // seems to fix this and make it draw the last frame.
+ seekToFrame -= .001;
+ }
+
+ anim.goToAndStop(seekToFrame, true /* isFrame */);
+ console.log("Used seek: " + (seekToFrame/totalFrames));
+ frame++;
+ window.requestAnimationFrame(drawFrame);
+ };
+ window.requestAnimationFrame(drawFrame);
+ })();
+ </script>
+</body>
+</html>
diff --git a/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html b/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html
new file mode 100644
index 0000000..88cc992
--- /dev/null
+++ b/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Lottie-Web Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+ <main>
+ <div style="width:1000px;height:1000px" class=anim></div>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ (function () {
+ const PATH = '/res/lottie.json';
+ const RENDERER = 'svg';
+ const MAX_FRAMES = 25;
+ const MAX_LOOPS = 5;
+
+ // Get total number of frames of the animation from the hash.
+ const hash = window.location.hash;
+ const totalFrames = hash.slice(1);
+ console.log("Lottie has " + totalFrames + "total frames");
+
+ // Load the animation with autoplay false. We will control which
+ // frame to seek to and then will measure performance.
+ let anim = lottie.loadAnimation({
+ container: document.querySelector('.anim'),
+ renderer: RENDERER,
+ loop: false,
+ autoplay: false,
+ path: PATH,
+ rendererSettings: {
+ preserveAspectRatio:'xMidYMid meet'
+ },
+ });
+
+ const t_rate = 1.0 / (MAX_FRAMES - 1);
+ let frame = 0;
+ let loop = 0;
+ const drawFrame = () => {
+ if (frame >= MAX_FRAMES) {
+ // Reached the end of one loop.
+ loop++;
+ if (loop == MAX_LOOPS) {
+ // These are global variables to talk with puppeteer.
+ window._lottieWebDone = true;
+ return;
+ }
+ // Reset frame to restart the loop.
+ frame = 0;
+ }
+
+ let t1 = Math.max(Math.min(t_rate * frame, 1.0), 0.0);
+ let seekToFrame = totalFrames * t1;
+ if (seekToFrame >= totalFrames-1) {
+ // bodymovin player sometimes draws blank when requesting
+ // to draw the very last frame. Subtracting a small value
+ // seems to fix this and make it draw the last frame.
+ seekToFrame -= .001;
+ }
+
+ anim.goToAndStop(seekToFrame, true /* isFrame */);
+ console.log("Used seek: " + (seekToFrame/totalFrames));
+ frame++;
+ window.requestAnimationFrame(drawFrame);
+ };
+ window.requestAnimationFrame(drawFrame);
+ })();
+ </script>
+</body>
+</html>
diff --git a/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.js b/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.js
new file mode 100644
index 0000000..3321cf6
--- /dev/null
+++ b/src/third_party/skia/tools/lottie-web-perf/lottie-web-perf.js
@@ -0,0 +1,184 @@
+/**
+ * Command line application to run Lottie-Web perf on a Lottie file in the
+ * browser and then exporting that result.
+ *
+ */
+const puppeteer = require('puppeteer');
+const express = require('express');
+const fs = require('fs');
+const commandLineArgs = require('command-line-args');
+const commandLineUsage= require('command-line-usage');
+const fetch = require('node-fetch');
+
+const opts = [
+ {
+ name: 'input',
+ typeLabel: '{underline file}',
+ description: 'The Lottie JSON file to process.'
+ },
+ {
+ name: 'output',
+ typeLabel: '{underline file}',
+ description: 'The perf file to write. Defaults to perf.json',
+ },
+ {
+ name: 'use_gpu',
+ description: 'Whether we should run in non-headless mode with GPU.',
+ type: Boolean,
+ },
+ {
+ name: 'port',
+ description: 'The port number to use, defaults to 8081.',
+ type: Number,
+ },
+ {
+ name: 'lottie_player',
+ description: 'The path to lottie.min.js, defaults to a local npm install location.',
+ type: String,
+ },
+ {
+ name: 'backend',
+ description: 'Which lottie-web backend to use. Options: canvas or svg.',
+ type: String,
+ },
+ {
+ name: 'help',
+ alias: 'h',
+ type: Boolean,
+ description: 'Print this usage guide.'
+ },
+];
+
+const usage = [
+ {
+ header: 'Lottie-Web Perf',
+ content: 'Command line application to run Lottie-Web perf.',
+ },
+ {
+ header: 'Options',
+ optionList: opts,
+ },
+];
+
+// Parse and validate flags.
+const options = commandLineArgs(opts);
+
+if (options.backend != 'canvas' && options.backend != 'svg') {
+ console.error('You must supply a lottie-web backend (canvas, svg).');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+if (!options.output) {
+ options.output = 'perf.json';
+}
+if (!options.port) {
+ options.port = 8081;
+}
+if (!options.lottie_player) {
+ options.lottie_player = 'node_modules/lottie-web/build/player/lottie.min.js';
+}
+
+if (options.help) {
+ console.log(commandLineUsage(usage));
+ process.exit(0);
+}
+
+if (!options.input) {
+ console.error('You must supply a Lottie JSON filename.');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+// Start up a web server to serve the three files we need.
+let lottieJS = fs.readFileSync(options.lottie_player, 'utf8');
+let lottieJSON = fs.readFileSync(options.input, 'utf8');
+let driverHTML;
+if (options.backend == 'svg') {
+ console.log('Using lottie-web-perf.html');
+ driverHTML = fs.readFileSync('lottie-web-perf.html', 'utf8');
+} else {
+ console.log('Using lottie-web-canvas-perf.html');
+ driverHTML = fs.readFileSync('lottie-web-canvas-perf.html', 'utf8');
+}
+
+// Find number of frames from the lottie JSON.
+let lottieJSONContent = JSON.parse(lottieJSON);
+const totalFrames = lottieJSONContent.op - lottieJSONContent.ip;
+console.log('Total frames: ' + totalFrames);
+
+const app = express();
+app.get('/', (req, res) => res.send(driverHTML));
+app.get('/res/lottie.js', (req, res) => res.send(lottieJS));
+app.get('/res/lottie.json', (req, res) => res.send(lottieJSON));
+app.listen(options.port, () => console.log('- Local web server started.'))
+
+// Utility function.
+async function wait(ms) {
+ await new Promise(resolve => setTimeout(() => resolve(), ms));
+ return ms;
+}
+
+const targetURL = "http://localhost:" + options.port + "/#" + totalFrames;
+const viewPort = {width: 1000, height: 1000};
+
+// Drive chrome to load the web page from the server we have running.
+async function driveBrowser() {
+ console.log('- Launching chrome for ' + options.input);
+ let browser;
+ let page;
+ const headless = !options.use_gpu;
+ let browser_args = [
+ '--no-sandbox',
+ '--disable-setuid-sandbox',
+ '--window-size=' + viewPort.width + ',' + viewPort.height,
+ ];
+ if (options.use_gpu) {
+ browser_args.push('--ignore-gpu-blacklist');
+ browser_args.push('--ignore-gpu-blocklist');
+ browser_args.push('--enable-gpu-rasterization');
+ }
+ console.log("Running with headless: " + headless + " args: " + browser_args);
+ try {
+ browser = await puppeteer.launch({headless: headless, args: browser_args});
+ page = await browser.newPage();
+ await page.setViewport(viewPort);
+ } catch (e) {
+ console.log('Could not open the browser.', e);
+ process.exit(1);
+ }
+
+ console.log("Loading " + targetURL);
+ try {
+ // Start trace.
+ await page.tracing.start({
+ path: options.output,
+ screenshots: false,
+ categories: ["blink", "cc", "gpu"]
+ });
+
+ await page.goto(targetURL, {
+ timeout: 60000,
+ waitUntil: 'networkidle0'
+ });
+
+ console.log('- Waiting 60s for run to be done.');
+ await page.waitForFunction('window._lottieWebDone === true', {
+ timeout: 60000,
+ });
+
+ // Stop trace.
+ await page.tracing.stop();
+ } catch(e) {
+ console.log('Timed out while loading or drawing. Either the JSON file was ' +
+ 'too big or hit a bug in the player.', e);
+ await browser.close();
+ process.exit(1);
+ }
+
+ await browser.close();
+ // Need to call exit() because the web server is still running.
+ process.exit(0);
+}
+
+driveBrowser();
diff --git a/src/third_party/skia/tools/lottie-web-perf/package.json b/src/third_party/skia/tools/lottie-web-perf/package.json
new file mode 100644
index 0000000..5a4aaaf
--- /dev/null
+++ b/src/third_party/skia/tools/lottie-web-perf/package.json
@@ -0,0 +1,10 @@
+{
+ "dependencies": {
+ "command-line-args": "^5.0.2",
+ "command-line-usage": "^5.0.3",
+ "express": "^4.16.3",
+ "lottie-web": "5.5.5",
+ "node-fetch": "^2.2.0",
+ "puppeteer": "~1.17.0"
+ }
+}
diff --git a/src/third_party/skia/tools/lottiecap/README.md b/src/third_party/skia/tools/lottiecap/README.md
new file mode 100644
index 0000000..79ed953
--- /dev/null
+++ b/src/third_party/skia/tools/lottiecap/README.md
@@ -0,0 +1,29 @@
+Capture Lottie Filmstrip in the Browser
+=======================================
+
+Command line application to build a 5x5 filmstrip
+from a Lottie file in the browser and then export
+that filmstrip in a 1000x1000 PNG.
+
+First run
+
+ $ npm install
+
+Then run
+
+ $ node ./lottiecap.js --input some_lottie_file.js
+
+To get more help:
+
+ $ node ./lottiecap.js -h
+
+Requirements
+------------
+
+You need to have a recent version of 'node' installed, i.e. version v8.9 or
+later. Get recent versions of Node from:
+
+ https://nodejs.org/en/download/
+
+It is doubtful that your workstation's distribution has a recent version of
+Node available.
diff --git a/src/third_party/skia/tools/lottiecap/driver.html b/src/third_party/skia/tools/lottiecap/driver.html
new file mode 100644
index 0000000..2b6dc94
--- /dev/null
+++ b/src/third_party/skia/tools/lottiecap/driver.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Lottie Filmstrip Capture</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body,
+ main,
+ .anim {
+ margin: 0;
+ padding: 0;
+ }
+
+ main {
+ display: flex;
+ width: 1000px;
+ height: 1000px;
+ flex-flow: row wrap;
+ }
+ </style>
+</head>
+<body>
+ <main>
+ <div class=anim></div>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ (function () {
+ const TILE_COUNT = 5; // Number of tiles in x or y direction.
+ const TARGET_SIZE = 1000; // Image size in pixels both x and y direction.
+ const PATH = '/lottie.json';
+
+ let renderer = 'svg';
+ let hash = window.location.hash;
+ if (hash) {
+ renderer = hash.slice(1);
+ }
+
+ // This global is used by puppeteer to determine if all tiles have finished drawing.
+ window._tileCount = 0;
+
+ // First load the animation for just a single tile
+ // so we can read out some values and calculate what
+ // the filmstrip should look like.
+ let anim = lottie.loadAnimation({
+ container: document.querySelector('.anim'),
+ renderer: renderer,
+ loop: false,
+ autoplay: true,
+ path: PATH,
+ rendererSettings: {
+ preserveAspectRatio:'xMidYMid meet'
+ },
+ });
+
+ anim.addEventListener('data_ready', (e) => {
+ // Once the first tile is loaded, calculate what
+ // the filmstrip should look like.
+ let animationData = anim.animationData;
+ let totalFrames = anim.totalFrames;
+ // t_rate mimics DMSrcSink.cpp::SkottieSrc::draw
+ let t_rate = 1.0 / (TILE_COUNT * TILE_COUNT - 1);
+
+ let main = document.querySelector('main');
+
+ // Clear out the first div now that our measurements are done.
+ main.firstElementChild.remove();
+
+ // Add in all the tiles.
+ for (let i = 0; i < TILE_COUNT*TILE_COUNT; i++) {
+ let div = document.createElement('div');
+ div.classList.add('anim');
+ div.style.width = (TARGET_SIZE / TILE_COUNT) + 'px';
+ div.style.height = (TARGET_SIZE / TILE_COUNT) + 'px';
+ main.appendChild(div);
+
+ // create a new animation for each tile. It is tempting to try having
+ // one animation and "clone" each frame, but that doesn't work
+ // because of how bodymovin cleans up the URLObjects that are the path
+ // data for the svgs.
+ // We can re-use the animationData to avoid having to hit the
+ // (local) network a bunch of times.
+ let anim = lottie.loadAnimation({
+ container: div,
+ renderer: renderer,
+ loop: false,
+ autoplay: false,
+ animationData: animationData,
+ rendererSettings: {
+ preserveAspectRatio:'xMidYMid meet'
+ },
+ });
+
+ let t = Math.max(Math.min(t_rate * i, 1.0), 0.0);
+ let seekToFrame = totalFrames * t;
+ if (seekToFrame >= totalFrames) {
+ // bodymovin player sometimes draws blank when requesting
+ // to draw the very last frame. Subtracting a small value
+ // seems to fix this and make it draw the last frame.
+ seekToFrame -= .001;
+ }
+
+ // don't need to wait for data_ready because it's instantly ready.
+ console.log(`t = ${t}, go to frame ${seekToFrame}`);
+ anim.goToAndStop(seekToFrame, true);
+ window._tileCount += 1;
+ }
+ });
+ })();
+ </script>
+</body>
+</html>
diff --git a/src/third_party/skia/tools/lottiecap/lottiecap.js b/src/third_party/skia/tools/lottiecap/lottiecap.js
new file mode 100644
index 0000000..ba8123a
--- /dev/null
+++ b/src/third_party/skia/tools/lottiecap/lottiecap.js
@@ -0,0 +1,218 @@
+/**
+ * Command line application to build a 5x5 filmstrip from a Lottie file in the
+ * browser and then exporting that filmstrip in a 1000x1000 PNG.
+ *
+ */
+const puppeteer = require('puppeteer');
+const express = require('express');
+const fs = require('fs');
+const commandLineArgs = require('command-line-args');
+const commandLineUsage= require('command-line-usage');
+const fetch = require('node-fetch');
+
+// Valid values for the --renderer flag.
+const RENDERERS = ['svg', 'canvas'];
+
+const opts = [
+ {
+ name: 'input',
+ typeLabel: '{underline file}',
+ description: 'The Lottie JSON file to process.'
+ },
+ {
+ name: 'output',
+ typeLabel: '{underline file}',
+ description: 'The captured filmstrip PNG file to write. Defaults to filmstrip.png',
+ },
+ {
+ name: 'renderer',
+ typeLabel: '{underline mode}',
+ description: 'Which renderer to use, "svg" or "canvas". Defaults to "svg".',
+ },
+ {
+ name: 'port',
+ description: 'The port number to use, defaults to 8081.',
+ type: Number,
+ },
+ {
+ name: 'lottie_player',
+ description: 'The path to lottie.min.js, defaults to a local npm install location.',
+ type: String,
+ },
+ {
+ name: 'post_to',
+ description: 'If set, the url to post results to for Gold Ingestion.',
+ type: String,
+ },
+ {
+ name: 'in_docker',
+ description: 'Is this being run in docker, defaults to false',
+ type: Boolean,
+ },
+ {
+ name: 'skip_automation',
+ description: 'If the automation of the screenshot taking should be skipped ' +
+ '(e.g. debugging). Defaults to false.',
+ type: Boolean,
+ },
+ {
+ name: 'help',
+ alias: 'h',
+ type: Boolean,
+ description: 'Print this usage guide.'
+ },
+];
+
+const usage = [
+ {
+ header: 'Lottie Filmstrip Capture',
+ content: `Command line application to build a 5x5 filmstrip
+from a Lottie file in the browser and then export
+that filmstrip in a 1000x1000 PNG.`
+ },
+ {
+ header: 'Options',
+ optionList: opts,
+ },
+];
+
+// Parse and validate flags.
+const options = commandLineArgs(opts);
+
+if (!options.output) {
+ options.output = 'filmstrip.png';
+}
+if (!options.port) {
+ options.port = 8081;
+}
+if (!options.lottie_player) {
+ options.lottie_player = 'node_modules/lottie-web/build/player/lottie.min.js';
+}
+
+if (options.help) {
+ console.log(commandLineUsage(usage));
+ process.exit(0);
+}
+
+if (!options.input) {
+ console.error('You must supply a Lottie JSON filename.');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+if (!options.renderer) {
+ options.renderer = 'svg';
+}
+
+if (!RENDERERS.includes(options.renderer)) {
+ console.error('The --renderer flag must have as a value one of: ', RENDERERS);
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+// Start up a web server to serve the three files we need.
+let lottieJS = fs.readFileSync(options.lottie_player, 'utf8');
+let driverHTML = fs.readFileSync('driver.html', 'utf8');
+let lottieJSON = fs.readFileSync(options.input, 'utf8');
+
+const app = express();
+app.get('/', (req, res) => res.send(driverHTML));
+app.get('/lottie.js', (req, res) => res.send(lottieJS));
+app.get('/lottie.json', (req, res) => res.send(lottieJSON));
+app.listen(options.port, () => console.log('- Local web server started.'))
+
+// Utiltity function.
+async function wait(ms) {
+ await new Promise(resolve => setTimeout(() => resolve(), ms));
+ return ms;
+}
+
+const targetURL = `http://localhost:${options.port}/#${options.renderer}`;
+
+// Drive chrome to load the web page from the server we have running.
+async function driveBrowser() {
+ console.log('- Launching chrome in headless mode.');
+ let browser = null;
+ if (options.in_docker) {
+ browser = await puppeteer.launch({
+ 'executablePath': '/usr/bin/google-chrome-stable',
+ 'args': ['--no-sandbox'],
+ });
+ } else {
+ browser = await puppeteer.launch();
+ }
+
+ const page = await browser.newPage();
+ console.log(`- Loading our Lottie exercising page for ${options.input}.`);
+ try {
+ // 20 seconds is plenty of time to wait for the json to be loaded once
+ // This usually times out for super large json.
+ await page.goto(targetURL, {
+ timeout: 20000,
+ waitUntil: 'networkidle0'
+ });
+ // 20 seconds is plenty of time to wait for the frames to be drawn.
+ // This usually times out for json that causes errors in the player.
+ console.log('- Waiting 15s for all the tiles to be drawn.');
+ await page.waitForFunction('window._tileCount === 25', {
+ timeout: 20000,
+ });
+ } catch(e) {
+ console.log('Timed out while loading or drawing. Either the JSON file was ' +
+ 'too big or hit a bug in the player.', e);
+ await browser.close();
+ process.exit(0);
+ }
+
+ console.log('- Taking screenshot.');
+ let encoding = 'binary';
+ if (options.post_to) {
+ encoding = 'base64';
+ // prevent writing the image to disk
+ options.output = '';
+ }
+
+ // See https://github.com/GoogleChrome/puppeteer/blob/v1.6.0/docs/api.md#pagescreenshotoptions
+ let result = await page.screenshot({
+ path: options.output,
+ type: 'png',
+ clip: {
+ x: 0,
+ y: 0,
+ width: 1000,
+ height: 1000,
+ },
+ encoding: encoding,
+ });
+
+ if (options.post_to) {
+ console.log(`- Reporting ${options.input} to Gold server ${options.post_to}`);
+ let shortenedName = options.input;
+ let lastSlash = shortenedName.lastIndexOf('/');
+ if (lastSlash !== -1) {
+ shortenedName = shortenedName.slice(lastSlash+1);
+ }
+ await fetch(options.post_to, {
+ method: 'POST',
+ mode: 'no-cors',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ 'data': result,
+ 'test_name': shortenedName,
+ })
+ });
+ }
+
+ await browser.close();
+ // Need to call exit() because the web server is still running.
+ process.exit(0);
+}
+
+if (!options.skip_automation) {
+ driveBrowser();
+} else {
+ console.log(`open ${targetURL} to see the animation.`)
+}
+
diff --git a/src/third_party/skia/tools/lottiecap/package.json b/src/third_party/skia/tools/lottiecap/package.json
new file mode 100644
index 0000000..6bce532
--- /dev/null
+++ b/src/third_party/skia/tools/lottiecap/package.json
@@ -0,0 +1,10 @@
+{
+ "dependencies": {
+ "command-line-args": "^5.0.2",
+ "command-line-usage": "^5.0.3",
+ "express": "^4.16.3",
+ "lottie-web": "5.2.1",
+ "node-fetch": "^2.2.0",
+ "puppeteer": "~1.6.2"
+ }
+}
diff --git a/src/third_party/skia/tools/lua/lua_app.cpp b/src/third_party/skia/tools/lua/lua_app.cpp
index 68e1a8d..0c1723e 100644
--- a/src/third_party/skia/tools/lua/lua_app.cpp
+++ b/src/third_party/skia/tools/lua/lua_app.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "SkLua.h"
-#include "SkGraphics.h"
-#include "SkStream.h"
-#include "SkData.h"
-#include "SkOSFile.h"
+#include "include/core/SkData.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkStream.h"
+#include "include/utils/SkLua.h"
+#include "src/core/SkOSFile.h"
#include <stdlib.h>
diff --git a/src/third_party/skia/tools/lua/lua_pictures.cpp b/src/third_party/skia/tools/lua/lua_pictures.cpp
index 85fbd98..faf9be4 100644
--- a/src/third_party/skia/tools/lua/lua_pictures.cpp
+++ b/src/third_party/skia/tools/lua/lua_pictures.cpp
@@ -5,16 +5,15 @@
* found in the LICENSE file.
*/
-#include "SkLua.h"
-#include "SkLuaCanvas.h"
-#include "SkPicture.h"
-#include "SkCommandLineFlags.h"
-#include "SkGraphics.h"
-#include "SkStream.h"
-#include "SkData.h"
-#include "picture_utils.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
+#include "include/core/SkData.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "include/utils/SkLua.h"
+#include "include/utils/SkLuaCanvas.h"
+#include "src/core/SkOSFile.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/flags/CommandLineFlags.h"
#include <stdlib.h>
@@ -64,8 +63,8 @@
}
int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("apply lua script to .skp files.");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::SetUsage("apply lua script to .skp files.");
+ CommandLineFlags::Parse(argc, argv);
if (FLAGS_skpPath.isEmpty()) {
SkDebugf(".skp files or directories are required.\n");
diff --git a/src/third_party/skia/tools/malisc/malisc.py b/src/third_party/skia/tools/malisc/malisc.py
new file mode 100644
index 0000000..d437e61
--- /dev/null
+++ b/src/third_party/skia/tools/malisc/malisc.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import subprocess
+import sys
+
+if len(sys.argv) != 3:
+ print sys.argv[0], ' <compiler> <folder>'
+ sys.exit(1)
+
+compiler = sys.argv[1]
+folder = sys.argv[2]
+
+stats = {}
+
+for filename in os.listdir(folder):
+ basename, ext = os.path.splitext(filename)
+ if ext not in ['.frag', '.spv']:
+ continue
+ cmdline = [compiler]
+ if ext == '.spv':
+ cmdline.extend(['-f', '-p'])
+ cmdline.append(os.path.join(folder, filename))
+ try:
+ output = subprocess.check_output(cmdline)
+ except subprocess.CalledProcessError:
+ continue
+ stats.setdefault(basename, {})
+ for line in output.splitlines():
+ if line.startswith('Instructions Emitted'):
+ inst = line.split(':')[1].split()
+ stats[basename][ext] = inst
+
+for k, v in stats.iteritems():
+ gl = v.get('.frag', ['', '', ''])
+ vk = v.get('.spv', ['', '', ''])
+ print '{0},{1},{2},{3},{4},{5},{6}'.format(k, gl[0], gl[1], gl[2], vk[0], vk[1], vk[2])
diff --git a/src/third_party/skia/tools/mdbviz/Model.cpp b/src/third_party/skia/tools/mdbviz/Model.cpp
new file mode 100644
index 0000000..0243d00
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/Model.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <memory>
+
+#include "tools/mdbviz/Model.h"
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "tools/debugger/DebugCanvas.h"
+
+Model::Model() : fCurOp(0) {
+ SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024);
+ fBM.allocPixels(ii, 0);
+}
+
+Model::~Model() {
+ this->resetOpsTask();
+}
+
+Model::ErrorCode Model::load(const char* filename) {
+ std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(filename);
+ if (!stream) {
+ return ErrorCode::kCouldntOpenFile;
+ }
+ sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
+ if (!pic) {
+ return ErrorCode::kCouldntDecodeSKP;
+ }
+
+ {
+ std::unique_ptr<DebugCanvas> temp(
+ new DebugCanvas(SkScalarCeilToInt(pic->cullRect().width()),
+ SkScalarCeilToInt(pic->cullRect().height())));
+
+ temp->setPicture(pic.get());
+ pic->playback(temp.get());
+ temp->setPicture(nullptr);
+ this->resetOpsTask();
+ temp->detachCommands(&fOps);
+ }
+
+ this->setCurOp(fOps.count()-1);
+
+ return ErrorCode::kOK;
+}
+
+const char* Model::ErrorString(ErrorCode err) {
+ static const char* kStrings[] = {
+ "OK",
+ "Couldn't read file",
+ "Couldn't decode picture"
+ };
+
+ return kStrings[(int)err];
+}
+
+const char* Model::getOpName(int index) const {
+ return DrawCommand::GetCommandString(fOps[index]->getType());
+}
+
+bool Model::isHierarchyPush(int index) const {
+ DrawCommand::OpType type = fOps[index]->getType();
+
+ return DrawCommand::kSave_OpType == type || DrawCommand::kSaveLayer_OpType == type ||
+ DrawCommand::kBeginDrawPicture_OpType == type;
+}
+
+bool Model::isHierarchyPop(int index) const {
+ DrawCommand::OpType type = fOps[index]->getType();
+
+ return DrawCommand::kRestore_OpType == type || DrawCommand::kEndDrawPicture_OpType == type;
+}
+
+void Model::setCurOp(int curOp) {
+ SkASSERT(curOp < fOps.count());
+
+ if (curOp == fCurOp) {
+ return; // the render state is already up to date
+ }
+
+ fCurOp = curOp;
+ this->drawTo(fCurOp);
+}
+
+void Model::drawTo(int index) {
+ SkASSERT(index < fOps.count());
+
+ SkCanvas canvas(fBM);
+
+ int saveCount = canvas.save();
+
+ for (int i = 0; i <= index; ++i) {
+ if (fOps[i]->isVisible()) {
+ fOps[i]->execute(&canvas);
+ }
+ }
+
+ canvas.restoreToCount(saveCount);
+}
+
+void Model::resetOpsTask() {
+ for (int i = 0; i < fOps.count(); ++i) {
+ delete fOps[i];
+ }
+ fOps.reset();
+ fCurOp = 0;
+}
diff --git a/src/third_party/skia/tools/mdbviz/Model.h b/src/third_party/skia/tools/mdbviz/Model.h
new file mode 100644
index 0000000..f3bc99d
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/Model.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkBitmap.h"
+#include "include/private/SkTDArray.h"
+
+class DrawCommand;
+
+// This class encapsulates the both the in-memory representation of the draw ops
+// and the state of Skia/Ganesh's rendering. It should never have any Qt intrusions.
+class Model {
+public:
+ enum class ErrorCode {
+ kOK,
+ kCouldntOpenFile,
+ kCouldntDecodeSKP
+ };
+
+ Model();
+ ~Model();
+
+ static const char* ErrorString(ErrorCode);
+
+ // Replace the list of draw ops by reading the provided skp filename and
+ // reset the Skia draw state. It is up to the view portion to update itself
+ // after this call (i.e., rebuild the opsTask view).
+ ErrorCode load(const char* filename);
+
+ // Update the rendering state to the provided op
+ void setCurOp(int curOp);
+ int curOp() const { return fCurOp; }
+
+ int numOps() const { return fOps.count(); }
+ const char* getOpName(int index) const;
+
+ bool isHierarchyPush(int index) const;
+ bool isHierarchyPop(int index) const;
+
+ // Get the bits visually representing the current rendering state
+ void* getPixels() const { return fBM.getPixels(); }
+ int width() const { return fBM.width(); }
+ int height() const { return fBM.height(); }
+
+protected:
+ // draw the ops up to (and including) the index-th op
+ void drawTo(int index);
+ void resetOpsTask();
+
+private:
+ SkTDArray<DrawCommand*> fOps;
+ int fCurOp; // The current op the rendering state is at
+ SkBitmap fBM;
+};
diff --git a/src/third_party/skia/tools/mdbviz/images/open.png b/src/third_party/skia/tools/mdbviz/images/open.png
new file mode 100644
index 0000000..6043f4b
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/images/open.png
Binary files differ
diff --git a/src/third_party/skia/tools/mdbviz/main.cpp b/src/third_party/skia/tools/mdbviz/main.cpp
new file mode 100644
index 0000000..6679871
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/main.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <QtWidgets>
+
+#include "tools/mdbviz/mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QCoreApplication::setOrganizationName("Google");
+ QCoreApplication::setApplicationName("MDB Viz");
+ QCoreApplication::setApplicationVersion("0.0");
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QCoreApplication::applicationName());
+ parser.addVersionOption();
+ parser.process(app);
+
+ MainWindow mainWin;
+ mainWin.show();
+
+ return app.exec();
+}
+
+
diff --git a/src/third_party/skia/tools/mdbviz/mainwindow.cpp b/src/third_party/skia/tools/mdbviz/mainwindow.cpp
new file mode 100644
index 0000000..e36f81a
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/mainwindow.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <QtWidgets>
+
+#include "MainWindow.h"
+
+MainWindow::MainWindow() {
+ this->createActions();
+ this->createStatusBar();
+ this->createDockWindows();
+
+ this->setWindowTitle("MDB Viz");
+
+ this->readSettings();
+ this->setUnifiedTitleAndToolBarOnMac(true);
+}
+
+void MainWindow::openFile() {
+ QString fileName = QFileDialog::getOpenFileName(this);
+ if (!fileName.isEmpty()) {
+ this->loadFile(fileName);
+ }
+}
+
+void MainWindow::setupOpsTaskWidget() {
+ fOpsTaskWidget->clear();
+
+ QTreeWidgetItem* item = nullptr;
+ SkTDArray<QTreeWidgetItem*> parents;
+
+ for (int i = 0; i < fModel.numOps(); i++) {
+ item = new QTreeWidgetItem();
+
+ item->setText(0, QString::number(i));
+ item->setData(0, Qt::UserRole, i);
+ item->setText(1, fModel.getOpName(i));
+
+ if (fModel.isHierarchyPop(i)) {
+ parents.pop();
+ }
+
+ if (parents.isEmpty()) {
+ fOpsTaskWidget->addTopLevelItem(item);
+ } else {
+ parents.top()->addChild(item);
+ }
+
+ if (fModel.isHierarchyPush(i)) {
+ *parents.push() = item;
+ }
+ }
+
+ fOpsTaskWidget->setCurrentItem(item);
+ fOpsTaskWidget->expandToDepth(100);
+}
+
+void MainWindow::presentCurrentRenderState() {
+ fImage = QImage((uchar*)fModel.getPixels(), fModel.width(), fModel.height(),
+ QImage::Format_RGBA8888);
+ fImageLabel->setPixmap(QPixmap::fromImage(fImage));
+}
+
+void MainWindow::loadFile(const QString &fileName) {
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly | QFile::Text)) {
+ QMessageBox::warning(this, tr("MDB Viz"),
+ tr("Cannot read file %1:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString()));
+ return;
+ }
+
+ QTextStream in(&file);
+#ifndef QT_NO_CURSOR
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+#endif
+
+ std::string str = file.fileName().toLocal8Bit().constData();
+
+ Model::ErrorCode err = fModel.load(str.c_str());
+ if (Model::ErrorCode::kOK != err) {
+ this->statusBar()->showMessage(Model::ErrorString(err));
+ return;
+ }
+
+ this->setupOpsTaskWidget();
+ this->presentCurrentRenderState();
+
+#ifndef QT_NO_CURSOR
+ QApplication::restoreOverrideCursor();
+#endif
+}
+
+
+void MainWindow::about() {
+ QMessageBox::about(this, "About MDB Viz", "Visualize MDB");
+}
+
+void MainWindow::createActions() {
+
+ // File menu
+ QMenu* fileMenu = this->menuBar()->addMenu(tr("&File"));
+ QToolBar* fileToolBar = this->addToolBar(tr("File"));
+
+ const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
+ QAction* openAct = new QAction(openIcon, tr("&Open..."), this);
+ openAct->setShortcuts(QKeySequence::Open);
+ openAct->setStatusTip(tr("Open an existing file"));
+ connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
+ fileMenu->addAction(openAct);
+ fileToolBar->addAction(openAct);
+
+ fileMenu->addSeparator();
+
+ const QIcon exitIcon = QIcon::fromTheme("application-exit");
+ QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
+ exitAct->setShortcuts(QKeySequence::Quit);
+ exitAct->setStatusTip(tr("Exit the application"));
+
+ // View menu
+ fViewMenu = this->menuBar()->addMenu(tr("&View"));
+
+ // Help menu
+ this->menuBar()->addSeparator();
+
+ QMenu* helpMenu = this->menuBar()->addMenu(tr("&Help"));
+
+ QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ aboutAct->setStatusTip(tr("Show the application's About box"));
+}
+
+void MainWindow::onCurrentItemChanged(QTreeWidgetItem* cur, QTreeWidgetItem* /* prev */) {
+ int currentRow = cur->data(0, Qt::UserRole).toInt();
+ fModel.setCurOp(currentRow);
+ this->presentCurrentRenderState();
+}
+
+void MainWindow::createStatusBar() {
+ this->statusBar()->showMessage(tr("Ready"));
+}
+
+void MainWindow::createDockWindows() {
+
+ // Op List Window
+ {
+ QDockWidget* opsTaskDock = new QDockWidget("Ops", this);
+ opsTaskDock->setAllowedAreas(Qt::LeftDockWidgetArea);
+
+ fOpsTaskWidget = new QTreeWidget(opsTaskDock);
+
+ QTreeWidgetItem* headerItem = new QTreeWidgetItem;
+ headerItem->setText(0, "Index");
+ headerItem->setText(1, "Op Name");
+ fOpsTaskWidget->setHeaderItem(headerItem);
+
+ fOpsTaskWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ fOpsTaskWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+
+ opsTaskDock->setWidget(fOpsTaskWidget);
+ this->addDockWidget(Qt::LeftDockWidgetArea, opsTaskDock);
+
+ fViewMenu->addAction(opsTaskDock->toggleViewAction());
+
+ connect(fOpsTaskWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
+ this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+ }
+
+ // Main canvas Window
+ {
+ QDockWidget* mainCanvasDock = new QDockWidget("Main Canvas", this);
+ mainCanvasDock->setAllowedAreas(Qt::RightDockWidgetArea);
+
+ fImageLabel = new QLabel(mainCanvasDock);
+
+ fImage = QImage(1024, 1024, QImage::Format_RGBA8888);
+ fImage.fill(0);
+ fImageLabel->setPixmap(QPixmap::fromImage(fImage));
+
+ mainCanvasDock->setWidget(fImageLabel);
+ this->addDockWidget(Qt::RightDockWidgetArea, mainCanvasDock);
+
+ fViewMenu->addAction(mainCanvasDock->toggleViewAction());
+ }
+}
+
+void MainWindow::readSettings() {
+ QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
+ const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
+ if (geometry.isEmpty()) {
+ const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
+ resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
+ move((availableGeometry.width() - width()) / 2,
+ (availableGeometry.height() - height()) / 2);
+ } else {
+ this->restoreGeometry(geometry);
+ }
+}
+
+void MainWindow::writeSettings() {
+ QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
+ settings.setValue("geometry", this->saveGeometry());
+}
diff --git a/src/third_party/skia/tools/mdbviz/mainwindow.h b/src/third_party/skia/tools/mdbviz/mainwindow.h
new file mode 100644
index 0000000..f80b157
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/mainwindow.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef MainWindow_DEFINED
+#define MainWindow_DEFINED
+
+#include <memory>
+#include <QMainWindow>
+
+#include "tools/mdbviz/Model.h"
+
+class QLabel;
+class QMenu;
+class QTreeWidget;
+class QTreeWidgetItem;
+
+
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+
+public:
+ MainWindow();
+
+private slots:
+ void openFile();
+ void about();
+ void onCurrentItemChanged(QTreeWidgetItem* cur, QTreeWidgetItem* prev);
+
+private:
+ void loadFile(const QString &fileName);
+ void setupOpsTaskWidget();
+ void presentCurrentRenderState();
+
+
+ void createActions();
+ void createStatusBar();
+ void createDockWindows();
+
+ void readSettings();
+ void writeSettings();
+
+ QImage fImage;
+ QLabel* fImageLabel;
+
+ QTreeWidget* fOpsTaskWidget;
+
+ QMenu* fViewMenu;
+
+ Model fModel;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/mdbviz/resources.qrc b/src/third_party/skia/tools/mdbviz/resources.qrc
new file mode 100644
index 0000000..e3e2dc0
--- /dev/null
+++ b/src/third_party/skia/tools/mdbviz/resources.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/open.png</file>
+</qresource>
+</RCC>
\ No newline at end of file
diff --git a/src/third_party/skia/tools/merge_static_libs.py b/src/third_party/skia/tools/merge_static_libs.py
index 842be18..a32c3a5 100755
--- a/src/third_party/skia/tools/merge_static_libs.py
+++ b/src/third_party/skia/tools/merge_static_libs.py
@@ -15,7 +15,7 @@
def MergeLibs(in_libs, out_lib):
""" Merges multiple static libraries into one.
-
+
in_libs: list of paths to static libraries to be merged
out_lib: path to the static library which will be created from in_libs
"""
@@ -38,12 +38,12 @@
proc.wait()
if proc.poll() == 0:
# The static library is non-thin, and we extracted objects
- for object in current_objects:
- objects.append(os.path.abspath(object))
+ for obj in current_objects:
+ objects.append(os.path.abspath(obj))
elif 'thin archive' in proc.communicate()[0]:
# The static library is thin, so it contains the paths to its objects
- for object in current_objects:
- objects.append(object)
+ for obj in current_objects:
+ objects.append(obj)
else:
raise Exception('Failed to extract objects from %s.' % in_lib)
os.chdir(curdir)
diff --git a/src/third_party/skia/tools/mirror-dev.sh b/src/third_party/skia/tools/mirror-dev.sh
index 0512a78..47786de 100755
--- a/src/third_party/skia/tools/mirror-dev.sh
+++ b/src/third_party/skia/tools/mirror-dev.sh
@@ -1,5 +1,9 @@
+# Copyright 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
# For each installed *-dev package DEV
- for DEV in $(dpkg --list | grep '^ii [^ ]' | cut -d ' ' -f 3 | grep '\-dev$')
+ for DEV in $(dpkg --list | grep '^ii [^ ]' | cut -d ' ' -f 3 | grep -P '\-dev($|\:amd64$)')
do
# For each multi-arch *.so SO installed by DEV
for DEV_64_SO in $(dpkg -L $DEV | grep '/lib/x86_64-linux-gnu/.*\.so$')
@@ -10,14 +14,14 @@
echo "$DEV installed $DEV_64_SO which is real."
continue
fi
-
+
DEV_64_TARGET=$(readlink $DEV_64_SO)
- DEV_64_TARGET_FULL=$(readlink -f $DEV_64_SO)
-
+ DEV_64_TARGET_FULL=$(readlink -f $DEV_64_SO)
+
DEV_32_SO=$(echo $DEV_64_SO | sed -e 's@/lib/x86_64-linux-gnu/@/lib/i386-linux-gnu/@')
DEV_32_TARGET=$(echo $DEV_64_TARGET | sed -e 's@/lib/x86_64-linux-gnu/@/lib/i386-linux-gnu/@')
DEV_32_TARGET_FULL=$(echo $DEV_64_TARGET_FULL | sed -e 's@/lib/x86_64-linux-gnu/@/lib/i386-linux-gnu/@')
-
+
# Error if DEV_32_TARGET does not exist.
if ! test -e $DEV_32_TARGET_FULL
then
@@ -27,7 +31,7 @@
#echo " $DEV_32_SO -> $DEV_32_TARGET ($DEV_32_TARGET_FULL)"
continue
fi
-
+
# Create DEV_32_SO
sudo ln -s $DEV_32_TARGET $DEV_32_SO
done
diff --git a/src/third_party/skia/tools/monobench.cpp b/src/third_party/skia/tools/monobench.cpp
deleted file mode 100644
index ff0abc2..0000000
--- a/src/third_party/skia/tools/monobench.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Benchmark.h"
-#include "OverwriteLine.h"
-#include "SkGraphics.h"
-#include "SkSurface.h"
-#include "SkTaskGroup.h"
-#include <algorithm>
-#include <chrono>
-#include <limits>
-#include <regex>
-#include <stdlib.h>
-#include <string>
-#include <vector>
-
-
-#if defined(SK_BUILD_FOR_WIN32)
-static const char* kEllipsis = "...";
-#else
-static const char* kEllipsis = "…";
-#endif
-
-int main(int argc, char** argv) {
- SkGraphics::Init();
- SkTaskGroup::Enabler enabled;
-
- using clock = std::chrono::high_resolution_clock;
- using ns = std::chrono::duration<double, std::nano>;
-
- std::regex pattern;
- int limit = 2147483647;
- if (argc > 1) { pattern = argv[1]; }
- if (argc > 2) { limit = atoi(argv[2]); }
-
- struct Bench {
- std::unique_ptr<Benchmark> b;
- std::string name;
- ns best;
- };
- std::vector<Bench> benches;
-
- for (auto r = BenchRegistry::Head(); r; r = r->next()) {
- std::unique_ptr<Benchmark> bench{ r->factory()(nullptr) };
-
- std::string name = bench->getName();
- if (std::regex_search(name, pattern) &&
- (bench->isSuitableFor(Benchmark::kNonRendering_Backend) ||
- bench->isSuitableFor(Benchmark:: kRaster_Backend))) {
- bench->delayedSetup();
- benches.emplace_back(Bench{std::move(bench), name,
- ns{std::numeric_limits<double>::infinity()}});
- }
- }
-
- if (benches.size() == 0) {
- SkDebugf("No bench matched.\n");
- return 1;
- }
-
- if (benches.size() > 1) {
- int common_prefix = benches[0].name.size();
- for (size_t i = 1; i < benches.size(); i++) {
- int len = std::mismatch(benches[i-1].name.begin(), benches[i-1].name.end(),
- benches[i-0].name.begin())
- .first - benches[i-1].name.begin();
- common_prefix = std::min(common_prefix, len);
- }
- std::string prefix = benches[0].name.substr(0, common_prefix);
- if (common_prefix) {
- for (auto& bench : benches) {
- bench.name.replace(0, common_prefix, kEllipsis);
- }
- }
-
- int common_suffix = benches[0].name.size();
- for (size_t i = 1; i < benches.size(); i++) {
- int len = std::mismatch(benches[i-1].name.rbegin(), benches[i-1].name.rend(),
- benches[i-0].name.rbegin())
- .first - benches[i-1].name.rbegin();
- common_suffix = std::min(common_suffix, len);
- }
- std::string suffix = benches[0].name.substr(benches[0].name.size() - common_suffix);
- if (common_suffix) {
- for (auto& bench : benches) {
- bench.name.replace(bench.name.size() - common_suffix, common_suffix, kEllipsis);
- }
- }
-
- SkDebugf("%s%s%s\n", prefix.c_str(), kEllipsis, suffix.c_str());
- }
-
- int samples = 0;
- while (samples < limit) {
- std::random_shuffle(benches.begin(), benches.end());
- for (auto& bench : benches) {
- sk_sp<SkSurface> dst;
- SkCanvas* canvas = nullptr;
- if (!bench.b->isSuitableFor(Benchmark::kNonRendering_Backend)) {
- dst = SkSurface::MakeRaster(SkImageInfo::MakeS32(bench.b->getSize().x(),
- bench.b->getSize().y(),
- kPremul_SkAlphaType));
- canvas = dst->getCanvas();
- bench.b->perCanvasPreDraw(canvas);
- }
- for (int loops = 1; loops < 1000000000;) {
-
- bench.b->preDraw(canvas);
- auto start = clock::now();
- bench.b->draw(loops, canvas);
- ns elapsed = clock::now() - start;
- bench.b->postDraw(canvas);
-
- if (elapsed < std::chrono::milliseconds{10}) {
- loops *= 2;
- continue;
- }
-
- bench.best = std::min(bench.best, elapsed / loops);
- samples++;
-
- struct Result { const char* name; ns best; };
- std::vector<Result> sorted(benches.size());
- for (size_t i = 0; i < benches.size(); i++) {
- sorted[i].name = benches[i].name.c_str();
- sorted[i].best = benches[i].best;
- }
- std::sort(sorted.begin(), sorted.end(), [](const Result& a, const Result& b) {
- return a.best < b.best;
- });
-
- SkDebugf("%s%d", kSkOverwriteLine, samples);
- for (auto& result : sorted) {
- if (sorted.size() == 1) {
- SkDebugf(" %s %gns" , result.name, result.best.count());
- } else {
- SkDebugf(" %s %.3gx", result.name, result.best / sorted[0].best);
- }
- }
- break;
- }
- if (canvas) {
- bench.b->perCanvasPostDraw(canvas);
- }
- }
- }
-
- return 0;
-}
diff --git a/src/third_party/skia/tools/ok.cpp b/src/third_party/skia/tools/ok.cpp
deleted file mode 100644
index edda9be..0000000
--- a/src/third_party/skia/tools/ok.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// ok is an experimental test harness, maybe to replace DM. Key features:
-// * work is balanced across separate processes for stability and isolation;
-// * ok is entirely opt-in. No more maintaining huge --blacklists.
-
-#include "SkGraphics.h"
-#include "SkImage.h"
-#include "ok.h"
-#include <chrono>
-#include <future>
-#include <list>
-#include <stdio.h>
-#include <stdlib.h>
-#include <thread>
-#include <vector>
-
-#if !defined(__has_include)
- #define __has_include(x) 0
-#endif
-
-static thread_local const char* tls_currently_running = "";
-
-#if __has_include(<execinfo.h>) && __has_include(<fcntl.h>) && __has_include(<signal.h>)
- #include <execinfo.h>
- #include <fcntl.h>
- #include <signal.h>
-
- static int log_fd = 2/*stderr*/;
-
- static void log(const char* msg) {
- write(log_fd, msg, strlen(msg));
- }
-
- static void setup_crash_handler() {
- static void (*original_handlers[32])(int);
- for (int sig : std::vector<int>{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV }) {
- original_handlers[sig] = signal(sig, [](int sig) {
- lockf(log_fd, F_LOCK, 0);
- log("\ncaught signal ");
- switch (sig) {
- #define CASE(s) case s: log(#s); break
- CASE(SIGABRT);
- CASE(SIGBUS);
- CASE(SIGFPE);
- CASE(SIGILL);
- CASE(SIGSEGV);
- #undef CASE
- }
- log(" while running '");
- log(tls_currently_running);
- log("'\n");
-
- void* stack[128];
- int frames = backtrace(stack, sizeof(stack)/sizeof(*stack));
- backtrace_symbols_fd(stack, frames, log_fd);
- lockf(log_fd, F_ULOCK, 0);
-
- signal(sig, original_handlers[sig]);
- raise(sig);
- });
- }
- }
-
- static void defer_logging() {
- log_fd = fileno(tmpfile());
- atexit([] {
- lseek(log_fd, 0, SEEK_SET);
- char buf[1024];
- while (size_t bytes = read(log_fd, buf, sizeof(buf))) {
- write(2, buf, bytes);
- }
- });
- }
-
- void ok_log(const char* msg) {
- lockf(log_fd, F_LOCK, 0);
- log("[");
- log(tls_currently_running);
- log("]\t");
- log(msg);
- log("\n");
- lockf(log_fd, F_ULOCK, 0);
- }
-
-#else
- static void setup_crash_handler() {}
- static void defer_logging() {}
-
- void ok_log(const char* msg) {
- fprintf(stderr, "%s\n", msg);
- }
-#endif
-
-struct Engine {
- virtual ~Engine() {}
- virtual bool spawn(std::function<Status(void)>) = 0;
- virtual Status wait_one() = 0;
-};
-
-struct SerialEngine : Engine {
- Status last = Status::None;
-
- bool spawn(std::function<Status(void)> fn) override {
- last = fn();
- return true;
- }
-
- Status wait_one() override {
- Status s = last;
- last = Status::None;
- return s;
- }
-};
-
-struct ThreadEngine : Engine {
- std::list<std::future<Status>> live;
- const std::chrono::steady_clock::time_point the_past = std::chrono::steady_clock::now();
-
- bool spawn(std::function<Status(void)> fn) override {
- live.push_back(std::async(std::launch::async, fn));
- return true;
- }
-
- Status wait_one() override {
- if (live.empty()) {
- return Status::None;
- }
-
- for (;;) {
- for (auto it = live.begin(); it != live.end(); it++) {
- if (it->wait_until(the_past) == std::future_status::ready) {
- Status s = it->get();
- live.erase(it);
- return s;
- }
- }
- }
- }
-};
-
-#if defined(_MSC_VER)
- using ForkEngine = ThreadEngine;
-#else
- #include <sys/wait.h>
- #include <unistd.h>
-
- struct ForkEngine : Engine {
- bool spawn(std::function<Status(void)> fn) override {
- switch (fork()) {
- case 0: _exit((int)fn());
- case -1: return false;
- default: return true;
- }
- }
-
- Status wait_one() override {
- do {
- int status;
- if (wait(&status) > 0) {
- return WIFEXITED(status) ? (Status)WEXITSTATUS(status)
- : Status::Crashed;
- }
- } while (errno == EINTR);
- return Status::None;
- }
- };
-#endif
-
-struct StreamType {
- const char *name, *help;
- std::unique_ptr<Stream> (*factory)(Options);
-};
-static std::vector<StreamType> stream_types;
-
-struct DstType {
- const char *name, *help;
- std::unique_ptr<Dst> (*factory)(Options);
-};
-static std::vector<DstType> dst_types;
-
-struct ViaType {
- const char *name, *help;
- std::unique_ptr<Dst> (*factory)(Options, std::unique_ptr<Dst>);
-};
-static std::vector<ViaType> via_types;
-
-template <typename T>
-static std::string help_for(std::vector<T> registered) {
- std::string help;
- for (auto r : registered) {
- help += "\n ";
- help += r.name;
- help += ": ";
- help += r.help;
- }
- return help;
-}
-
-int main(int argc, char** argv) {
- SkGraphics::Init();
- setup_crash_handler();
-
- int jobs{1};
- std::unique_ptr<Stream> stream;
- std::function<std::unique_ptr<Dst>(void)> dst_factory = []{
- // A default Dst that's enough for unit tests and not much else.
- struct : Dst {
- Status draw(Src* src) override { return src->draw(nullptr); }
- sk_sp<SkImage> image() override { return nullptr; }
- } dst;
- return move_unique(dst);
- };
-
- auto help = [&] {
- std::string stream_help = help_for(stream_types),
- dst_help = help_for( dst_types),
- via_help = help_for( via_types);
-
- printf("%s [-j N] src[:k=v,...] dst[:k=v,...] [via[:k=v,...] ...] \n"
- " -j: Run at most N processes at any time. \n"
- " If <0, use -N threads instead. \n"
- " If 0, use one thread in one process. \n"
- " If 1 (default) or -1, auto-detect N. \n"
- " src: content to draw%s \n"
- " dst: how to draw that content%s \n"
- " via: wrappers around dst%s \n"
- " Most srcs, dsts and vias have options, e.g. skp:dir=skps sw:ct=565 \n",
- argv[0], stream_help.c_str(), dst_help.c_str(), via_help.c_str());
- return 1;
- };
-
- for (int i = 1; i < argc; i++) {
- if (0 == strcmp("-j", argv[i])) { jobs = atoi(argv[++i]); }
- if (0 == strcmp("-h", argv[i])) { return help(); }
- if (0 == strcmp("--help", argv[i])) { return help(); }
-
- for (auto s : stream_types) {
- size_t len = strlen(s.name);
- if (0 == strncmp(s.name, argv[i], len)) {
- switch (argv[i][len]) {
- case ':': len++;
- case '\0': stream = s.factory(Options{argv[i]+len});
- }
- }
- }
- for (auto d : dst_types) {
- size_t len = strlen(d.name);
- if (0 == strncmp(d.name, argv[i], len)) {
- switch (argv[i][len]) {
- case ':': len++;
- case '\0': dst_factory = [=]{
- return d.factory(Options{argv[i]+len});
- };
- }
- }
- }
- for (auto v : via_types) {
- size_t len = strlen(v.name);
- if (0 == strncmp(v.name, argv[i], len)) {
- if (!dst_factory) { return help(); }
- switch (argv[i][len]) {
- case ':': len++;
- case '\0': dst_factory = [=]{
- return v.factory(Options{argv[i]+len}, dst_factory());
- };
- }
- }
- }
- }
- if (!stream) { return help(); }
-
- std::unique_ptr<Engine> engine;
- if (jobs == 0) { engine.reset(new SerialEngine); }
- if (jobs > 0) { engine.reset(new ForkEngine); defer_logging(); }
- if (jobs < 0) { engine.reset(new ThreadEngine); jobs = -jobs; }
-
- if (jobs == 1) { jobs = std::thread::hardware_concurrency(); }
-
- int ok = 0, failed = 0, crashed = 0, skipped = 0;
-
- auto update_stats = [&](Status s) {
- switch (s) {
- case Status::OK: ok++; break;
- case Status::Failed: failed++; break;
- case Status::Crashed: crashed++; break;
- case Status::Skipped: skipped++; break;
- case Status::None: return;
- }
- const char* leader = "\r";
- auto print = [&](int count, const char* label) {
- if (count) {
- printf("%s%d %s", leader, count, label);
- leader = ", ";
- }
- };
- print(ok, "ok");
- print(failed, "failed");
- print(crashed, "crashed");
- print(skipped, "skipped");
- fflush(stdout);
- };
-
- auto spawn = [&](std::function<Status(void)> fn) {
- if (--jobs < 0) {
- update_stats(engine->wait_one());
- }
- while (!engine->spawn(fn)) {
- update_stats(engine->wait_one());
- }
- };
-
- for (std::unique_ptr<Src> owned = stream->next(); owned; owned = stream->next()) {
- Src* raw = owned.release(); // Can't move std::unique_ptr into a lambda in C++11. :(
- spawn([=] {
- std::unique_ptr<Src> src{raw};
-
- std::string name = src->name();
- tls_currently_running = name.c_str();
-
- return dst_factory()->draw(src.get());
- });
- }
-
- for (Status s = Status::OK; s != Status::None; ) {
- s = engine->wait_one();
- update_stats(s);
- }
- printf("\n");
- return (failed || crashed) ? 1 : 0;
-}
-
-
-Register::Register(const char* name, const char* help,
- std::unique_ptr<Stream> (*factory)(Options)) {
- stream_types.push_back(StreamType{name, help, factory});
-}
-Register::Register(const char* name, const char* help,
- std::unique_ptr<Dst> (*factory)(Options)) {
- dst_types.push_back(DstType{name, help, factory});
-}
-Register::Register(const char* name, const char* help,
- std::unique_ptr<Dst> (*factory)(Options, std::unique_ptr<Dst>)) {
- via_types.push_back(ViaType{name, help, factory});
-}
-
-Options::Options(std::string str) {
- std::string k,v, *curr = &k;
- for (auto c : str) {
- switch(c) {
- case ',': (*this)[k] = v;
- curr = &(k = "");
- break;
- case '=': curr = &(v = "");
- break;
- default: *curr += c;
- }
- }
- (*this)[k] = v;
-}
-
-std::string& Options::operator[](std::string k) { return this->kv[k]; }
-
-std::string Options::operator()(std::string k, std::string fallback) const {
- for (auto it = kv.find(k); it != kv.end(); ) {
- return it->second;
- }
- return fallback;
-}
diff --git a/src/third_party/skia/tools/ok.h b/src/third_party/skia/tools/ok.h
deleted file mode 100644
index f55842b..0000000
--- a/src/third_party/skia/tools/ok.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef ok_DEFINED
-#define ok_DEFINED
-
-#include "SkCanvas.h"
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-
-// Not really ok-specific, but just kind of generally handy.
-template <typename T>
-static std::unique_ptr<T> move_unique(T& v) {
- return std::unique_ptr<T>{new T{std::move(v)}};
-}
-
-void ok_log(const char*);
-
-enum class Status { OK, Failed, Crashed, Skipped, None };
-
-struct Src {
- virtual ~Src() {}
- virtual std::string name() = 0;
- virtual SkISize size() = 0;
- virtual Status draw(SkCanvas*) = 0;
-};
-
-struct Stream {
- virtual ~Stream() {}
- virtual std::unique_ptr<Src> next() = 0;
-};
-
-struct Dst {
- virtual ~Dst() {}
- virtual Status draw(Src*) = 0;
- virtual sk_sp<SkImage> image() = 0;
-};
-
-class Options {
- std::map<std::string, std::string> kv;
-public:
- explicit Options(std::string = "");
- std::string& operator[](std::string k);
- std::string operator()(std::string k, std::string fallback = "") const;
-};
-
-// Create globals to register your new type of Stream or Dst.
-struct Register {
- Register(const char* name, const char* help, std::unique_ptr<Stream> (*factory)(Options));
- Register(const char* name, const char* help, std::unique_ptr<Dst> (*factory)(Options));
- Register(const char* name, const char* help,
- std::unique_ptr<Dst>(*factory)(Options, std::unique_ptr<Dst>));
-};
-
-#endif//ok_DEFINED
diff --git a/src/third_party/skia/tools/ok_dsts.cpp b/src/third_party/skia/tools/ok_dsts.cpp
deleted file mode 100644
index c25a8d5f..0000000
--- a/src/third_party/skia/tools/ok_dsts.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "ok.h"
-#include "SkSurface.h"
-
-struct SWDst : Dst {
- SkImageInfo info;
- sk_sp<SkSurface> surface;
-
- static std::unique_ptr<Dst> Create(Options options) {
- SkImageInfo info = SkImageInfo::MakeN32Premul(0,0);
- if (options("ct") == "565") { info = info.makeColorType(kRGB_565_SkColorType); }
- if (options("ct") == "f16") { info = info.makeColorType(kRGBA_F16_SkColorType); }
-
- if (options("cs") == "srgb") {
- auto cs = info.colorType() == kRGBA_F16_SkColorType ? SkColorSpace::MakeSRGBLinear()
- : SkColorSpace::MakeSRGB();
- info = info.makeColorSpace(std::move(cs));
- }
-
- SWDst dst;
- dst.info = info;
- return move_unique(dst);
- }
-
- Status draw(Src* src) override {
- auto size = src->size();
- surface = SkSurface::MakeRaster(info.makeWH(size.width(), size.height()));
- return src->draw(surface->getCanvas());
- }
-
- sk_sp<SkImage> image() override {
- return surface->makeImageSnapshot();
- }
-};
-static Register sw{"sw", "draw with the software backend", SWDst::Create};
-static Register _8888{"8888", "alias for sw", SWDst::Create};
-
-static Register _565{"565", "alias for sw:ct=565", [](Options options) {
- options["ct"] = "565";
- return SWDst::Create(options);
-}};
-
-static Register srgb{"srgb", "alias for sw:cs=srgb", [](Options options) {
- options["cs"] = "srgb";
- return SWDst::Create(options);
-}};
-
-static Register f16{"f16", "alias for sw:ct=f16,cs=srgb", [](Options options) {
- options["ct"] = "f16";
- options["cs"] = "srgb";
- return SWDst::Create(options);
-}};
-
-extern bool gSkForceRasterPipelineBlitter;
-static Register rp{"rp", "draw forcing SkRasterPipelineBlitter", [](Options options) {
- gSkForceRasterPipelineBlitter = true;
- return SWDst::Create(options);
-}};
diff --git a/src/third_party/skia/tools/ok_srcs.cpp b/src/third_party/skia/tools/ok_srcs.cpp
deleted file mode 100644
index 5630a34..0000000
--- a/src/third_party/skia/tools/ok_srcs.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "ok.h"
-#include "gm.h"
-#include "SkData.h"
-#include "SkOSFile.h"
-#include "SkPicture.h"
-#include <vector>
-
-struct GMStream : Stream {
- const skiagm::GMRegistry* registry = skiagm::GMRegistry::Head();
-
- static std::unique_ptr<Stream> Create(Options) {
- GMStream stream;
- return move_unique(stream);
- }
-
- struct GMSrc : Src {
- skiagm::GM* (*factory)(void*);
- std::unique_ptr<skiagm::GM> gm;
-
- void init() {
- if (gm) { return; }
- gm.reset(factory(nullptr));
- }
-
- std::string name() override {
- this->init();
- return gm->getName();
- }
-
- SkISize size() override {
- this->init();
- return gm->getISize();
- }
-
- Status draw(SkCanvas* canvas) override {
- this->init();
- canvas->clear(0xffffffff);
- canvas->concat(gm->getInitialTransform());
- gm->draw(canvas);
- return Status::OK;
- }
- };
-
- std::unique_ptr<Src> next() override {
- if (!registry) {
- return nullptr;
- }
- GMSrc src;
- src.factory = registry->factory();
- registry = registry->next();
- return move_unique(src);
- }
-};
-static Register gm{"gm", "draw GMs linked into this binary", GMStream::Create};
-
-struct SKPStream : Stream {
- std::string dir;
- std::vector<std::string> skps;
-
- static std::unique_ptr<Stream> Create(Options options) {
- SKPStream stream;
- stream.dir = options("dir", "skps");
- SkOSFile::Iter it{stream.dir.c_str(), ".skp"};
- for (SkString path; it.next(&path); ) {
- stream.skps.push_back(path.c_str());
- }
- return move_unique(stream);
- }
-
- struct SKPSrc : Src {
- std::string dir, path;
- sk_sp<SkPicture> pic;
-
- void init() {
- if (pic) { return; }
- auto skp = SkData::MakeFromFileName((dir+"/"+path).c_str());
- pic = SkPicture::MakeFromData(skp.get());
- }
-
- std::string name() override {
- return path;
- }
-
- SkISize size() override {
- this->init();
- return pic->cullRect().roundOut().size();
- }
-
- Status draw(SkCanvas* canvas) override {
- this->init();
- canvas->clear(0xffffffff);
- pic->playback(canvas);
- return Status::OK;
- }
- };
-
- std::unique_ptr<Src> next() override {
- if (skps.empty()) {
- return nullptr;
- }
- SKPSrc src;
- src.dir = dir;
- src.path = skps.back();
- skps.pop_back();
- return move_unique(src);
- }
-};
-static Register skp{"skp", "draw SKPs from dir=skps", SKPStream::Create};
diff --git a/src/third_party/skia/tools/ok_test.cpp b/src/third_party/skia/tools/ok_test.cpp
deleted file mode 100644
index f5c4f22..0000000
--- a/src/third_party/skia/tools/ok_test.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "ok.h"
-#include "Test.h"
-
-#if SK_SUPPORT_GPU
- #include "GrContextFactory.h"
-#endif
-
-struct TestStream : Stream {
- const skiatest::TestRegistry* registry = skiatest::TestRegistry::Head();
- bool extended = false, verbose = false;
-
- static std::unique_ptr<Stream> Create(Options options) {
- TestStream stream;
- if (options("extended") != "") { stream.extended = true; }
- if (options("verbose" ) != "") { stream.verbose = true; }
-
- return move_unique(stream);
- }
-
- struct TestSrc : Src {
- skiatest::Test test {"", false, nullptr};
- bool extended, verbose;
-
- std::string name() override { return test.name; }
- SkISize size() override { return {0,0}; }
-
- Status draw(SkCanvas*) override {
-
- struct : public skiatest::Reporter {
- Status status = Status::OK;
- bool extended, verbose_;
-
- void reportFailed(const skiatest::Failure& failure) override {
- ok_log(failure.toString().c_str());
- status = Status::Failed;
- }
- bool allowExtendedTest() const override { return extended; }
- bool verbose() const override { return verbose_; }
- } reporter;
- reporter.extended = extended;
- reporter.verbose_ = verbose;
-
- sk_gpu_test::GrContextFactory* factory = nullptr;
- #if SK_SUPPORT_GPU
- GrContextOptions options;
- sk_gpu_test::GrContextFactory a_real_factory(options);
- factory = &a_real_factory;
- #endif
-
- test.proc(&reporter, factory);
- return reporter.status;
- }
- };
-
- std::unique_ptr<Src> next() override {
- if (!registry) {
- return nullptr;
- }
- TestSrc src;
- src.test = registry->factory();
- src.extended = extended;
- src.verbose = verbose;
- registry = registry->next();
- return move_unique(src);
- }
-};
-static Register test{"test", "run unit tests linked into this binary", TestStream::Create};
-
-// Hey, now why were these defined in DM.cpp? That's kind of weird.
-namespace skiatest {
-#if SK_SUPPORT_GPU
- bool IsGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
- return kOpenGL_GrBackend == sk_gpu_test::GrContextFactory::ContextTypeBackend(type);
- }
- bool IsVulkanContextType(sk_gpu_test::GrContextFactory::ContextType type) {
- return kVulkan_GrBackend == sk_gpu_test::GrContextFactory::ContextTypeBackend(type);
- }
- bool IsRenderingGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
- return IsGLContextType(type) && sk_gpu_test::GrContextFactory::IsRenderingContext(type);
- }
- bool IsNullGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
- return type == sk_gpu_test::GrContextFactory::kNullGL_ContextType;
- }
-#else
- bool IsGLContextType (int) { return false; }
- bool IsVulkanContextType (int) { return false; }
- bool IsRenderingGLContextType(int) { return false; }
- bool IsNullGLContextType (int) { return false; }
-#endif
-
- void RunWithGPUTestContexts(GrContextTestFn* test, GrContextTypeFilterFn* contextTypeFilter,
- Reporter* reporter, sk_gpu_test::GrContextFactory* factory) {
- // TODO(bsalomon)
- }
-}
diff --git a/src/third_party/skia/tools/ok_vias.cpp b/src/third_party/skia/tools/ok_vias.cpp
deleted file mode 100644
index 37d371f..0000000
--- a/src/third_party/skia/tools/ok_vias.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImage.h"
-#include "SkOSFile.h"
-#include "SkPictureRecorder.h"
-#include "SkPngEncoder.h"
-#include "ProcStats.h"
-#include "Timer.h"
-#include "ok.h"
-#include <chrono>
-#include <regex>
-
-static std::unique_ptr<Src> proxy(Src* original, std::function<Status(SkCanvas*)> fn) {
- struct : Src {
- Src* original;
- std::function<Status(SkCanvas*)> fn;
-
- std::string name() override { return original->name(); }
- SkISize size() override { return original->size(); }
- Status draw(SkCanvas* canvas) override { return fn(canvas); }
- } src;
- src.original = original;
- src.fn = fn;
- return move_unique(src);
-}
-
-struct ViaPic : Dst {
- std::unique_ptr<Dst> target;
- bool rtree = false;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- ViaPic via;
- via.target = std::move(dst);
- if (options("bbh") == "rtree") { via.rtree = true; }
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- SkRTreeFactory factory;
- SkPictureRecorder rec;
- rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
- rtree ? &factory : nullptr);
-
- for (auto status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
- return status;
- }
- auto pic = rec.finishRecordingAsPicture();
-
- return target->draw(proxy(src, [=](SkCanvas* canvas) {
- pic->playback(canvas);
- return Status::OK;
- }).get());
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register via_pic{"via_pic", "record then play back an SkPicture", ViaPic::Create};
-
-struct Png : Dst {
- std::unique_ptr<Dst> target;
- std::string dir;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- Png via;
- via.target = std::move(dst);
- via.dir = options("dir", "ok");
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- for (auto status = target->draw(src); status != Status::OK; ) {
- return status;
- }
-
- SkBitmap bm;
- SkPixmap pm;
- if (!target->image()->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode) ||
- !bm.peekPixels(&pm)) {
- return Status::Failed;
- }
-
- sk_mkdir(dir.c_str());
- SkFILEWStream dst{(dir + "/" + src->name() + ".png").c_str()};
-
- SkPngEncoder::Options options;
- options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
- options.fZLibLevel = 1;
- options.fUnpremulBehavior = pm.colorSpace() ? SkTransferFunctionBehavior::kRespect
- : SkTransferFunctionBehavior::kIgnore;
- return SkPngEncoder::Encode(&dst, pm, options) ? Status::OK
- : Status::Failed;
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register png{"png", "dump PNGs to dir=ok" , Png::Create};
-
-struct Filter : Dst {
- std::unique_ptr<Dst> target;
- std::regex match, search;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- Filter via;
- via.target = std::move(dst);
- via.match = options("match", ".*");
- via.search = options("search", ".*");
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- auto name = src->name();
- if (!std::regex_match (name, match) ||
- !std::regex_search(name, search)) {
- return Status::Skipped;
- }
- return target->draw(src);
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register filter{"filter",
- "run only srcs matching match=.* exactly and search=.* somewhere",
- Filter::Create};
-
-struct Time : Dst {
- std::unique_ptr<Dst> target;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- Time via;
- via.target = std::move(dst);
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- auto start = std::chrono::steady_clock::now();
- Status status = target->draw(src);
- std::chrono::duration<double, std::milli> elapsed = std::chrono::steady_clock::now()
- - start;
-
- auto msg = HumanizeMs(elapsed.count());
- ok_log(msg.c_str());
- return status;
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register _time{"time", "print wall run time", Time::Create};
-
-struct Memory : Dst {
- std::unique_ptr<Dst> target;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- Memory via;
- via.target = std::move(dst);
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- Status status = target->draw(src);
-
- auto msg = SkStringPrintf("%dMB", sk_tools::getMaxResidentSetSizeMB());
- ok_log(msg.c_str());
-
- return status;
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register memory{"memory", "print process maximum memory usage", Memory::Create};
diff --git a/src/third_party/skia/tools/pathops_sorter.htm b/src/third_party/skia/tools/pathops_sorter.htm
index d8371ad..c2c5103 100644
--- a/src/third_party/skia/tools/pathops_sorter.htm
+++ b/src/third_party/skia/tools/pathops_sorter.htm
@@ -6,16 +6,11 @@
<title></title>
<div style="height:0">
-<div id="cubics">
-{{{152, 16}, {152, 16.0685501}, {91.06044, 16.1242027}, {16, 16.1242027}}}, id=0
-{{{16, 16.1242027}, {-59.06044, 16.1242027}, {-120, 16.0685501}, {-120, 16}}}, id=1
-{{{-120, 16}, {-120, 15.9314508}, {-59.06044, 15.8757973}, {16, 15.8757973}}}, id=2
-{{{16, 15.8757973}, {91.06044, 15.8757973}, {152, 15.9314508}, {152, 16}}}, id=3
-{{{16, 16}, {152, 16}}}, id=4
-{{{16, 17}, {152, 17}}}, id=5
-{{{16, 16}, {16, 17}}}, id=6
-{{{152, 16}, {152, 17}}}, id=7
-</div>
+ <div id="cubics">
+{{{fX=124.70011901855469 fY=9.3718261718750000 } {fX=124.66775026544929 fY=9.3744316215161234 } {fX=124.63530969619751 fY=9.3770743012428284 }{fX=124.60282897949219 fY=9.3797206878662109 } id=10
+{{{fX=124.70011901855469 fY=9.3718004226684570 } {fX=124.66775026544929 fY=9.3744058723095804 } {fX=124.63530969619751 fY=9.3770485520362854 } {fX=124.60282897949219 fY=9.3796949386596680 } id=1
+{{{fX=124.70011901855469 fY=9.3718004226684570 } {fX=124.66786243087600 fY=9.3743968522034287 } {fX=124.63553249625420 fY=9.3770303056986286 } {fX=124.60316467285156 fY=9.3796672821044922 } id=2
+ </div>
</div>
@@ -145,7 +140,7 @@
mouseX = (screenWidth / 2) / hscale + srcLeft;
mouseY = (screenHeight / 2) / vscale + srcTop;
hinitScale = hscale;
- vinitScale = vscale;
+ vinitScale = vscale;
}
function setScale(x0, x1, y0, y1) {
@@ -160,7 +155,7 @@
vscale = screenHeight / srcHeight;
if (uniformScale) {
hscale = Math.min(hscale, vscale);
- vscale = hscale;
+ vscale = hscale;
}
var hinvScale = 1 / hscale;
var vinvScale = 1 / vscale;
@@ -897,10 +892,10 @@
var scaleTextOffset = hscale != vscale ? -25 : -5;
ctx.fillText(hscale.toFixed(decimal_places) + 'x',
screenWidth - 10, screenHeight - scaleTextOffset);
- if (hscale != vscale) {
+ if (hscale != vscale) {
ctx.fillText(vscale.toFixed(decimal_places) + 'y',
- screenWidth - 10, screenHeight - 5);
- }
+ screenWidth - 10, screenHeight - 5);
+ }
}
if (draw_t) {
drawPointAtT(curve);
@@ -1105,10 +1100,10 @@
if (focusWasOn) {
focus_on_selection = false;
hscale /= 1.2;
- vscale /= 1.2;
+ vscale /= 1.2;
} else {
- hscale /= 2;
- vscale /= 2;
+ hscale /= 2;
+ vscale /= 2;
}
calcLeftTop();
redraw();
@@ -1119,11 +1114,11 @@
focusWasOn = focus_on_selection;
if (focusWasOn) {
focus_on_selection = false;
- hscale *= 1.2;
- vscale *= 1.2;
+ hscale *= 1.2;
+ vscale *= 1.2;
} else {
- hscale *= 2;
- vscale *= 2;
+ hscale *= 2;
+ vscale *= 2;
}
calcLeftTop();
redraw();
diff --git a/src/third_party/skia/tools/pathops_visualizer.htm b/src/third_party/skia/tools/pathops_visualizer.htm
index 99acb76..c8afb44 100644
--- a/src/third_party/skia/tools/pathops_visualizer.htm
+++ b/src/third_party/skia/tools/pathops_visualizer.htm
@@ -1,223 +1,547 @@
<html>
<head>
-<div height="0" hidden="true">
-
-Skia UnitTests: --match PathOpsOp$ --resourcePath resources\ SK_DEBUG
-<div id="android1">
-seg=1 {{{-5, 0}, {1075, 0}}}
-seg=2 {{{1075, 0}, {1075, 242}}}
-seg=3 {{{1075, 242}, {-5, 242}}}
-seg=4 {{{-5, 242}, {-5, 0}}}
+<div height="0" hidden="true">
+<div id="bug8380">
+SkDCubic::ComplexBreak
+{{{126, 9.396100044250488281}, {125.6320571899414063, 9.295844078063964844}, {125.1227340698242188, 9.337338447570800781}, {124.6031646728515625, 9.379667282104492188}}},
+inflectionsTs[0]=0.999997776 {{{126.1618761931709827, 9.252680507258252973}, {123.04446008475567, 9.506653492188940291}}},
+SkDCubic::ComplexBreak
+{{{124.6031646728515625, 9.379667282104492188}, {124.1427383422851563, 9.417178153991699219}, {123.6742630004882813, 9.45534515380859375}, {123.28900146484375, 9.396100044250488281}}},
+inflectionsTs[0]=4.14921088e-06 {{{125.984438133710114, 9.267135117035042668}, {123.2218797495565639, 9.492200381017113386}}},
+maxCurvature[0]=0.0817322831 {{{125.8735553329735666, 9.277935394706121386}, {123.1067608854740314, 9.499713475347833835}}},
+SkDCubic::ComplexBreak
+{{{126, 9.396200180053710938}, {125.305999755859375, 9.206999778747558594}, {124.1090011596679688, 9.522199630737304688}, {123.28900146484375, 9.396200180053710938}}},
+inflectionsTs[0]=0.530286644 {{{127.5428560571536707, 9.140180090182106198}, {121.6628069847287179, 9.619260454379688241}}},
+maxCurvature[0]=0.568563182 {{{127.4346914043237859, 9.15278490094694952}, {121.5456828946143446, 9.624913158409162506}}},
+seg=1 {{{0, 353.891998f}, {126, 9.39610004f}}}
+seg=2 {{{126, 9.39610004f}, {125.632057f, 9.29584408f}, {125.122734f, 9.33733845f}, {124.603165f, 9.37966728f}}}
+seg=3 {{{124.603165f, 9.37966728f}, {124.142731f, 9.41717815f}, {123.674263f, 9.45534515f}, {123.289001f, 9.39610004f}}}
+seg=4 {{{123.289001f, 9.39610004f}, {118.119003f, 8.07219982f}}}
+seg=5 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}}
+seg=6 {{{8.17210007f, 104.212997f}, {0, 259.298737f}}}
+seg=7 {{{0, 259.298737f}, {0, 353.891998f}}}
op sect
-seg=5 {{{0, 0}, {1080, 0}}}
-seg=6 {{{1080, 0}, {1080, 242}}}
-seg=7 {{{1080, 242}, {0, 242}}}
-seg=8 {{{0, 242}, {0, 0}}}
-debugShowLineIntersection wtTs[0]=0 {{{1075,0}, {1075,242}}} {{1075,0}} wnTs[0]=1 {{{-5,0}, {1075,0}}}
-debugShowLineIntersection wtTs[0]=1 {{{-5,242}, {-5,0}}} {{-5,0}} wnTs[0]=0 {{{-5,0}, {1075,0}}}
-debugShowLineIntersection wtTs[0]=0 {{{1075,242}, {-5,242}}} {{1075,242}} wnTs[0]=1 {{{1075,0}, {1075,242}}}
-debugShowLineIntersection wtTs[0]=0 {{{-5,242}, {-5,0}}} {{-5,242}} wnTs[0]=1 {{{1075,242}, {-5,242}}}
-debugShowLineIntersection wtTs[0]=0 {{{0,0}, {1080,0}}} {{0,0}} wtTs[1]=0.99537037 {{1075,0}} wnTs[0]=0.00462963 {{{-5,0}, {1075,0}}} wnTs[1]=1
-SkOpSegment::addT insert t=0.00462962963 segID=1 spanID=17
-SkOpSegment::addT insert t=0.99537037 segID=5 spanID=18
-debugShowLineIntersection wtTs[0]=1 {{{0,242}, {0,0}}} {{0,0}} wnTs[0]=0.00462963 {{{-5,0}, {1075,0}}}
-debugShowLineIntersection wtTs[0]=0.99537037 {{{0,0}, {1080,0}}} {{1075,0}} wnTs[0]=0 {{{1075,0}, {1075,242}}}
-debugShowLineIntersection wtTs[0]=0.00462962963 {{{1080,242}, {0,242}}} {{1075,242}} wnTs[0]=1 {{{1075,0}, {1075,242}}}
-SkOpSegment::addT insert t=0.00462962963 segID=7 spanID=19
-debugShowLineIntersection wtTs[0]=0.00462962963 {{{1080,242}, {0,242}}} {{1075,242}} wtTs[1]=1 {{0,242}} wnTs[0]=0 {{{1075,242}, {-5,242}}} wnTs[1]=0.99537037
-SkOpSegment::addT insert t=0.99537037 segID=3 spanID=20
-debugShowLineIntersection wtTs[0]=0 {{{0,242}, {0,0}}} {{0,242}} wnTs[0]=0.99537 {{{1075,242}, {-5,242}}}
-debugShowLineIntersection wtTs[0]=0 {{{1080,0}, {1080,242}}} {{1080,0}} wnTs[0]=1 {{{0,0}, {1080,0}}}
-debugShowLineIntersection wtTs[0]=1 {{{0,242}, {0,0}}} {{0,0}} wnTs[0]=0 {{{0,0}, {1080,0}}}
-debugShowLineIntersection wtTs[0]=0 {{{1080,242}, {0,242}}} {{1080,242}} wnTs[0]=1 {{{1080,0}, {1080,242}}}
-debugShowLineIntersection wtTs[0]=0 {{{0,242}, {0,0}}} {{0,242}} wnTs[0]=1 {{{1080,242}, {0,242}}}
-------------------x--x---------------- addExpanded
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-SkOpSegment::debugShowActiveSpans id=1 (-5,0 -8.8817842e-16,0) t=0 tEnd=0.00462962963 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=1 (-8.8817842e-16,0 1075,0) t=0.00462962963 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=2 (1075,0 1075,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (1075,242 2.22044605e-14,242) t=0 tEnd=0.99537037 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (2.22044605e-14,242 -5,242) t=0.99537037 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=4 (-5,242 -5,0) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (0,0 1075,0) t=0 tEnd=0.99537037 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (1075,0 1080,0) t=0.99537037 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=6 (1080,0 1080,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=7 (1080,242 1075,242) t=0 tEnd=0.00462962963 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=7 (1075,242 0,242) t=0.00462962963 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=8 (0,242 0,0) t=0 tEnd=1 windSum=? windValue=1
-------------------x--x---------------- move_multiples
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- move_nearby
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- correctEnds
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- addEndMovedSpans
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- expand
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- addExpanded
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
-------------------x--x---------------- mark
-00: seg/base=3/5 seg/base=7/19 MarkCoinStart
-01: seg/base=3/20 seg/base=7/14 MarkCoinEnd
-02: seg/base=1/17 seg/base=5/9 MarkCoinStart
-03: seg/base=1/2 seg/base=5/18 MarkCoinEnd
+seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}}
+seg=9 {{{-5.82350016f, 369.813995f}, {126, 9.39620018f}}}
+seg=10 {{{126, 9.39620018f}, {125.631981f, 9.29586983f}, {125.12252f, 9.3373785f}, {124.602829f, 9.37972069f}}}
+seg=11 {{{124.602829f, 9.37972069f}, {124.142509f, 9.41722488f}, {123.674164f, 9.45538425f}, {123.289001f, 9.39620018f}}}
+seg=12 {{{123.289001f, 9.39620018f}, {118.119003f, 8.07219982f}}}
+seg=13 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}}
+debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{-5.82350016,369.813995}} wnTs[0]=0 {{{-5.82350016,369.813995}, {126,9.39620018}}}
+debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{-5.82350016,369.813995}, {126,9.39620018}}}
+debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{-5.82350016,369.813995}, {126,9.39620018}}}
+debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
+debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowCubicIntersection wtTs[0]=1 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{124.602829,9.37972069}} wnTs[0]=0 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}}
+debugShowCubicLineIntersection wtTs[0]=1 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
+debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection no intersect {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{{0,353.891998}, {126,9.39610004}}}
+debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wtTs[1]=0.583904956 {{0,259.298737}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}} wnTs[1]=1
+SkOpSegment::addT insert t=0.583904956 segID=8 spanID=27
+debugShowLineIntersection wtTs[0]=0.583904956 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}}
+debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wtTs[1]=1 {{126,9.39620018}} wnTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} wnTs[1]=0.999999744
+SkOpSegment::addT insert t=0.0441765002 segID=9 spanID=28
+debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{-5.82350016,369.813995}, {126,9.39620018}}}
+debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{8.17210007,104.212997}, {0,259.298737}}}
+debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}}
+-1=(0.375,0.5) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.5,0.625) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.625,0.75) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.75,0.8125) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.8125,0.875) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.875,0.9375) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+SkTSect::addForPerp priorSpan=-1 t=0.937702598 opp=-1
+-1=(0.9375,1) []
+SkTSect::addForPerp addBounded span=-1 opp=-1
+debugShowCubicIntersection wtTs[0]=0.307128906 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{125.624687,9.33981037}} wtTs[1]=0.9375 {{124.700119,9.37182617}} wnTs[0]=0.307191 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} wnTs[1]=0.937702598
+SkOpSegment::addT insert t=0.307128906 segID=10 spanID=29
+SkOpSegment::addT insert t=0.307190555 segID=2 spanID=30
+SkOpSegment::addT insert t=0.9375 segID=10 spanID=31
+SkOpSegment::addT insert t=0.937702598 segID=2 spanID=32
+debugShowCubicIntersection no intersect {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}}
+debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{0,353.891998}, {126,9.39610004}}}
+-1=(0.125,0.1875) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.1875,0.25) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.25,0.375) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.375,0.5) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.5,0.625) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+-1=(0.625,0.75) [-1]
+SkTSect::addForPerp addBounded span=-1 opp=-1
+debugShowCubicIntersection wtTs[0]=0.0625 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{124.516449,9.38673687}} wtTs[1]=0.625 {{123.752594,9.4268837}} wnTs[0]=0.0627287 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} wnTs[1]=0.625091708
+SkOpSegment::addT insert t=0.0625 segID=11 spanID=33
+SkOpSegment::addT insert t=0.0627286673 segID=3 spanID=34
+SkOpSegment::addT insert t=0.625 segID=11 spanID=35
+SkOpSegment::addT insert t=0.625091708 segID=3 spanID=36
+debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
+debugShowLineIntersection no intersect {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{{0,353.891998}, {126,9.39610004}}}
+debugShowCubicLineIntersection wtTs[0]=0.999978653 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
+debugShowLineIntersection wtTs[0]=4.65488731e-06 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{123.289001,9.39610004}} wtTs[1]=1 {{118.119003,8.07219982}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} wnTs[1]=1
+debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection no intersect {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{{0,353.891998}, {126,9.39610004}}}
+debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wnTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
+debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wtTs[1]=1 {{8.17210007,104.212997}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} wnTs[1]=1
+debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{126,9.39610004}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}}
+debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{0,353.891998}, {126,9.39610004}}}
+debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
+debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{8.17210007,104.212997}, {0,259.298737}}}
+debugShowLineIntersection wtTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}}
+debugShowCubicIntersection wtTs[0]=1 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{124.603165,9.37966728}} wnTs[0]=0 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}}
+debugShowCubicLineIntersection wtTs[0]=1 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39610004}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
+debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
+debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}}
+debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {0,259.298737}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}}
+----------------x-x--x-x-------------- addExpanded
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=10 (126,9.39620018 125.886971,9.36538583 125.760599,9.34795095 125.624687,9.33981037) t=0 tEnd=0.307128906 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=10 (125.624687,9.33981037 125.345733,9.32310212 125.026588,9.34554777 124.700119,9.37182617) t=0.307128906 tEnd=0.9375 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=1 (0,353.891998 126,9.39610004) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=3 (124.516441,9.38671017 124.257145,9.40763418 123.997124,9.42681973 123.752594,9.42682648) t=0.0627286673 tEnd=0.625091708 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=3 (123.752594,9.42682648 123.589574,9.42683098 123.433439,9.41831153 123.289001,9.39610004) t=0.625091708 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=6 (8.17210007,104.212997 0,259.298737) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1
+----------------x-x--x-x-------------- move_multiples
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+----------------x-x--x-x-------------- move_nearby
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+----------------x-x--x-x-------------- correctEnds
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+----------------x-x--x-x-------------- addEndMovedSpans
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+----------------x-x--x-x-------------- expand
+00: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+01: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+02: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+03: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
+04: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
+05: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+06: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+07: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+08: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
+09: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
+10: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
+11: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
+12: seg/base=13/25 seg/base=5/9 MarkCoinStart
+13: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+14: seg/base=4/7 seg/base=12/23 MarkCoinStart
+15: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+16: seg/base=11/33 seg/base=3/34 MarkCoinStart
+17: seg/base=11/35 seg/base=3/36 MarkCoinEnd
+18: seg/base=2/30 seg/base=10/29 MarkCoinStart
+19: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+20: seg/base=9/28 seg/base=1/1 MarkCoinStart
+21: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+22: seg/base=8/15 seg/base=6/11 MarkCoinStart
+23: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+------------------xx-x-x-------------- addExpanded
+00: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+01: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+02: seg/base=13/25 seg/base=5/9 MarkCoinStart
+03: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+04: seg/base=4/7 seg/base=12/23 MarkCoinStart
+05: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+06: seg/base=11/33 seg/base=3/34 MarkCoinStart
+07: seg/base=11/22 seg/base=3/6 MarkCoinEnd
+08: seg/base=3/36 MarkCoinInsert
+09: seg/base=11/35 MarkCoinInsert
+10: seg/base=2/3 seg/base=10/19 MarkCoinStart
+11: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+12: seg/base=10/29 MarkCoinInsert
+13: seg/base=2/30 MarkCoinInsert
+14: seg/base=9/28 seg/base=1/1 MarkCoinStart
+15: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+16: seg/base=8/15 seg/base=6/11 MarkCoinStart
+17: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+------------------xx-x-x-------------- move_multiples
+00: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+01: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+02: seg/base=13/25 seg/base=5/9 MarkCoinStart
+03: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+04: seg/base=4/7 seg/base=12/23 MarkCoinStart
+05: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+06: seg/base=11/33 seg/base=3/34 MarkCoinStart
+07: seg/base=11/22 seg/base=3/6 MarkCoinEnd
+08: seg/base=3/36 MarkCoinInsert
+09: seg/base=11/35 MarkCoinInsert
+10: seg/base=2/3 seg/base=10/19 MarkCoinStart
+11: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+12: seg/base=10/29 MarkCoinInsert
+13: seg/base=2/30 MarkCoinInsert
+14: seg/base=9/28 seg/base=1/1 MarkCoinStart
+15: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+16: seg/base=8/15 seg/base=6/11 MarkCoinStart
+17: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+------------------xx-x-x-------------- move_nearby
+00: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+01: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+02: seg/base=13/25 seg/base=5/9 MarkCoinStart
+03: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+04: seg/base=4/7 seg/base=12/23 MarkCoinStart
+05: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+06: seg/base=11/33 seg/base=3/34 MarkCoinStart
+07: seg/base=11/22 seg/base=3/6 MarkCoinEnd
+08: seg/base=3/36 MarkCoinInsert
+09: seg/base=11/35 MarkCoinInsert
+10: seg/base=2/3 seg/base=10/19 MarkCoinStart
+11: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+12: seg/base=10/29 MarkCoinInsert
+13: seg/base=2/30 MarkCoinInsert
+14: seg/base=9/28 seg/base=1/1 MarkCoinStart
+15: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+16: seg/base=8/15 seg/base=6/11 MarkCoinStart
+17: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+------------------xx-x-x-------------- addExpanded
+00: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+01: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+02: seg/base=13/25 seg/base=5/9 MarkCoinStart
+03: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+04: seg/base=4/7 seg/base=12/23 MarkCoinStart
+05: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+06: seg/base=11/33 seg/base=3/34 MarkCoinStart
+07: seg/base=11/22 seg/base=3/6 MarkCoinEnd
+08: seg/base=3/36 MarkCoinInsert
+09: seg/base=11/35 MarkCoinInsert
+10: seg/base=2/3 seg/base=10/19 MarkCoinStart
+11: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+12: seg/base=10/29 MarkCoinInsert
+13: seg/base=2/30 MarkCoinInsert
+14: seg/base=9/28 seg/base=1/1 MarkCoinStart
+15: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+16: seg/base=8/15 seg/base=6/11 MarkCoinStart
+17: seg/base=8/27 seg/base=6/12 MarkCoinEnd
+------------------xx-x-x-------------- mark
+00: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+01: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
+02: seg/base=13/25 seg/base=5/9 MarkCoinStart
+03: seg/base=13/26 seg/base=5/10 MarkCoinEnd
+04: seg/base=4/7 seg/base=12/23 MarkCoinStart
+05: seg/base=4/8 seg/base=12/24 MarkCoinEnd
+06: seg/base=11/33 seg/base=3/34 MarkCoinStart
+07: seg/base=11/22 seg/base=3/6 MarkCoinEnd
+08: seg/base=3/36 MarkCoinInsert
+09: seg/base=11/35 MarkCoinInsert
+10: seg/base=2/3 seg/base=10/19 MarkCoinStart
+11: seg/base=2/32 seg/base=10/31 MarkCoinEnd
+12: seg/base=10/29 MarkCoinInsert
+13: seg/base=2/30 MarkCoinInsert
+14: seg/base=9/28 seg/base=1/1 MarkCoinStart
+15: seg/base=9/18 seg/base=1/2 MarkCoinEnd
+16: seg/base=8/15 seg/base=6/11 MarkCoinStart
+17: seg/base=8/27 seg/base=6/12 MarkCoinEnd
-------------------------------------- missing_coincidence
-------------------------------------- expand
-------------------------------------- expand
-------------------------------------- apply
-SkOpSegment::markDone id=7 (1080,242 0,242) t=0.00462962963 [19] (1075,242) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-SkOpSegment::markDone id=5 (0,0 1080,0) t=0 [9] (0,0) tEnd=0.99537037 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 [9] (118.119003,8.07219982) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 [23] (123.289001,9.39620018) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.0627286673 [34] (124.516441,9.38671017) tEnd=0.625091708 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.625091708 [36] (123.752594,9.42682648) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0 [19] (126,9.39620018) tEnd=0.307128906 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.307128906 [29] (125.624687,9.33981037) tEnd=0.9375 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=1 (0,353.891998 126,9.39610004) t=0 [1] (0,353.891998) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
+SkOpSegment::markDone id=6 (8.17210007,104.212997 0,259.298737) t=0 [11] (8.17210007,104.212997) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-------------------------------------- findOverlaps
-SkOpSegment::debugShowActiveSpans id=1 (-5,0 -8.8817842e-16,0) t=0 tEnd=0.00462962963 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=1 (-8.8817842e-16,0 1075,0) t=0.00462962963 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=2 (1075,0 1075,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (1075,242 2.22044605e-14,242) t=0 tEnd=0.99537037 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=3 (2.22044605e-14,242 -5,242) t=0.99537037 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=4 (-5,242 -5,0) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (1075,0 1080,0) t=0.99537037 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=6 (1080,0 1080,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=7 (1080,242 1075,242) t=0 tEnd=0.00462962963 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=8 (0,242 0,0) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
+SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1
-------------------------------------- calc_angles
-SkOpSegment::sortAngles [1] tStart=0.00462962963 [17]
-SkOpAngle::after [1/1] 15/15 tStart=0.00462962963 tEnd=0 < [8/12] 23/23 tStart=1 tEnd=0 < [1/2] 31/31 tStart=0.00462962963 tEnd=1 T 4
-SkOpAngle::afterPart {{{0,0}, {-5,0}}} id=1
-SkOpAngle::afterPart {{{0,0}, {0,242}}} id=8
-SkOpAngle::afterPart {{{0,0}, {1075,0}}} id=1
-SkOpSegment::sortAngles [1] tStart=1 [2]
-SkOpAngle::after [1/3] 15/15 tStart=1 tEnd=0.00462962963 < [2/4] 23/23 tStart=0 tEnd=1 < [5/9] 31/31 tStart=0.99537037 tEnd=1 T 4
-SkOpAngle::afterPart {{{1075,0}, {-8.8817842e-16,0}}} id=1
-SkOpAngle::afterPart {{{1075,0}, {1075,242}}} id=2
-SkOpAngle::afterPart {{{1075,0}, {1080,0}}} id=5
-SkOpSegment::sortAngles [2] tStart=0 [3]
-SkOpSegment::sortAngles [2] tStart=1 [4]
-SkOpAngle::after [2/5] 7/7 tStart=1 tEnd=0 < [3/6] 15/15 tStart=0 tEnd=0.99537037 < [7/10] 31/31 tStart=0.00462962963 tEnd=0 T 4
-SkOpAngle::afterPart {{{1075,242}, {1075,0}}} id=2
-SkOpAngle::afterPart {{{1075,242}, {2.22044605e-14,242}}} id=3
-SkOpAngle::afterPart {{{1075,242}, {1080,242}}} id=7
-SkOpSegment::sortAngles [3] tStart=0 [5]
-SkOpSegment::sortAngles [3] tStart=0.99537037 [20]
-SkOpAngle::after [3/7] 31/31 tStart=0.99537037 tEnd=0 < [8/11] 7/7 tStart=0 tEnd=1 < [3/8] 15/15 tStart=0.99537037 tEnd=1 T 4
-SkOpAngle::afterPart {{{0,242}, {1075,242}}} id=3
-SkOpAngle::afterPart {{{0,242}, {0,0}}} id=8
-SkOpAngle::afterPart {{{0,242}, {-5,242}}} id=3
-SkOpSegment::sortAngles [5] tStart=0.99537037 [18]
-SkOpSegment::sortAngles [7] tStart=0.00462962963 [19]
SkOpSegment::sortAngles [8] tStart=0 [15]
-SkOpSegment::sortAngles [8] tStart=1 [16]
-coinSpan - id=3 t=0 tEnd=0.99537037
-coinSpan + id=7 t=0.00462962963 tEnd=1
-coinSpan - id=1 t=0.00462962963 tEnd=1
-coinSpan + id=5 t=0 tEnd=0.99537037
-SkOpSpan::sortableTop dir=kTop seg=1 t=0.00231481481 pt=(-2.5,0)
-SkOpSpan::sortableTop [0] valid=1 operand=0 span=1 ccw=1 seg=1 {{{-5, 0}, {1075, 0}}} t=0.00231481481 pt=(-2.5,0) slope=(1080,0)
-SkOpSegment::markWinding id=1 (-5,0 1075,0) t=0 [1] (-5,0) tEnd=0.00462962963 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=1 (-5,0 1075,0) t=0 [1] (-5,0) tEnd=0.00462962963 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=4 (-5,242 -5,0) t=0 [7] (-5,242) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=3 (1075,242 -5,242) t=0.99537037 [20] (2.22044605e-14,242) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::activeOp id=1 t=0.00462962963 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
-SkOpSegment::markDone id=1 (-5,0 1075,0) t=0 [1] (-5,0) tEnd=0.00462962963 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=4 (-5,242 -5,0) t=0 [7] (-5,242) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=3 (1075,242 -5,242) t=0.99537037 [20] (2.22044605e-14,242) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-bridgeOp chase.append id=3 windSum=-1
-SkOpSegment::markWinding id=3 (1075,242 -5,242) t=0 [5] (1075,242) tEnd=0.99537037 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
-SkOpSegment::markAngle last segment=3 span=5 windSum=-1
-SkOpSegment::markWinding id=8 (0,242 0,0) t=0 [15] (0,242) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=8 span=16
-SkOpSegment::debugShowActiveSpans id=1 (-8.8817842e-16,0 1075,0) t=0.00462962963 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=2 (1075,0 1075,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (1075,242 2.22044605e-14,242) t=0 tEnd=0.99537037 windSum=-1 oppSum=-1 windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=5 (1075,0 1080,0) t=0.99537037 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=6 (1080,0 1080,242) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=7 (1080,242 1075,242) t=0 tEnd=0.00462962963 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=8 (0,242 0,0) t=0 tEnd=1 windSum=-1 oppSum=-1 windValue=1 oppValue=0
-SkOpSegment::activeOp id=3 t=0.99537037 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=1 result=1
-SkOpSegment::markWinding id=7 (1080,242 0,242) t=0 [13] (1080,242) tEnd=0.00462962963 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=6 (1080,0 1080,242) t=0 [11] (1080,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=5 (0,0 1080,0) t=0.99537037 [18] (1075,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=5 span=18 windSum=-1
-SkOpSegment::markWinding id=2 (1075,0 1075,242) t=0 [3] (1075,0) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=2 span=3 windSum=-1
+SkOpSegment::sortAngles [8] tStart=0.583904956 [27]
+SkOpAngle::after [8/2] 5/5 tStart=0.583904956 tEnd=0 < [7/23] 23/23 tStart=0 tEnd=1 < [8/3] 21/21 tStart=0.583904956 tEnd=1 F 4
+SkOpAngle::afterPart {{{0,259.298737}, {8.17210034,104.212997}}} id=8
+SkOpAngle::afterPart {{{0,259.298737}, {0,353.891998}}} id=7
+SkOpAngle::afterPart {{{0,259.298737}, {-5.82349988,369.813995}}} id=8
+SkOpSegment::sortAngles [9] tStart=0.0441765002 [28]
+SkOpAngle::after [9/4] 21/21 tStart=0.0441765002 tEnd=0 < [7/24] 7/7 tStart=1 tEnd=0 < [9/5] 5/5 tStart=0.0441765002 tEnd=1 F 4
+SkOpAngle::afterPart {{{0,353.891998}, {-5.82350088,369.813995}}} id=9
+SkOpAngle::afterPart {{{0,353.891998}, {0,259.298737}}} id=7
+SkOpAngle::afterPart {{{0,353.891998}, {125.999999,9.39620018}}} id=9
+SkOpSegment::sortAngles [9] tStart=1 [18]
+SkOpSegment::sortAngles [10] tStart=0.9375 [31]
+SkOpAngle::after [10/7] 17/17 tStart=0.9375 tEnd=1 < [2/19] 17/17 tStart=0.937702598 tEnd=1 < [2/18] 1/1 tStart=0.937702598 tEnd=0.307190555 T 12
+SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.66775,9.37440587}, {124.63531,9.37704855}, {124.602829,9.37969494}}} id=10
+SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.667862,9.37439685}, {124.635532,9.37703031}, {124.603165,9.37966728}}} id=2
+SkOpAngle::afterPart {{{124.700119,9.37180042}, {125.026588,9.34552196}, {125.345738,9.3230648}, {125.624695,9.33975124}}} id=2
+SkOpSegment::sortAngles [11] tStart=0.0625 [33]
+SkOpAngle::after [11/8] 1/1 tStart=0.0625 tEnd=0 < [3/20] 1/1 tStart=0.0627286673 tEnd=0 < [11/9] 17/17 tStart=0.0625 tEnd=0.625 T 12
+SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545252,9.38438496}, {124.574051,9.382038}, {124.602821,9.37969398}}} id=11
+SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545364,9.3843762}, {124.574282,9.38202029}, {124.603165,9.37966728}}} id=3
+SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.257148,9.40763702}, {123.997118,9.42683311}, {123.752586,9.42685699}}} id=11
+SkOpSegment::sortAngles [11] tStart=0.625 [35]
+SkOpSegment::sortAngles [11] tStart=1 [22]
+SkOpSegment::sortAngles [13] tStart=0 [25]
+SkOpSegment::sortAngles [13] tStart=1 [26]
+SkOpSegment::sortAngles [2] tStart=0 [3]
+SkOpSegment::sortAngles [2] tStart=0.307190555 [30]
+SkOpSegment::sortAngles [2] tStart=0.937702598 [32]
+SkOpSegment::sortAngles [3] tStart=0.0627286673 [34]
+SkOpSegment::sortAngles [4] tStart=0 [7]
+SkOpSegment::sortAngles [4] tStart=1 [8]
+SkOpSegment::sortAngles [7] tStart=0 [13]
+SkOpSegment::sortAngles [7] tStart=1 [14]
+coinSpan - id=13 t=0 tEnd=1
+coinSpan + id=5 t=0 tEnd=1
+coinSpan - id=4 t=0 tEnd=1
+coinSpan + id=12 t=0 tEnd=1
+coinSpan - id=11 t=0.0625 tEnd=1
+coinSpan + id=3 t=0.0627286673 tEnd=1
+coinSpan - id=2 t=0 tEnd=0.937702598
+coinSpan + id=10 t=0 tEnd=0.9375
+coinSpan - id=9 t=0.0441765002 tEnd=1
+coinSpan + id=1 t=0 tEnd=1
+coinSpan - id=8 t=0 tEnd=0.583904956
+coinSpan + id=6 t=0 tEnd=1
+SkOpSpan::sortableTop dir=kLeft seg=8 t=0.291952478 pt=(4.08605003,181.755859)
+SkOpSpan::sortableTop [0] valid=1 operand=1 span=15 ccw=0 seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}} t=0.291952478 pt=(4.08605003,181.755859) slope=(-13.9956002,265.600998)
+SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+SkOpSegment::markWinding id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markWinding id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::activeOp id=8 t=0.583904956 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=1 suTo=0 result=1
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+bridgeOp current id=8 from=(-2.71619996e-07,259.298737) to=(8.17210007,104.212997)
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+bridgeOp current id=13 from=(8.17210007,104.212997) to=(118.119003,8.07219982)
+path.moveTo(-2.71619996e-07,259.298737);
+path.lineTo(8.17210007,104.212997);
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+bridgeOp current id=4 from=(118.119003,8.07219982) to=(123.289001,9.39610004)
+path.lineTo(118.119003,8.07219982);
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+bridgeOp current id=11 from=(123.289001,9.39620018) to=(123.752594,9.4268837)
+path.lineTo(123.289001,9.39610004);
+path.cubicTo(123.433441,9.41839409, 123.589569,9.42689991, 123.752594,9.4268837);
+SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markAngle last segment=10 span=31 windSum=1
+SkOpSegment::markWinding id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markAngle last segment=2 span=32 windSum=1
SkOpSegment::findNextOp
-SkOpAngle::dumpOne [3/6] next=7/10 sect=15/15 s=0 [5] e=0.99537037 [20] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1
-SkOpAngle::dumpOne [7/10] next=2/5 sect=31/31 s=0.00462962963 [19] e=0 [13] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
-SkOpAngle::dumpOne [2/5] next=3/6 sect=7/7 s=1 [4] e=0 [3] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1
-SkOpSegment::activeOp id=7 t=0.00462962963 tEnd=0 op=sect miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-SkOpSegment::markDone id=7 (1080,242 0,242) t=0 [13] (1080,242) tEnd=0.00462962963 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=6 (1080,0 1080,242) t=0 [11] (1080,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=5 (0,0 1080,0) t=0.99537037 [18] (1075,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp chase.append segment=5 span=18 windSum=-1
-SkOpSegment::activeOp id=2 t=1 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1
-SkOpSegment::findNextOp chase.append segment=2 span=3 windSum=-1
-SkOpSegment::markDone id=3 (1075,242 -5,242) t=0 [5] (1075,242) tEnd=0.99537037 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
-SkOpSegment::findNextOp from:[3] to:[2] start=90366152 end=90366008
-bridgeOp current id=3 from=(2.22044605e-14,242) to=(1075,242)
-SkOpSegment::markWinding id=1 (-5,0 1075,0) t=0.00462962963 [17] (-8.8817842e-16,0) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
-SkOpSegment::markAngle last segment=1 span=17 windSum=-1
+SkOpAngle::dumpOne [11/9] next=11/8 sect=17/17 s=0.0625 [33] e=0.625 [35] sgn=-1 windVal=1 windSum=1 oppVal=1 oppSum=1 operand
+SkOpAngle::dumpOne [11/8] next=3/20 sect=1/1 s=0.0625 [33] e=0 [21] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand
+SkOpAngle::dumpOne [3/20] next=11/9 sect=1/1 s=0.0627286673 [34] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0
+SkOpSegment::activeOp id=11 t=0.0625 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
+SkOpSegment::findNextOp chase.append segment=10 span=31 windSum=1
+SkOpSegment::activeOp id=3 t=0.0627286673 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
+SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+SkOpSegment::findNextOp chase.append segment=2 span=32 windSum=1
+SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
+SkOpSegment::findNextOp from:[11] to:[11] start=-1132576784 end=-1353716568
+bridgeOp current id=11 from=(123.752594,9.4268837) to=(124.516449,9.38673687)
+path.cubicTo(123.997124,9.42685986, 124.257156,9.40766335, 124.516449,9.38673687);
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+bridgeOp current id=11 from=(124.516449,9.38673687) to=(124.602829,9.37972069)
+path.cubicTo(124.545258,9.38441181, 124.574059,9.38206482, 124.602829,9.37972069);
+SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
+SkOpSegment::markAngle last segment=9 span=28 windSum=-1
SkOpSegment::findNextOp
-SkOpAngle::dumpOne [2/4] next=5/9 sect=23/23 s=0 [3] e=1 [4] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1
-SkOpAngle::dumpOne [5/9] next=1/3 sect=31/31 s=0.99537037 [18] e=1 [10] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done operand
-SkOpAngle::dumpOne [1/3] next=2/4 sect=15/15 s=1 [2] e=0.00462962963 [17] sgn=1 windVal=1 windSum=-1 oppVal=1 oppSum=-1
-SkOpSegment::activeOp id=5 t=0.99537037 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-SkOpSegment::activeOp id=1 t=1 tEnd=0.00462962963 op=sect miFrom=0 miTo=1 suFrom=0 suTo=1 result=1
-SkOpSegment::findNextOp chase.append segment=1 span=17 windSum=-1
-SkOpSegment::markDone id=2 (1075,0 1075,242) t=0 [3] (1075,0) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp from:[2] to:[1] start=90365736 end=90368360
-bridgeOp current id=2 from=(1075,242) to=(1075,0)
-path.moveTo(2.22044605e-14,242);
-path.lineTo(1075,242);
-SkOpSegment::findNextOp
-SkOpAngle::dumpOne [1/2] next=1/1 sect=31/31 s=0.00462962963 [17] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1
-SkOpAngle::dumpOne [1/1] next=8/12 sect=15/15 s=0.00462962963 [17] e=0 [1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done
-SkOpAngle::dumpOne [8/12] next=1/2 sect=23/23 s=1 [16] e=0 [15] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand
-SkOpSegment::activeOp id=1 t=0.00462962963 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
-SkOpSegment::activeOp id=8 t=1 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-SkOpSegment::markDone id=1 (-5,0 1075,0) t=0.00462962963 [17] (-8.8817842e-16,0) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
-SkOpSegment::findNextOp from:[1] to:[8] start=90368192 end=90368048
-bridgeOp current id=1 from=(1075,0) to=(-8.8817842e-16,0)
-path.lineTo(1075,0);
-SkOpSegment::findNextOp
-SkOpAngle::dumpOne [8/11] next=3/8 sect=7/7 s=0 [15] e=1 [16] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand
-SkOpAngle::dumpOne [3/8] next=3/7 sect=15/15 s=0.99537037 [20] e=1 [6] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done
-SkOpAngle::dumpOne [3/7] next=8/11 sect=31/31 s=0.99537037 [20] e=0 [5] sgn=1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 done
-SkOpSegment::activeOp id=3 t=0.99537037 tEnd=1 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
-SkOpSegment::activeOp id=3 t=0.99537037 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=1 result=1
-SkOpSegment::markDone id=8 (0,242 0,0) t=0 [15] (0,242) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp from:[8] to:[3] start=90368840 end=90366336
-bridgeOp current id=8 from=(0,0) to=(0,242)
-path.lineTo(-8.8817842e-16,0);
-path.lineTo(0,242);
-path.close();
+SkOpAngle::dumpOne [10/7] next=2/19 sect=17/17 s=0.9375 [31] e=1 [20] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand
+SkOpAngle::dumpOne [2/19] next=2/18 sect=17/17 s=0.937702598 [32] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
+SkOpAngle::dumpOne [2/18] next=10/7 sect=1/1 s=0.937702598 [32] e=0.307190555 [30] sgn=1 windVal=1 windSum=1 oppVal=1 oppSum=-1
+SkOpSegment::activeOp id=2 t=0.937702598 tEnd=1 op=sect = result=1
+SkOpSegment::activeOp id=2 t=0.937702598 tEnd=0.307190555 op=sect miFrom=0 miTo=1 suFrom=1 suTo=0 result=0
+SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1
+SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1
+SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=1
+SkOpSegment::findNextOp chase.append segment=9 span=28 windSum=-1
+SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+SkOpSegment::findNextOp from:[10] to:[2] start=-1132576976 end=-1353719496
+bridgeOp current id=10 from=(124.602829,9.37972069) to=(124.700119,9.37182617)
+path.cubicTo(124.635307,9.37707424, 124.667747,9.37443161, 124.700119,9.37182617);
+SkOpSegment::markWinding id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
+SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0
+SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
+SkOpSegment::activeOp id=7 t=1 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
+SkOpSegment::markDone id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+bridgeOp chase.append id=7 windSum=1
+SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
+SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0
+SkOpSegment::activeOp id=8 t=0.583904956 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
+SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
+SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
</div>
-</div>
+
+
+ </div>
<script type="text/javascript">
var testDivs = [
- android1,
+ bug8380,
];
var decimal_places = 3; // make this 3 to show more precision
@@ -504,9 +828,9 @@
escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
- escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
- escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
+ escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
+ escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
+ escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/PATH/g, "pathB?");
escape = escape.replace(/IDX/g, "(-?\\d+)");
escape = escape.replace(/NUM/g, "(-?\\d+)");
@@ -524,9 +848,9 @@
escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
- escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
- escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
+ escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
+ escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
+ escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/OPER/g, "[a-z]+");
escape = escape.replace(/PATH/g, "pathB?");
escape = escape.replace(/T_F/g, "([TF])");
@@ -2226,9 +2550,9 @@
return dxy;
}
-function dpt_at_t(curve, t) {
+function dpt_at_t(curve, t) {
var type = PATH_LINE + (curve.length / 2 - 2);
- return dxy_at_t(curve, type, t);
+ return dxy_at_t(curve, type, t);
}
function drawLabel(num, px, py) {
@@ -2346,11 +2670,11 @@
return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
}
-function pt_at_t(curve, t) {
- var pt = {};
- pt.x = x_at_t(curve, t);
- pt.y = y_at_t(curve, t);
- return pt;
+function pt_at_t(curve, t) {
+ var pt = {};
+ pt.x = x_at_t(curve, t);
+ pt.y = y_at_t(curve, t);
+ return pt;
}
function drawOrder(curve, t, label) {
@@ -2377,59 +2701,59 @@
ctx.font = "normal 10px Arial";
}
-function drawVisibleOrder(curve, label) {
- var s = pt_at_t(curve, 0);
- var e = pt_at_t(curve, 1);
- var sOn = ptOnScreen(s);
- var eOn = ptOnScreen(e);
- var defaultT = 0.85;
- if (sOn && eOn)
- return drawOrder(curve, defaultT, label);
- if (sOn || eOn) {
- if (eOn) {
- defaultT = 1 - defaultT;
- }
- var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
- var t = defaultT;
- var tries = 16;
- do {
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawOrder(curve, t, label);
- t += step;
- step /= 2;
- } while (--tries > 0);
- drawOrder(curve, defaultT, label);
- }
- // scattershot until we find a visible point
- var denom = 2; // visit odd number num / denom to hit unique pts
- var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
- do {
- for (var numer = 1; numer < denom; numer += 2) {
- var t = numer / denom + 0.1;
- if (t >= 1) {
- break;
- }
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawOrder(curve, t, label);
- }
- denom *= 2;
- } while (--tries > 0);
- drawOrder(curve, defaultT, label);
+function drawVisibleOrder(curve, label) {
+ var s = pt_at_t(curve, 0);
+ var e = pt_at_t(curve, 1);
+ var sOn = ptOnScreen(s);
+ var eOn = ptOnScreen(e);
+ var defaultT = 0.85;
+ if (sOn && eOn)
+ return drawOrder(curve, defaultT, label);
+ if (sOn || eOn) {
+ if (eOn) {
+ defaultT = 1 - defaultT;
+ }
+ var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
+ var t = defaultT;
+ var tries = 16;
+ do {
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawOrder(curve, t, label);
+ t += step;
+ step /= 2;
+ } while (--tries > 0);
+ drawOrder(curve, defaultT, label);
+ }
+ // scattershot until we find a visible point
+ var denom = 2; // visit odd number num / denom to hit unique pts
+ var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
+ do {
+ for (var numer = 1; numer < denom; numer += 2) {
+ var t = numer / denom + 0.1;
+ if (t >= 1) {
+ break;
+ }
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawOrder(curve, t, label);
+ }
+ denom *= 2;
+ } while (--tries > 0);
+ drawOrder(curve, defaultT, label);
}
-function set_length(pt, newLen) {
- var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
- var scale = newLen / len;
- var newPt = { x: pt.x * scale, y: pt.y * scale };
- return newPt;
+function set_length(pt, newLen) {
+ var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
+ var scale = newLen / len;
+ var newPt = { x: pt.x * scale, y: pt.y * scale };
+ return newPt;
}
-function drawDirection(curve, t) {
+function drawDirection(curve, t) {
var d = dpt_at_t(curve, t);
d = set_length(d, 16);
- var pt = localToGlobal(pt_at_t(curve, t));
+ var pt = localToGlobal(pt_at_t(curve, t));
ctx.beginPath();
ctx.moveTo(pt.x - d.y, pt.y + d.x);
ctx.lineTo(pt.x + d.x, pt.y + d.y);
@@ -2438,47 +2762,47 @@
ctx.stroke();
}
-function drawVisibleDirection(curve) {
- var s = pt_at_t(curve, 0);
- var e = pt_at_t(curve, 1);
- var sOn = ptOnScreen(s);
- var eOn = ptOnScreen(e);
- var defaultT = 0.65;
- if (sOn && eOn) {
- return drawDirection(curve, defaultT);
- }
- if (sOn || eOn) {
- if (eOn) {
- defaultT = 1 - defaultT;
- }
- var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
- var t = defaultT;
- var tries = 16;
- do {
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawDirection(curve, t);
- t += step;
- step /= 2;
- } while (--tries > 0);
- drawDirection(curve, defaultT);
- }
- // scattershot until we find a visible point
- var denom = 2; // visit odd number num / denom to hit unique pts
- var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
- do {
- for (var numer = 1; numer < denom; numer += 2) {
- var t = numer / denom + 0.1;
- if (t >= 1) {
- break;
- }
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawDirection(curve, t);
- }
- denom *= 2;
- } while (--tries > 0);
- drawDirection(curve, defaultT);
+function drawVisibleDirection(curve) {
+ var s = pt_at_t(curve, 0);
+ var e = pt_at_t(curve, 1);
+ var sOn = ptOnScreen(s);
+ var eOn = ptOnScreen(e);
+ var defaultT = 0.65;
+ if (sOn && eOn) {
+ return drawDirection(curve, defaultT);
+ }
+ if (sOn || eOn) {
+ if (eOn) {
+ defaultT = 1 - defaultT;
+ }
+ var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
+ var t = defaultT;
+ var tries = 16;
+ do {
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawDirection(curve, t);
+ t += step;
+ step /= 2;
+ } while (--tries > 0);
+ drawDirection(curve, defaultT);
+ }
+ // scattershot until we find a visible point
+ var denom = 2; // visit odd number num / denom to hit unique pts
+ var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
+ do {
+ for (var numer = 1; numer < denom; numer += 2) {
+ var t = numer / denom + 0.1;
+ if (t >= 1) {
+ break;
+ }
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawDirection(curve, t);
+ }
+ denom *= 2;
+ } while (--tries > 0);
+ drawDirection(curve, defaultT);
}
function drawID(curve, t, id) {
@@ -2489,53 +2813,53 @@
draw_id_at(id, _px, _py);
}
-function localToGlobal(local) {
- var global = {};
- global.x = (local.x - srcLeft) * scale;
- global.y = (local.y - srcTop) * scale;
- return global;
+function localToGlobal(local) {
+ var global = {};
+ global.x = (local.x - srcLeft) * scale;
+ global.y = (local.y - srcTop) * scale;
+ return global;
}
-function ptOnScreen(local) {
- var pt = localToGlobal(local);
- return 10 <= pt.x && pt.x <= screenWidth - 10
- && 10 <= pt.y && pt.y <= screenHeight - 10;
+function ptOnScreen(local) {
+ var pt = localToGlobal(local);
+ return 10 <= pt.x && pt.x <= screenWidth - 10
+ && 10 <= pt.y && pt.y <= screenHeight - 10;
}
-function drawVisibleID(curve, defaultT, id) {
- // determine if either or both ends are visible
- var s = pt_at_t(curve, 0);
- var e = pt_at_t(curve, 1);
- var sOn = ptOnScreen(s);
- var eOn = ptOnScreen(e);
- if (sOn && eOn)
- return drawID(curve, defaultT, id);
- if (sOn || eOn) {
- var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
- var t = defaultT;
- var tries = 16;
- do {
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawID(curve, t, id);
- t += step;
- step /= 2;
- } while (--tries > 0);
- drawID(curve, defaultT, id);
- }
- // scattershot until we find a visible point
- var denom = 2; // visit odd number num / denom to hit unique pts
- var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
- do {
- for (var numer = 1; numer < denom; numer += 2) {
- var t = numer / denom;
- var mid = pt_at_t(curve, t);
- if (ptOnScreen(mid))
- return drawID(curve, t, id);
- }
- denom *= 2;
- } while (--tries > 0);
- drawID(curve, defaultT, id);
+function drawVisibleID(curve, defaultT, id) {
+ // determine if either or both ends are visible
+ var s = pt_at_t(curve, 0);
+ var e = pt_at_t(curve, 1);
+ var sOn = ptOnScreen(s);
+ var eOn = ptOnScreen(e);
+ if (sOn && eOn)
+ return drawID(curve, defaultT, id);
+ if (sOn || eOn) {
+ var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
+ var t = defaultT;
+ var tries = 16;
+ do {
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawID(curve, t, id);
+ t += step;
+ step /= 2;
+ } while (--tries > 0);
+ drawID(curve, defaultT, id);
+ }
+ // scattershot until we find a visible point
+ var denom = 2; // visit odd number num / denom to hit unique pts
+ var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
+ do {
+ for (var numer = 1; numer < denom; numer += 2) {
+ var t = numer / denom;
+ var mid = pt_at_t(curve, t);
+ if (ptOnScreen(mid))
+ return drawID(curve, t, id);
+ }
+ denom *= 2;
+ } while (--tries > 0);
+ drawID(curve, defaultT, id);
}
function draw_id_at(id, _px, _py) {
@@ -2613,8 +2937,8 @@
drawVisibleID(curve, 0.5, id);
}
}
- if (draw_direction) {
- drawVisibleDirection(curve);
+ if (draw_direction) {
+ drawVisibleDirection(curve);
}
if (type == PATH_LINE) {
return;
@@ -3205,10 +3529,10 @@
drawVisibleOrder(leftCurve, 'L');
drawVisibleOrder(rightCurve, 'R');
}
- if (draw_id) {
- drawVisibleID(leftCurve, 0.5, frags[0]);
- drawVisibleID(midCurve, 0.5, frags[6]);
- drawVisibleID(rightCurve, 0.5, frags[12]);
+ if (draw_id) {
+ drawVisibleID(leftCurve, 0.5, frags[0]);
+ drawVisibleID(midCurve, 0.5, frags[6]);
+ drawVisibleID(rightCurve, 0.5, frags[12]);
}
break;
case REC_TYPE_AFTERPART:
@@ -3245,8 +3569,8 @@
throw "stop execution";
}
drawCurve(curve);
- if (draw_id) {
- drawVisibleID(curve, 0.5, id);
+ if (draw_id) {
+ drawVisibleID(curve, 0.5, id);
}
++afterIndex;
break;
diff --git a/src/third_party/skia/tools/picture_utils.cpp b/src/third_party/skia/tools/picture_utils.cpp
deleted file mode 100644
index 93d598d..0000000
--- a/src/third_party/skia/tools/picture_utils.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "picture_utils.h"
-#include "SkBitmap.h"
-#include "SkColorPriv.h"
-#include "SkHalf.h"
-#include "SkImageEncoder.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkPM4fPriv.h"
-#include "SkPicture.h"
-#include "SkStream.h"
-#include "SkString.h"
-#include "SkRasterPipeline.h"
-
-#include "sk_tool_utils.h"
-
-namespace sk_tools {
- void force_all_opaque(const SkBitmap& bitmap) {
- SkASSERT(kN32_SkColorType == bitmap.colorType());
- if (kN32_SkColorType == bitmap.colorType()) {
- return;
- }
-
- for (int y = 0; y < bitmap.height(); y++) {
- for (int x = 0; x < bitmap.width(); x++) {
- *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
- }
- }
- }
-
- void replace_char(SkString* str, const char oldChar, const char newChar) {
- if (nullptr == str) {
- return;
- }
- for (size_t i = 0; i < str->size(); ++i) {
- if (oldChar == str->operator[](i)) {
- str->operator[](i) = newChar;
- }
- }
- }
-
- bool is_percentage(const char* const string) {
- SkString skString(string);
- return skString.endsWith("%");
- }
-
- void setup_bitmap(SkBitmap* bitmap, int width, int height) {
- bitmap->allocN32Pixels(width, height);
- bitmap->eraseColor(SK_ColorTRANSPARENT);
- }
-
- bool write_bitmap_to_disk(const SkBitmap& bm, const SkString& dirPath,
- const char *subdirOrNull, const SkString& baseName) {
- SkString partialPath;
- if (subdirOrNull) {
- partialPath = SkOSPath::Join(dirPath.c_str(), subdirOrNull);
- sk_mkdir(partialPath.c_str());
- } else {
- partialPath.set(dirPath);
- }
- SkString fullPath = SkOSPath::Join(partialPath.c_str(), baseName.c_str());
- if (sk_tool_utils::EncodeImageToFile(fullPath.c_str(), bm, SkEncodedImageFormat::kPNG, 100)) {
- return true;
- } else {
- SkDebugf("Failed to write the bitmap to %s.\n", fullPath.c_str());
- return false;
- }
- }
-
- sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap) {
- const int w = bitmap.width(),
- h = bitmap.height();
-
- // PNG wants unpremultiplied 8-bit RGBA pixels (16-bit could work fine too).
- // We leave the gamma of these bytes unspecified, to continue the status quo,
- // which we think generally is to interpret them as sRGB.
-
- SkAutoTMalloc<uint32_t> rgba(w*h);
-
- const void* src = bitmap.getPixels();
- uint32_t* dst = rgba.get();
-
- SkRasterPipeline_<256> p;
- switch (bitmap.colorType()) {
- case kRGBA_F16_SkColorType: p.append(SkRasterPipeline::load_f16, &src); break;
- case kBGRA_8888_SkColorType: p.append(SkRasterPipeline::load_bgra, &src); break;
- case kRGBA_8888_SkColorType: p.append(SkRasterPipeline::load_8888, &src); break;
- case kRGB_565_SkColorType: p.append(SkRasterPipeline::load_565, &src); break;
- default: SkASSERT(false); // DM doesn't support any other formats, does it?
- }
- if (bitmap.info().gammaCloseToSRGB()) {
- p.append_from_srgb(kUnpremul_SkAlphaType);
- }
- p.append(SkRasterPipeline::unpremul);
- p.append(SkRasterPipeline::clamp_0);
- p.append(SkRasterPipeline::clamp_1);
- if (bitmap.info().colorSpace()) {
- // We leave legacy modes as-is. They're already sRGB encoded (kind of).
- p.append(SkRasterPipeline::to_srgb);
- }
- p.append(SkRasterPipeline::store_8888, &dst);
-
- auto run = p.compile();
- for (int y = 0; y < h; y++) {
- run(0,y, w);
- src = SkTAddOffset<const void>(src, bitmap.rowBytes());
- dst += w;
- }
-
- return SkData::MakeFromMalloc(rgba.release(), w*h*sizeof(uint32_t));
- }
-
-} // namespace sk_tools
diff --git a/src/third_party/skia/tools/picture_utils.h b/src/third_party/skia/tools/picture_utils.h
deleted file mode 100644
index 49a2c82..0000000
--- a/src/third_party/skia/tools/picture_utils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef picture_utils_DEFINED
-#define picture_utils_DEFINED
-
-#include "SkBitmap.h"
-
-class SkData;
-class SkString;
-
-namespace sk_tools {
- // since PNG insists on unpremultiplying our alpha, we take no precision
- // chances and force all pixels to be 100% opaque, otherwise on compare we
- // may not get a perfect match.
- //
- // This expects a bitmap with a config type of 8888 and for the pixels to
- // not be on the GPU.
- void force_all_opaque(const SkBitmap& bitmap);
-
- /**
- * Replaces all instances of oldChar with newChar in str.
- */
- void replace_char(SkString* str, const char oldChar, const char newChar);
-
- // Returns true if the string ends with %
- bool is_percentage(const char* const string);
-
- // Prepares the bitmap so that it can be written.
- //
- // Specifically, it configures the bitmap, allocates pixels and then
- // erases the pixels to transparent black.
- void setup_bitmap(SkBitmap* bitmap, int width, int height);
-
- /**
- * Write a bitmap file to disk.
- *
- * @param bm the bitmap to record
- * @param dirPath directory within which to write the image file
- * @param subdirOrNull subdirectory within dirPath, or nullptr to just write into dirPath
- * @param baseName last part of the filename
- *
- * @return true if written out successfully
- */
- bool write_bitmap_to_disk(const SkBitmap& bm, const SkString& dirPath,
- const char *subdirOrNull, const SkString& baseName);
-
- // Return raw unpremultiplied RGBA bytes, suitable for storing in a PNG. The output
- // colors are assumed to be sRGB values. This is only guaranteed to work for the
- // cases that are currently emitted by tools:
- // Linear premul 8888, sRGB premul 8888, Linear premul F16
- sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap);
-
-} // namespace sk_tools
-
-#endif // picture_utils_DEFINED
diff --git a/src/third_party/skia/tools/pinspect.cpp b/src/third_party/skia/tools/pinspect.cpp
deleted file mode 100644
index 29a4222..0000000
--- a/src/third_party/skia/tools/pinspect.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkGraphics.h"
-#include "SkOSFile.h"
-#include "SkPicture.h"
-#include "SkStream.h"
-#include "SkString.h"
-#include "SkDumpCanvas.h"
-
-static sk_sp<SkPicture> inspect(const char path[]) {
- SkFILEStream stream(path);
- if (!stream.isValid()) {
- printf("-- Can't open '%s'\n", path);
- return nullptr;
- }
-
- printf("Opening '%s'...\n", path);
-
- {
- int32_t header[3];
- if (stream.read(header, sizeof(header)) != sizeof(header)) {
- printf("-- Failed to read header (12 bytes)\n");
- return nullptr;
- }
- printf("version:%d width:%d height:%d\n", header[0], header[1], header[2]);
- }
-
- stream.rewind();
- auto pic = SkPicture::MakeFromStream(&stream);
- if (nullptr == pic) {
- SkDebugf("Could not create SkPicture: %s\n", path);
- return nullptr;
- }
- printf("picture cullRect: [%f %f %f %f]\n",
- pic->cullRect().fLeft, pic->cullRect().fTop,
- pic->cullRect().fRight, pic->cullRect().fBottom);
- return pic;
-}
-
-static void dumpOps(SkPicture* pic) {
-#ifdef SK_DEBUG
- SkDebugfDumper dumper;
- SkDumpCanvas canvas(&dumper);
- canvas.drawPicture(pic);
-#else
- printf("SK_DEBUG mode not enabled\n");
-#endif
-}
-
-int main(int argc, char** argv) {
- SkAutoGraphics ag;
- if (argc < 2) {
- printf("Usage: pinspect [--dump-ops] filename [filename ...]\n");
- return 1;
- }
-
- bool doDumpOps = false;
-
- int index = 1;
- if (!strcmp(argv[index], "--dump-ops")) {
- index += 1;
- doDumpOps = true;
- }
-
- for (; index < argc; ++index) {
- auto pic(inspect(argv[index]));
- if (doDumpOps) {
- dumpOps(pic.get());
- }
- if (index < argc - 1) {
- printf("\n");
- }
- }
- return 0;
-}
diff --git a/src/third_party/skia/tools/random_parse_path.cpp b/src/third_party/skia/tools/random_parse_path.cpp
index ffc4b58..4d13f65 100644
--- a/src/third_party/skia/tools/random_parse_path.cpp
+++ b/src/third_party/skia/tools/random_parse_path.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#include "SkRandom.h"
-#include "random_parse_path.h"
+#include "include/utils/SkRandom.h"
+#include "tools/random_parse_path.h"
const struct Legal {
char fSymbol;
diff --git a/src/third_party/skia/tools/random_parse_path.h b/src/third_party/skia/tools/random_parse_path.h
index 4dfa501..7071c8a 100644
--- a/src/third_party/skia/tools/random_parse_path.h
+++ b/src/third_party/skia/tools/random_parse_path.h
@@ -8,7 +8,7 @@
#ifndef random_parse_path_DEFINED
#define random_parse_path_DEFINED
-#include "SkString.h"
+#include "include/core/SkString.h"
class SkRandom;
diff --git a/src/third_party/skia/tools/rebaseline/toggle_legacy_flag.py b/src/third_party/skia/tools/rebaseline/toggle_legacy_flag.py
new file mode 100644
index 0000000..80edeb2
--- /dev/null
+++ b/src/third_party/skia/tools/rebaseline/toggle_legacy_flag.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+README = """
+Automatically add or remove a specific legacy flag to multiple Skia client repos.
+
+This would only work on Google desktop.
+
+Example usage:
+ $ python toggle_legacy_flag.py SK_SUPPORT_LEGACY_SOMETHING \\
+ -a /data/android -c ~/chromium/src -g legacyflag
+
+If you only need to add the flag to one repo, for example, Android, please give
+only -a (--android-dir) argument:
+ $ python toggle_legacy_flag.py SK_SUPPORT_LEGACY_SOMETHING -a /data/android
+
+"""
+
+import os, sys
+import argparse
+import subprocess
+import getpass
+from random import randint
+
+
+ANDROID_TOOLS_DIR = os.path.join(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
+ 'android')
+
+
+def toggle_android(args):
+ sys.path.append(ANDROID_TOOLS_DIR)
+ import upload_to_android
+
+ modifier = upload_to_android.AndroidLegacyFlagModifier(args.flag)
+ upload_to_android.upload_to_android(args.android_dir, modifier)
+
+
+def toggle_chromium(args):
+ os.chdir(args.chromium_dir)
+
+ branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
+ branch = branch.strip()
+
+ EXPECTED_STASH_OUT = "No local changes to save"
+ stash_output = subprocess.check_output(['git', 'stash']).strip()
+
+ if branch != "master" or stash_output != EXPECTED_STASH_OUT:
+ print ("Please checkout a clean master branch at your chromium repo (%s) "
+ "before running this script") % args.chromium_dir
+ if stash_output != EXPECTED_STASH_OUT:
+ subprocess.check_call(['git', 'stash', 'pop'])
+ exit(1)
+
+ # Update the repository to avoid conflicts
+ subprocess.check_call(['git', 'pull'])
+ subprocess.check_call(['gclient', 'sync']);
+
+ # Use random number to avoid branch name collision.
+ # We'll delete the branch in the end.
+ random = randint(1, 10000)
+ subprocess.check_call(['git', 'checkout', '-b', 'legacyflag_%d' % random])
+
+ try:
+ config_file = os.path.join('skia', 'config', 'SkUserConfig.h')
+ with open(config_file) as f:
+ lines = f.readlines()
+
+ flag_line = "#define %s\n" % args.flag
+ if flag_line in lines:
+ index = lines.index(flag_line)
+ del lines[index-1 : index +2]
+ verb = "Remove"
+ else:
+ separator = (
+ "/////////////////////////"
+ " Imported from BUILD.gn and skia_common.gypi\n")
+ content = ("#ifndef {0}\n"
+ "#define {0}\n"
+ "#endif\n\n").format(args.flag)
+ lines.insert(lines.index(separator), content)
+ verb = "Add"
+
+ with open(config_file, 'w') as f:
+ for line in lines:
+ f.write(line)
+
+ message = "%s %s" % (verb, args.flag)
+
+ subprocess.check_call('git commit -a -m "%s"' % message, shell=True)
+ subprocess.check_call('git cl upload -m "%s" -f' % message,
+ shell=True)
+ finally:
+ subprocess.check_call(['git', 'checkout', 'master'])
+ subprocess.check_call(['git', 'branch', '-D', 'legacyflag_%d' % random])
+
+
+def toggle_google3(args):
+ G3_SCRIPT_DIR = os.path.expanduser("~/skia-g3/scripts")
+ if not os.path.isdir(G3_SCRIPT_DIR):
+ print ("Google3 directory unavailable.\n"
+ "Please see "
+ "https://sites.google.com/a/google.com/skia/rebaseline#g3_flag "
+ "for Google3 setup.")
+ exit(1)
+ sys.path.append(G3_SCRIPT_DIR)
+ import citc_flag
+
+ citc_flag.toggle_google3(args.google3, args.flag)
+
+
+def main():
+ if len(sys.argv) <= 1 or sys.argv[1] == '-h' or sys.argv[1] == '--help':
+ print README
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--android-dir', '-a', required=False,
+ help='Directory where an Android checkout will be created (if it does '
+ 'not already exist). Note: ~1GB space will be used.')
+ parser.add_argument(
+ '--chromium-dir', '-c', required=False,
+ help='Directory of an EXISTING Chromium checkout (e.g., ~/chromium/src)')
+ parser.add_argument(
+ '--google3', '-g', required=False,
+ help='Google3 workspace to be created (if it does not already exist).')
+ parser.add_argument('flag', type=str, help='legacy flag name')
+
+ args = parser.parse_args()
+
+ if not args.android_dir and not args.chromium_dir and not args.google3:
+ print """
+Nothing to do. Please give me at least one of these three arguments:
+ -a (--android-dir)
+ -c (--chromium-dir)
+ -g (--google3)
+"""
+ exit(1)
+
+ end_message = "CLs generated. Now go review and land them:\n"
+ if args.chromium_dir:
+ args.chromium_dir = os.path.expanduser(args.chromium_dir)
+ toggle_chromium(args)
+ end_message += " * https://chromium-review.googlesource.com\n"
+ if args.google3:
+ toggle_google3(args)
+ end_message += " * http://goto.google.com/cl\n"
+ if args.android_dir:
+ args.android_dir = os.path.expanduser(args.android_dir)
+ toggle_android(args)
+ end_message += " * http://goto.google.com/androidcl\n"
+
+ print end_message
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/remote_demo.cpp b/src/third_party/skia/tools/remote_demo.cpp
new file mode 100644
index 0000000..91fd124
--- /dev/null
+++ b/src/third_party/skia/tools/remote_demo.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <chrono>
+#include <err.h>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <thread>
+#include <unistd.h>
+
+#include "include/core/SkGraphics.h"
+#include "include/core/SkSurface.h"
+#include "src/core/SkRemoteGlyphCache.h"
+#include "src/core/SkScalerContext.h"
+
+static std::string gSkpName;
+static bool gUseGpu = true;
+static bool gPurgeFontCaches = true;
+static bool gUseProcess = true;
+
+class ServerDiscardableManager : public SkStrikeServer::DiscardableHandleManager {
+public:
+ ServerDiscardableManager() = default;
+ ~ServerDiscardableManager() override = default;
+
+ SkDiscardableHandleId createHandle() override { return ++nextHandleId; }
+ bool lockHandle(SkDiscardableHandleId handleId) override {
+ return handleId > lastPurgedHandleId;
+ }
+ void purgeAll() { lastPurgedHandleId = nextHandleId; }
+
+private:
+ SkDiscardableHandleId nextHandleId = 0u;
+ SkDiscardableHandleId lastPurgedHandleId = 0u;
+};
+
+class ClientDiscardableManager : public SkStrikeClient::DiscardableHandleManager {
+public:
+ class ScopedPurgeCache {
+ public:
+ ScopedPurgeCache(ClientDiscardableManager* manager) : fManager(manager) {
+ if (fManager) fManager->allowPurging = true;
+ }
+ ~ScopedPurgeCache() {
+ if (fManager) fManager->allowPurging = false;
+ }
+
+ private:
+ ClientDiscardableManager* fManager;
+ };
+
+ ClientDiscardableManager() = default;
+ ~ClientDiscardableManager() override = default;
+
+ bool deleteHandle(SkDiscardableHandleId) override { return allowPurging; }
+
+private:
+ bool allowPurging = false;
+};
+
+static bool write_SkData(int fd, const SkData& data) {
+ size_t size = data.size();
+ ssize_t bytesWritten = ::write(fd, &size, sizeof(size));
+ if (bytesWritten < 0) {
+ err(1,"Failed write %zu", size);
+ return false;
+ }
+
+ bytesWritten = ::write(fd, data.data(), data.size());
+ if (bytesWritten < 0) {
+ err(1,"Failed write %zu", size);
+ return false;
+ }
+
+ return true;
+}
+
+static sk_sp<SkData> read_SkData(int fd) {
+ size_t size;
+ ssize_t readSize = ::read(fd, &size, sizeof(size));
+ if (readSize <= 0) {
+ if (readSize < 0) {
+ err(1, "Failed read %zu", size);
+ }
+ return nullptr;
+ }
+
+ auto out = SkData::MakeUninitialized(size);
+ auto data = (uint8_t*)out->data();
+
+ size_t totalRead = 0;
+ while (totalRead < size) {
+ ssize_t sizeRead;
+ sizeRead = ::read(fd, &data[totalRead], size - totalRead);
+ if (sizeRead <= 0) {
+ if (readSize < 0) {
+ err(1, "Failed read %zu", size);
+ }
+ return nullptr;
+ }
+ totalRead += sizeRead;
+ }
+
+ return out;
+}
+
+class Timer {
+public:
+ void start() {
+ fStart = std::chrono::high_resolution_clock::now();
+ }
+
+ void stop() {
+ auto end = std::chrono::high_resolution_clock::now();
+ fElapsedSeconds += end - fStart;
+ }
+
+ double elapsedSeconds() {
+ return fElapsedSeconds.count();
+ }
+
+private:
+ decltype(std::chrono::high_resolution_clock::now()) fStart;
+ std::chrono::duration<double> fElapsedSeconds{0.0};
+};
+
+static bool push_font_data(const SkPicture& pic, SkStrikeServer* strikeServer,
+ sk_sp<SkColorSpace> colorSpace, int writeFd) {
+ const SkIRect bounds = pic.cullRect().round();
+ const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
+ SkTextBlobCacheDiffCanvas filter(bounds.width(), bounds.height(), props,
+ strikeServer, std::move(colorSpace), true);
+ pic.playback(&filter);
+
+ std::vector<uint8_t> fontData;
+ strikeServer->writeStrikeData(&fontData);
+ auto data = SkData::MakeWithoutCopy(fontData.data(), fontData.size());
+ return write_SkData(writeFd, *data);
+}
+
+static void final_draw(std::string outFilename, SkData* picData, SkStrikeClient* client,
+ ClientDiscardableManager* discardableManager, int readFd, int writeFd) {
+ SkDeserialProcs procs;
+ auto decode = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
+ return reinterpret_cast<SkStrikeClient*>(ctx)->deserializeTypeface(data, length);
+ };
+ procs.fTypefaceProc = decode;
+ procs.fTypefaceCtx = client;
+
+ auto pic = SkPicture::MakeFromData(picData, &procs);
+
+ auto cullRect = pic->cullRect();
+ auto r = cullRect.round();
+
+ auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
+ auto c = s->getCanvas();
+ auto picUnderTest = SkPicture::MakeFromData(picData, &procs);
+
+ Timer drawTime;
+ auto randomData = SkData::MakeUninitialized(1u);
+ for (int i = 0; i < 100; i++) {
+ if (gPurgeFontCaches) {
+ ClientDiscardableManager::ScopedPurgeCache purge(discardableManager);
+ SkGraphics::PurgeFontCache();
+ SkASSERT(SkGraphics::GetFontCacheUsed() == 0u);
+ }
+
+ drawTime.start();
+ if (client != nullptr) {
+ // Kick the renderer to send us the fonts.
+ write_SkData(writeFd, *randomData);
+ auto fontData = read_SkData(readFd);
+ if (fontData && !fontData->isEmpty()) {
+ if (!client->readStrikeData(fontData->data(), fontData->size()))
+ SK_ABORT("Bad serialization");
+ }
+ }
+ c->drawPicture(picUnderTest);
+ drawTime.stop();
+ }
+
+ std::cout << "useProcess: " << gUseProcess
+ << " useGPU: " << gUseGpu
+ << " purgeCache: " << gPurgeFontCaches << std::endl;
+ fprintf(stderr, "%s use GPU %s elapsed time %8.6f s\n", gSkpName.c_str(),
+ gUseGpu ? "true" : "false", drawTime.elapsedSeconds());
+
+ auto i = s->makeImageSnapshot();
+ auto data = i->encodeToData();
+ SkFILEWStream f(outFilename.c_str());
+ f.write(data->data(), data->size());
+}
+
+static void gpu(int readFd, int writeFd) {
+
+ if (gUseGpu) {
+ auto picData = read_SkData(readFd);
+ if (picData == nullptr) {
+ return;
+ }
+
+ sk_sp<ClientDiscardableManager> discardableManager = sk_make_sp<ClientDiscardableManager>();
+ SkStrikeClient strikeClient(discardableManager);
+
+ final_draw("test.png", picData.get(), &strikeClient, discardableManager.get(), readFd,
+ writeFd);
+ }
+
+ ::close(writeFd);
+ ::close(readFd);
+
+ printf("GPU is exiting\n");
+}
+
+static int renderer(
+ const std::string& skpName, int readFd, int writeFd)
+{
+ ServerDiscardableManager discardableManager;
+ SkStrikeServer server(&discardableManager);
+ auto closeAll = [readFd, writeFd]() {
+ ::close(writeFd);
+ ::close(readFd);
+ };
+
+ auto skpData = SkData::MakeFromFileName(skpName.c_str());
+ std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl;
+
+ sk_sp<SkData> stream;
+ if (gUseGpu) {
+ auto pic = SkPicture::MakeFromData(skpData.get());
+ auto colorSpace = SkColorSpace::MakeSRGB();
+ SkSerialProcs procs;
+ auto encode = [](SkTypeface* tf, void* ctx) -> sk_sp<SkData> {
+ return reinterpret_cast<SkStrikeServer*>(ctx)->serializeTypeface(tf);
+ };
+ procs.fTypefaceProc = encode;
+ procs.fTypefaceCtx = &server;
+
+ stream = pic->serialize(&procs);
+
+ if (!write_SkData(writeFd, *stream)) {
+ closeAll();
+ return 1;
+ }
+
+ while (true) {
+ auto inBuffer = read_SkData(readFd);
+ if (inBuffer == nullptr) {
+ closeAll();
+ return 0;
+ }
+ if (gPurgeFontCaches) discardableManager.purgeAll();
+ push_font_data(*pic.get(), &server, colorSpace, writeFd);
+ }
+ } else {
+ stream = skpData;
+ final_draw("test-correct.png", stream.get(), nullptr, nullptr, -1, -1);
+ closeAll();
+ return 0;
+ }
+}
+
+int main(int argc, char** argv) {
+ std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"skps/desk_nytimes.skp"};
+ int mode = argc > 2 ? atoi(argv[2]) : -1;
+ printf("skp: %s\n", skpName.c_str());
+
+ gSkpName = skpName;
+
+ enum direction : int {kRead = 0, kWrite = 1};
+
+
+ int render_to_gpu[2],
+ gpu_to_render[2];
+
+ for (int m = 0; m < 8; m++) {
+ int r = pipe(render_to_gpu);
+ if (r < 0) {
+ perror("Can't write picture from render to GPU ");
+ return 1;
+ }
+ r = pipe(gpu_to_render);
+ if (r < 0) {
+ perror("Can't write picture from render to GPU ");
+ return 1;
+ }
+
+ gPurgeFontCaches = (m & 4) == 4;
+ gUseGpu = (m & 2) == 2;
+ gUseProcess = (m & 1) == 1;
+
+ if (mode >= 0 && mode < 8 && mode != m) {
+ continue;
+ }
+
+ if (gUseProcess) {
+ pid_t child = fork();
+ SkGraphics::Init();
+
+ if (child == 0) {
+ close(gpu_to_render[kRead]);
+ close(render_to_gpu[kWrite]);
+ gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
+ } else {
+ close(render_to_gpu[kRead]);
+ close(gpu_to_render[kWrite]);
+ renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
+ waitpid(child, nullptr, 0);
+ }
+ } else {
+ SkGraphics::Init();
+ std::thread(gpu, render_to_gpu[kRead], gpu_to_render[kWrite]).detach();
+ renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/third_party/skia/tools/rewrite_includes.py b/src/third_party/skia/tools/rewrite_includes.py
new file mode 100644
index 0000000..d0ee8f8
--- /dev/null
+++ b/src/third_party/skia/tools/rewrite_includes.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python2
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import StringIO
+import argparse
+import os
+import sys
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-n', '--dry-run', action='store_true',
+ help='Just check there is nothing to rewrite.')
+parser.add_argument('sources', nargs='*',
+ help='Source files to rewrite, or all if empty.')
+args = parser.parse_args()
+
+roots = [
+ 'bench',
+ 'dm',
+ 'docs',
+ 'example',
+ 'experimental',
+ 'fuzz',
+ 'gm',
+ 'include',
+ 'modules',
+ 'platform_tools/android/apps',
+ 'samplecode',
+ 'src',
+ 'tests',
+ 'third_party/etc1',
+ 'third_party/gif',
+ 'tools'
+ ]
+
+# Don't count our local Vulkan headers as Skia headers;
+# we don't want #include <vulkan/vulkan_foo.h> rewritten to point to them.
+blacklist = ['include/third_party/vulkan']
+
+assert '/' in [os.sep, os.altsep]
+def fix_path(p):
+ return p.replace(os.sep, os.altsep) if os.altsep else p
+
+# Map short name -> absolute path for all Skia headers.
+headers = {}
+for root in roots:
+ for path, _, files in os.walk(root):
+ if not any(snippet in fix_path(path) for snippet in blacklist):
+ for file_name in files:
+ if file_name.endswith('.h'):
+ if file_name in headers:
+ print path, file_name, headers[file_name]
+ assert file_name not in headers
+ headers[file_name] = os.path.abspath(os.path.join(path, file_name))
+
+def to_rewrite():
+ if args.sources:
+ for path in args.sources:
+ yield path
+ else:
+ for root in roots:
+ for path, _, files in os.walk(root):
+ for file_name in files:
+ yield os.path.join(path, file_name)
+
+# Rewrite any #includes relative to Skia's top-level directory.
+need_rewriting = []
+for file_path in to_rewrite():
+ if 'generated' in file_path or 'third_party/skcms' in file_path:
+ continue
+ if (file_path.endswith('.h') or
+ file_path.endswith('.c') or
+ file_path.endswith('.m') or
+ file_path.endswith('.mm') or
+ file_path.endswith('.inc') or
+ file_path.endswith('.fp') or
+ file_path.endswith('.cc') or
+ file_path.endswith('.cpp')):
+ # Read the whole file into memory.
+ lines = open(file_path).readlines()
+
+ # Write it back out again line by line with substitutions for #includes.
+ output = StringIO.StringIO() if args.dry_run else open(file_path, 'wb')
+
+ includes = []
+ for line in lines:
+ parts = line.replace('<', '"').replace('>', '"').split('"')
+ if (len(parts) == 3
+ and '#' in parts[0]
+ and 'include' in parts[0]
+ and os.path.basename(parts[1]) in headers):
+ header = fix_path(os.path.relpath(headers[os.path.basename(parts[1])], '.'))
+ includes.append(parts[0] + '"%s"' % header + parts[2])
+ else:
+ for inc in sorted(includes):
+ output.write(inc.strip('\n') + '\n')
+ includes = []
+ output.write(line.strip('\n') + '\n')
+
+ if args.dry_run and output.getvalue() != open(file_path).read():
+ need_rewriting.append(file_path)
+ rc = 1
+ output.close()
+
+if need_rewriting:
+ print 'Some files need rewritten #includes:'
+ for path in need_rewriting:
+ print '\t' + path
+ print 'To do this automatically, run'
+ print 'python tools/rewrite_includes.py ' + ' '.join(need_rewriting)
+ sys.exit(1)
diff --git a/src/third_party/skia/tools/viewer/sk_app/Application.h b/src/third_party/skia/tools/sk_app/Application.h
similarity index 100%
rename from src/third_party/skia/tools/viewer/sk_app/Application.h
rename to src/third_party/skia/tools/sk_app/Application.h
diff --git a/src/third_party/skia/tools/viewer/sk_app/CommandSet.cpp b/src/third_party/skia/tools/sk_app/CommandSet.cpp
similarity index 75%
rename from src/third_party/skia/tools/viewer/sk_app/CommandSet.cpp
rename to src/third_party/skia/tools/sk_app/CommandSet.cpp
index d0154d6..ea0eb13 100644
--- a/src/third_party/skia/tools/viewer/sk_app/CommandSet.cpp
+++ b/src/third_party/skia/tools/sk_app/CommandSet.cpp
@@ -5,10 +5,11 @@
* found in the LICENSE file.
*/
-#include "CommandSet.h"
+#include "tools/sk_app/CommandSet.h"
-#include "SkCanvas.h"
-#include "SkTSort.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFont.h"
+#include "src/core/SkTSort.h"
namespace sk_app {
@@ -34,8 +35,8 @@
fWindow = window;
}
-bool CommandSet::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) {
- if (Window::kDown_InputState == state) {
+bool CommandSet::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {
+ if (skui::InputState::kDown == state) {
for (Command& cmd : fCommands) {
if (Command::kKey_CommandType == cmd.fType && key == cmd.fKey) {
cmd.fFunction();
@@ -47,7 +48,7 @@
return false;
}
-bool CommandSet::onChar(SkUnichar c, uint32_t modifiers) {
+bool CommandSet::onChar(SkUnichar c, skui::ModifierKey modifiers) {
for (Command& cmd : fCommands) {
if (Command::kChar_CommandType == cmd.fType && c == cmd.fChar) {
cmd.fFunction();
@@ -73,12 +74,12 @@
fCommands.push_back(Command(c, group, description, function));
}
-void CommandSet::addCommand(Window::Key k, const char* keyName, const char* group,
+void CommandSet::addCommand(skui::Key k, const char* keyName, const char* group,
const char* description, std::function<void(void)> function) {
fCommands.push_back(Command(k, keyName, group, description, function));
}
-#if defined(SK_BUILD_FOR_WIN32)
+#if defined(SK_BUILD_FOR_WIN)
#define SK_strcasecmp _stricmp
#else
#define SK_strcasecmp strcasecmp
@@ -101,17 +102,21 @@
SkTQSort(fCommands.begin(), fCommands.end() - 1,
kAlphabetical_HelpMode == fHelpMode ? compareCommandKey : compareCommandGroup);
+ SkFont font;
+ font.setSize(16);
+
+ SkFont groupFont;
+ groupFont.setSize(18);
+
SkPaint bgPaint;
bgPaint.setColor(0xC0000000);
canvas->drawPaint(bgPaint);
SkPaint paint;
- paint.setTextSize(16);
paint.setAntiAlias(true);
paint.setColor(0xFFFFFFFF);
SkPaint groupPaint;
- groupPaint.setTextSize(18);
groupPaint.setAntiAlias(true);
groupPaint.setColor(0xFFFFFFFF);
@@ -122,14 +127,15 @@
SkScalar keyWidth = 0;
for (Command& cmd : fCommands) {
keyWidth = SkMaxScalar(keyWidth,
- paint.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size()));
+ font.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size(),
+ SkTextEncoding::kUTF8));
}
- keyWidth += paint.measureText(" ", 1);
+ keyWidth += font.measureText(" ", 1, SkTextEncoding::kUTF8);
// If we're grouping by category, we'll be adding text height on every new group (including the
// first), so no need to do that here. Otherwise, skip down so the first line is where we want.
if (kGrouped_HelpMode != fHelpMode) {
- y += paint.getTextSize();
+ y += font.getSize();
}
// Print everything:
@@ -137,16 +143,18 @@
for (Command& cmd : fCommands) {
if (kGrouped_HelpMode == fHelpMode && lastGroup != cmd.fGroup) {
// Group change. Advance and print header:
- y += paint.getTextSize();
- canvas->drawString(cmd.fGroup, x, y, groupPaint);
- y += groupPaint.getTextSize() + 2;
+ y += font.getSize();
+ canvas->drawSimpleText(cmd.fGroup.c_str(), cmd.fGroup.size(), SkTextEncoding::kUTF8,
+ x, y, groupFont, groupPaint);
+ y += groupFont.getSize() + 2;
lastGroup = cmd.fGroup;
}
- canvas->drawString(cmd.fKeyName, x, y, paint);
+ canvas->drawSimpleText(cmd.fKeyName.c_str(), cmd.fKeyName.size(), SkTextEncoding::kUTF8,
+ x, y, font, paint);
SkString text = SkStringPrintf(": %s", cmd.fDescription.c_str());
- canvas->drawString(text, x + keyWidth, y, paint);
- y += paint.getTextSize() + 2;
+ canvas->drawString(text, x + keyWidth, y, font, paint);
+ y += font.getSize() + 2;
}
}
diff --git a/src/third_party/skia/tools/viewer/sk_app/CommandSet.h b/src/third_party/skia/tools/sk_app/CommandSet.h
similarity index 88%
rename from src/third_party/skia/tools/viewer/sk_app/CommandSet.h
rename to src/third_party/skia/tools/sk_app/CommandSet.h
index 0784a38..07a7def 100644
--- a/src/third_party/skia/tools/viewer/sk_app/CommandSet.h
+++ b/src/third_party/skia/tools/sk_app/CommandSet.h
@@ -8,8 +8,8 @@
#ifndef CommandSet_DEFINED
#define CommandSet_DEFINED
-#include "SkString.h"
-#include "Window.h"
+#include "include/core/SkString.h"
+#include "tools/sk_app/Window.h"
#include <functional>
#include <vector>
@@ -41,13 +41,13 @@
CommandSet();
void attach(Window* window);
- bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
- bool onChar(SkUnichar, uint32_t modifiers);
+ bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers);
+ bool onChar(SkUnichar, skui::ModifierKey modifiers);
bool onSoftkey(const SkString& softkey);
void addCommand(SkUnichar c, const char* group, const char* description,
std::function<void(void)> function);
- void addCommand(Window::Key k, const char* keyName, const char* group, const char* description,
+ void addCommand(skui::Key k, const char* keyName, const char* group, const char* description,
std::function<void(void)> function);
void drawHelp(SkCanvas* canvas);
@@ -70,7 +70,7 @@
, fDescription(description)
, fFunction(function) {}
- Command(Window::Key k, const char* keyName, const char* group, const char* description,
+ Command(skui::Key k, const char* keyName, const char* group, const char* description,
std::function<void(void)> function)
: fType(kKey_CommandType)
, fKey(k)
@@ -85,7 +85,7 @@
SkUnichar fChar;
// For kKey_CommandType
- Window::Key fKey;
+ skui::Key fKey;
// Common to all command types
SkString fKeyName;
diff --git a/src/third_party/skia/tools/sk_app/DawnWindowContext.cpp b/src/third_party/skia/tools/sk_app/DawnWindowContext.cpp
new file mode 100644
index 0000000..1d9b58e
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/DawnWindowContext.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContext.h"
+#include "src/core/SkAutoMalloc.h"
+#include "tools/sk_app/DawnWindowContext.h"
+
+#include "dawn/dawn_proc.h"
+
+static void PrintDeviceError(DawnErrorType, const char* message, void*) {
+ printf("Device error: %s\n", message);
+ SkASSERT(false);
+}
+
+namespace sk_app {
+
+DawnWindowContext::DawnWindowContext(const DisplayParams& params,
+ dawn::TextureFormat swapChainFormat)
+ : WindowContext(params)
+ , fSwapChainFormat(swapChainFormat)
+ , fInstance(std::make_unique<dawn_native::Instance>()) {
+}
+
+void DawnWindowContext::initializeContext(int width, int height) {
+ fWidth = width;
+ fHeight = height;
+ fDevice = onInitializeContext();
+ fContext = GrContext::MakeDawn(fDevice, fDisplayParams.fGrContextOptions);
+
+ if (!fContext) {
+ return;
+ }
+ fSwapChainImplementation = this->createSwapChainImplementation(-1, -1, fDisplayParams);
+ dawn::SwapChainDescriptor swapChainDesc;
+ swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
+ fSwapChain = fDevice.CreateSwapChain(&swapChainDesc);
+ if (!fSwapChain) {
+ fContext.reset();
+ return;
+ }
+ fSwapChain.Configure(fSwapChainFormat, dawn::TextureUsage::OutputAttachment, width, height);
+ fDevice.SetUncapturedErrorCallback(PrintDeviceError, 0);
+}
+
+DawnWindowContext::~DawnWindowContext() {
+}
+
+void DawnWindowContext::destroyContext() {
+ if (!fDevice.Get()) {
+ return;
+ }
+
+ this->onDestroyContext();
+
+ fContext.reset();
+ fDevice = nullptr;
+}
+
+sk_sp<SkSurface> DawnWindowContext::getBackbufferSurface() {
+ GrDawnImageInfo imageInfo;
+ imageInfo.fTexture = fSwapChain.GetNextTexture();
+ imageInfo.fFormat = fSwapChainFormat;
+ imageInfo.fLevelCount = 1; // FIXME
+ GrBackendTexture backendTexture(fWidth, fHeight, imageInfo);
+ fSurface = SkSurface::MakeFromBackendTextureAsRenderTarget(fContext.get(),
+ backendTexture,
+ this->getRTOrigin(),
+ fDisplayParams.fMSAASampleCount,
+ fDisplayParams.fColorType,
+ fDisplayParams.fColorSpace,
+ &fDisplayParams.fSurfaceProps);
+ return fSurface;
+}
+
+void DawnWindowContext::swapBuffers() {
+ GrBackendRenderTarget backendRT = fSurface->getBackendRenderTarget(
+ SkSurface::kFlushRead_BackendHandleAccess);
+ GrDawnImageInfo imageInfo;
+ SkAssertResult(backendRT.getDawnImageInfo(&imageInfo));
+
+ fSwapChain.Present(imageInfo.fTexture);
+ this->onSwapBuffers();
+}
+
+void DawnWindowContext::resize(int w, int h) {
+ fWidth = w;
+ fHeight = h;
+ fSwapChainImplementation = this->createSwapChainImplementation(w, h, fDisplayParams);
+ dawn::SwapChainDescriptor swapChainDesc;
+ swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
+ fSwapChain = fDevice.CreateSwapChain(&swapChainDesc);
+ if (!fSwapChain) {
+ fContext.reset();
+ return;
+ }
+ fSwapChain.Configure(fSwapChainFormat, dawn::TextureUsage::OutputAttachment, fWidth,
+ fHeight);
+}
+
+void DawnWindowContext::setDisplayParams(const DisplayParams& params) {
+ fDisplayParams = params;
+}
+
+dawn::Device DawnWindowContext::createDevice(dawn_native::BackendType type) {
+ fInstance->DiscoverDefaultAdapters();
+ DawnProcTable backendProcs = dawn_native::GetProcs();
+ dawnProcSetProcs(&backendProcs);
+
+ std::vector<dawn_native::Adapter> adapters = fInstance->GetAdapters();
+ for (dawn_native::Adapter adapter : adapters) {
+ if (adapter.GetBackendType() == type) {
+ return adapter.CreateDevice();
+ }
+ }
+ return nullptr;
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/DawnWindowContext.h b/src/third_party/skia/tools/sk_app/DawnWindowContext.h
new file mode 100644
index 0000000..6c2e1c9
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/DawnWindowContext.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef DawnWindowContext_DEFINED
+#define DawnWindowContext_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurface.h"
+
+#include "tools/sk_app/WindowContext.h"
+#include "dawn/dawncpp.h"
+#include "dawn_native/DawnNative.h"
+#include "dawn/dawn_wsi.h"
+
+class GrContext;
+
+namespace sk_app {
+
+class DawnWindowContext : public WindowContext {
+public:
+ DawnWindowContext(const DisplayParams&, dawn::TextureFormat swapChainFormat);
+ ~DawnWindowContext() override;
+ sk_sp<SkSurface> getBackbufferSurface() override;
+ void swapBuffers() override;
+ bool isValid() override { return SkToBool(fDevice.Get()); }
+
+ void resize(int w, int h) override;
+
+ void setDisplayParams(const DisplayParams& params) override;
+
+protected:
+ bool isGpuContext() override { return true; }
+ void initializeContext(int width, int height);
+ dawn::Device createDevice(dawn_native::BackendType type);
+ virtual dawn::Device onInitializeContext() = 0;
+ virtual void onDestroyContext() = 0;
+ virtual void onSwapBuffers() = 0;
+ virtual GrSurfaceOrigin getRTOrigin() const { return kTopLeft_GrSurfaceOrigin; }
+ void destroyContext();
+ virtual DawnSwapChainImplementation createSwapChainImplementation( int width, int height,
+ const DisplayParams& params) = 0;
+
+ sk_sp<SkSurface> fSurface;
+ DawnSwapChainImplementation fSwapChainImplementation;
+ dawn::TextureFormat fSwapChainFormat;
+ dawn::SwapChain fSwapChain;
+ dawn::Device fDevice;
+ std::unique_ptr<dawn_native::Instance> fInstance;
+};
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/DisplayParams.h b/src/third_party/skia/tools/sk_app/DisplayParams.h
similarity index 61%
rename from src/third_party/skia/tools/viewer/sk_app/DisplayParams.h
rename to src/third_party/skia/tools/sk_app/DisplayParams.h
index 959735e..afad8e1 100644
--- a/src/third_party/skia/tools/viewer/sk_app/DisplayParams.h
+++ b/src/third_party/skia/tools/sk_app/DisplayParams.h
@@ -7,8 +7,9 @@
#ifndef DisplayParams_DEFINED
#define DisplayParams_DEFINED
-#include "GrContextOptions.h"
-#include "SkImageInfo.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkSurfaceProps.h"
+#include "include/gpu/GrContextOptions.h"
namespace sk_app {
@@ -16,12 +17,17 @@
DisplayParams()
: fColorType(kN32_SkColorType)
, fColorSpace(nullptr)
- , fMSAASampleCount(0) {}
+ , fMSAASampleCount(1)
+ , fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
+ , fDisableVsync(false)
+ {}
SkColorType fColorType;
sk_sp<SkColorSpace> fColorSpace;
int fMSAASampleCount;
GrContextOptions fGrContextOptions;
+ SkSurfaceProps fSurfaceProps;
+ bool fDisableVsync;
};
} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/GLWindowContext.cpp b/src/third_party/skia/tools/sk_app/GLWindowContext.cpp
new file mode 100644
index 0000000..6e6130b
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/GLWindowContext.cpp
@@ -0,0 +1,98 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContext.h"
+#include "src/core/SkMathPriv.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/gl/GrGLDefines.h"
+#include "src/gpu/gl/GrGLUtil.h"
+#include "src/image/SkImage_Base.h"
+#include "tools/sk_app/GLWindowContext.h"
+
+namespace sk_app {
+
+GLWindowContext::GLWindowContext(const DisplayParams& params)
+ : WindowContext(params)
+ , fBackendContext(nullptr)
+ , fSurface(nullptr) {
+ fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
+}
+
+void GLWindowContext::initializeContext() {
+ SkASSERT(!fContext);
+
+ fBackendContext = this->onInitializeContext();
+ fContext = GrContext::MakeGL(fBackendContext, fDisplayParams.fGrContextOptions);
+ if (!fContext && fDisplayParams.fMSAASampleCount > 1) {
+ fDisplayParams.fMSAASampleCount /= 2;
+ this->initializeContext();
+ return;
+ }
+}
+
+void GLWindowContext::destroyContext() {
+ fSurface.reset(nullptr);
+
+ if (fContext) {
+ // in case we have outstanding refs to this guy (lua?)
+ fContext->abandonContext();
+ fContext.reset();
+ }
+
+ fBackendContext.reset(nullptr);
+
+ this->onDestroyContext();
+}
+
+sk_sp<SkSurface> GLWindowContext::getBackbufferSurface() {
+ if (nullptr == fSurface) {
+ if (fContext) {
+ GrGLint buffer;
+ GR_GL_CALL(fBackendContext.get(), GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer));
+
+ GrGLFramebufferInfo fbInfo;
+ fbInfo.fFBOID = buffer;
+ fbInfo.fFormat = GR_GL_RGBA8;
+
+ GrBackendRenderTarget backendRT(fWidth,
+ fHeight,
+ fSampleCount,
+ fStencilBits,
+ fbInfo);
+
+ fSurface = SkSurface::MakeFromBackendRenderTarget(fContext.get(), backendRT,
+ kBottomLeft_GrSurfaceOrigin,
+ kRGBA_8888_SkColorType,
+ fDisplayParams.fColorSpace,
+ &fDisplayParams.fSurfaceProps);
+ }
+ }
+
+ return fSurface;
+}
+
+void GLWindowContext::swapBuffers() {
+ this->onSwapBuffers();
+}
+
+void GLWindowContext::resize(int w, int h) {
+ this->destroyContext();
+ this->initializeContext();
+}
+
+void GLWindowContext::setDisplayParams(const DisplayParams& params) {
+ fDisplayParams = params;
+ this->destroyContext();
+ this->initializeContext();
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/GLWindowContext.h b/src/third_party/skia/tools/sk_app/GLWindowContext.h
similarity index 82%
rename from src/third_party/skia/tools/viewer/sk_app/GLWindowContext.h
rename to src/third_party/skia/tools/sk_app/GLWindowContext.h
index 09d544a..8d3085b 100644
--- a/src/third_party/skia/tools/viewer/sk_app/GLWindowContext.h
+++ b/src/third_party/skia/tools/sk_app/GLWindowContext.h
@@ -9,12 +9,12 @@
#define GLWindowContext_DEFINED
-#include "gl/GrGLInterface.h"
+#include "include/gpu/gl/GrGLInterface.h"
-#include "SkRefCnt.h"
-#include "SkSurface.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurface.h"
-#include "WindowContext.h"
+#include "tools/sk_app/WindowContext.h"
class GrContext;
@@ -31,16 +31,12 @@
void setDisplayParams(const DisplayParams& params) override;
- GrBackendContext getBackendContext() override {
- return (GrBackendContext) fBackendContext.get();
- }
-
protected:
GLWindowContext(const DisplayParams&);
// This should be called by subclass constructor. It is also called when window/display
// parameters change. This will in turn call onInitializeContext().
void initializeContext();
- virtual void onInitializeContext() = 0;
+ virtual sk_sp<const GrGLInterface> onInitializeContext() = 0;
// This should be called by subclass destructor. It is also called when window/display
// parameters change prior to initializing a new GL context. This will in turn call
diff --git a/src/third_party/skia/tools/sk_app/MetalWindowContext.h b/src/third_party/skia/tools/sk_app/MetalWindowContext.h
new file mode 100644
index 0000000..8fe19bf
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/MetalWindowContext.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef MetalWindowContext_DEFINED
+#define MetalWindowContext_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurface.h"
+
+#include "tools/sk_app/WindowContext.h"
+
+#import <Metal/Metal.h>
+#import <QuartzCore/CAMetalLayer.h>
+
+namespace sk_app {
+
+class MetalWindowContext : public WindowContext {
+public:
+ sk_sp<SkSurface> getBackbufferSurface() override;
+
+ bool isValid() override { return fValid; }
+
+ void swapBuffers() override;
+
+ void setDisplayParams(const DisplayParams& params) override;
+
+protected:
+ MetalWindowContext(const DisplayParams&);
+ // This should be called by subclass constructor. It is also called when window/display
+ // parameters change. This will in turn call onInitializeContext().
+ void initializeContext();
+ virtual bool onInitializeContext() = 0;
+
+ // This should be called by subclass destructor. It is also called when window/display
+ // parameters change prior to initializing a new Metal context. This will in turn call
+ // onDestroyContext().
+ void destroyContext();
+ virtual void onDestroyContext() = 0;
+
+ bool fValid;
+ id<MTLDevice> fDevice;
+ id<MTLCommandQueue> fQueue;
+ CAMetalLayer* fMetalLayer;
+ id<CAMetalDrawable> fCurrentDrawable;
+};
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/MetalWindowContext.mm b/src/third_party/skia/tools/sk_app/MetalWindowContext.mm
new file mode 100644
index 0000000..fbcc849
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/MetalWindowContext.mm
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/mtl/GrMtlTypes.h"
+#include "src/core/SkMathPriv.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/image/SkImage_Base.h"
+#include "tools/sk_app/MetalWindowContext.h"
+
+using sk_app::DisplayParams;
+using sk_app::MetalWindowContext;
+
+namespace sk_app {
+
+MetalWindowContext::MetalWindowContext(const DisplayParams& params)
+ : WindowContext(params)
+ , fValid(false) {
+
+ fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
+}
+
+void MetalWindowContext::initializeContext() {
+ SkASSERT(!fContext);
+
+ fDevice = MTLCreateSystemDefaultDevice();
+ fQueue = [fDevice newCommandQueue];
+
+ if (fDisplayParams.fMSAASampleCount > 1) {
+ if (@available(macOS 10.11, iOS 9.0, *)) {
+ if (![fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+ fSampleCount = fDisplayParams.fMSAASampleCount;
+ fStencilBits = 8;
+
+ fValid = this->onInitializeContext();
+
+ fContext = GrContext::MakeMetal((__bridge void*)fDevice, (__bridge void*)fQueue,
+ fDisplayParams.fGrContextOptions);
+ if (!fContext && fDisplayParams.fMSAASampleCount > 1) {
+ fDisplayParams.fMSAASampleCount /= 2;
+ this->initializeContext();
+ return;
+ }
+}
+
+void MetalWindowContext::destroyContext() {
+ if (fContext) {
+ // in case we have outstanding refs to this guy (lua?)
+ fContext->abandonContext();
+ fContext.reset();
+ }
+
+ this->onDestroyContext();
+
+ fMetalLayer = nil;
+ fValid = false;
+
+ [fQueue release];
+ [fDevice release];
+}
+
+sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
+ sk_sp<SkSurface> surface;
+ if (fContext) {
+ GrMTLHandle drawable;
+ surface = SkSurface::MakeFromCAMetalLayer(fContext.get(), (__bridge GrMTLHandle)fMetalLayer,
+ kTopLeft_GrSurfaceOrigin, fSampleCount,
+ kBGRA_8888_SkColorType,
+ fDisplayParams.fColorSpace,
+ &fDisplayParams.fSurfaceProps,
+ &drawable);
+ // ARC is off in sk_app, so we need to release the CF ref manually
+ fCurrentDrawable = (id<CAMetalDrawable>)drawable;
+ CFRelease(drawable);
+ }
+
+ return surface;
+}
+
+void MetalWindowContext::swapBuffers() {
+ id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
+ commandBuffer.label = @"Present";
+
+ [commandBuffer presentDrawable:fCurrentDrawable];
+ [commandBuffer commit];
+ fCurrentDrawable = nil;
+}
+
+void MetalWindowContext::setDisplayParams(const DisplayParams& params) {
+ this->destroyContext();
+ fDisplayParams = params;
+ this->initializeContext();
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h b/src/third_party/skia/tools/sk_app/RasterWindowContext.h
similarity index 70%
rename from src/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h
rename to src/third_party/skia/tools/sk_app/RasterWindowContext.h
index 75bde03..4a01aab 100644
--- a/src/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h
+++ b/src/third_party/skia/tools/sk_app/RasterWindowContext.h
@@ -8,7 +8,7 @@
#ifndef RasterWindowContext_DEFINED
#define RasterWindowContext_DEFINED
-#include "WindowContext.h"
+#include "tools/sk_app/WindowContext.h"
namespace sk_app {
@@ -16,9 +16,6 @@
public:
RasterWindowContext(const DisplayParams& params) : WindowContext(params) {}
- // Explicitly convert nullptr to GrBackendContext is needed for compiling
- GrBackendContext getBackendContext() override { return (GrBackendContext) nullptr; }
-
protected:
bool isGpuContext() override { return false; }
};
diff --git a/src/third_party/skia/tools/sk_app/VulkanWindowContext.cpp b/src/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
new file mode 100644
index 0000000..793c88c
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
@@ -0,0 +1,544 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/VulkanWindowContext.h"
+
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrBackendSemaphore.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContext.h"
+#include "src/core/SkAutoMalloc.h"
+
+#include "include/gpu/vk/GrVkExtensions.h"
+#include "include/gpu/vk/GrVkTypes.h"
+#include "src/gpu/vk/GrVkImage.h"
+#include "src/gpu/vk/GrVkUtil.h"
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
+#undef CreateSemaphore
+#endif
+
+#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fInstance, "vk" #F)
+#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fDevice, "vk" #F)
+
+namespace sk_app {
+
+VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
+ CreateVkSurfaceFn createVkSurface,
+ CanPresentFn canPresent,
+ PFN_vkGetInstanceProcAddr instProc,
+ PFN_vkGetDeviceProcAddr devProc)
+ : WindowContext(params)
+ , fCreateVkSurfaceFn(createVkSurface)
+ , fCanPresentFn(canPresent)
+ , fSurface(VK_NULL_HANDLE)
+ , fSwapchain(VK_NULL_HANDLE)
+ , fImages(nullptr)
+ , fImageLayouts(nullptr)
+ , fSurfaces(nullptr)
+ , fBackbuffers(nullptr) {
+ fGetInstanceProcAddr = instProc;
+ fGetDeviceProcAddr = devProc;
+ this->initializeContext();
+}
+
+void VulkanWindowContext::initializeContext() {
+ // any config code here (particularly for msaa)?
+
+ PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr getDeviceProc = fGetDeviceProcAddr;
+ auto getProc = [getInstanceProc, getDeviceProc](const char* proc_name,
+ VkInstance instance, VkDevice device) {
+ if (device != VK_NULL_HANDLE) {
+ return getDeviceProc(device, proc_name);
+ }
+ return getInstanceProc(instance, proc_name);
+ };
+ GrVkBackendContext backendContext;
+ GrVkExtensions extensions;
+ VkPhysicalDeviceFeatures2 features;
+ if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, &extensions, &features,
+ &fDebugCallback, &fPresentQueueIndex, fCanPresentFn)) {
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ if (!extensions.hasExtension(VK_KHR_SURFACE_EXTENSION_NAME, 25) ||
+ !extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 68)) {
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ fInstance = backendContext.fInstance;
+ fPhysicalDevice = backendContext.fPhysicalDevice;
+ fDevice = backendContext.fDevice;
+ fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
+ fGraphicsQueue = backendContext.fQueue;
+
+ PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
+ reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
+ backendContext.fGetProc("vkGetPhysicalDeviceProperties",
+ backendContext.fInstance,
+ VK_NULL_HANDLE));
+ if (!localGetPhysicalDeviceProperties) {
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+ VkPhysicalDeviceProperties physDeviceProperties;
+ localGetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &physDeviceProperties);
+ uint32_t physDevVersion = physDeviceProperties.apiVersion;
+
+ fInterface.reset(new GrVkInterface(backendContext.fGetProc, fInstance, fDevice,
+ backendContext.fInstanceVersion, physDevVersion,
+ &extensions));
+
+ GET_PROC(DestroyInstance);
+ if (fDebugCallback != VK_NULL_HANDLE) {
+ GET_PROC(DestroyDebugReportCallbackEXT);
+ }
+ GET_PROC(DestroySurfaceKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
+ GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
+ GET_DEV_PROC(DeviceWaitIdle);
+ GET_DEV_PROC(QueueWaitIdle);
+ GET_DEV_PROC(DestroyDevice);
+ GET_DEV_PROC(CreateSwapchainKHR);
+ GET_DEV_PROC(DestroySwapchainKHR);
+ GET_DEV_PROC(GetSwapchainImagesKHR);
+ GET_DEV_PROC(AcquireNextImageKHR);
+ GET_DEV_PROC(QueuePresentKHR);
+ GET_DEV_PROC(GetDeviceQueue);
+
+ fContext = GrContext::MakeVulkan(backendContext, fDisplayParams.fGrContextOptions);
+
+ fSurface = fCreateVkSurfaceFn(fInstance);
+ if (VK_NULL_HANDLE == fSurface) {
+ this->destroyContext();
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ VkBool32 supported;
+ VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fPhysicalDevice, fPresentQueueIndex,
+ fSurface, &supported);
+ if (VK_SUCCESS != res) {
+ this->destroyContext();
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ if (!this->createSwapchain(-1, -1, fDisplayParams)) {
+ this->destroyContext();
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ // create presentQueue
+ fGetDeviceQueue(fDevice, fPresentQueueIndex, 0, &fPresentQueue);
+ sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+}
+
+bool VulkanWindowContext::createSwapchain(int width, int height,
+ const DisplayParams& params) {
+ // check for capabilities
+ VkSurfaceCapabilitiesKHR caps;
+ VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fPhysicalDevice, fSurface, &caps);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t surfaceFormatCount;
+ res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
+ nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
+ VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
+ res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
+ surfaceFormats);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t presentModeCount;
+ res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
+ nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
+ VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
+ res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
+ presentModes);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ VkExtent2D extent = caps.currentExtent;
+ // use the hints
+ if (extent.width == (uint32_t)-1) {
+ extent.width = width;
+ extent.height = height;
+ }
+
+ // clamp width; to protect us from broken hints
+ if (extent.width < caps.minImageExtent.width) {
+ extent.width = caps.minImageExtent.width;
+ } else if (extent.width > caps.maxImageExtent.width) {
+ extent.width = caps.maxImageExtent.width;
+ }
+ // clamp height
+ if (extent.height < caps.minImageExtent.height) {
+ extent.height = caps.minImageExtent.height;
+ } else if (extent.height > caps.maxImageExtent.height) {
+ extent.height = caps.maxImageExtent.height;
+ }
+
+ fWidth = (int)extent.width;
+ fHeight = (int)extent.height;
+
+ uint32_t imageCount = caps.minImageCount + 2;
+ if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
+ // Application must settle for fewer images than desired:
+ imageCount = caps.maxImageCount;
+ }
+
+ VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
+ SkASSERT(caps.supportedTransforms & caps.currentTransform);
+ SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
+ VkCompositeAlphaFlagBitsKHR composite_alpha =
+ (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ // Pick our surface format.
+ VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
+ VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
+ VkFormat localFormat = surfaceFormats[i].format;
+ if (GrVkFormatIsSupported(localFormat)) {
+ surfaceFormat = localFormat;
+ colorSpace = surfaceFormats[i].colorSpace;
+ break;
+ }
+ }
+ fDisplayParams = params;
+ fSampleCount = SkTMax(1, params.fMSAASampleCount);
+ fStencilBits = 8;
+
+ if (VK_FORMAT_UNDEFINED == surfaceFormat) {
+ return false;
+ }
+
+ SkColorType colorType;
+ switch (surfaceFormat) {
+ case VK_FORMAT_R8G8B8A8_UNORM: // fall through
+ case VK_FORMAT_R8G8B8A8_SRGB:
+ colorType = kRGBA_8888_SkColorType;
+ break;
+ case VK_FORMAT_B8G8R8A8_UNORM: // fall through
+ colorType = kBGRA_8888_SkColorType;
+ break;
+ default:
+ return false;
+ }
+
+ // If mailbox mode is available, use it, as it is the lowest-latency non-
+ // tearing mode. If not, fall back to FIFO which is always available.
+ VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
+ bool hasImmediate = false;
+ for (uint32_t i = 0; i < presentModeCount; ++i) {
+ // use mailbox
+ if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
+ mode = VK_PRESENT_MODE_MAILBOX_KHR;
+ }
+ if (VK_PRESENT_MODE_IMMEDIATE_KHR == presentModes[i]) {
+ hasImmediate = true;
+ }
+ }
+ if (params.fDisableVsync && hasImmediate) {
+ mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+ }
+
+ VkSwapchainCreateInfoKHR swapchainCreateInfo;
+ memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
+ swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainCreateInfo.surface = fSurface;
+ swapchainCreateInfo.minImageCount = imageCount;
+ swapchainCreateInfo.imageFormat = surfaceFormat;
+ swapchainCreateInfo.imageColorSpace = colorSpace;
+ swapchainCreateInfo.imageExtent = extent;
+ swapchainCreateInfo.imageArrayLayers = 1;
+ swapchainCreateInfo.imageUsage = usageFlags;
+
+ uint32_t queueFamilies[] = { fGraphicsQueueIndex, fPresentQueueIndex };
+ if (fGraphicsQueueIndex != fPresentQueueIndex) {
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchainCreateInfo.queueFamilyIndexCount = 2;
+ swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
+ } else {
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainCreateInfo.queueFamilyIndexCount = 0;
+ swapchainCreateInfo.pQueueFamilyIndices = nullptr;
+ }
+
+ swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ swapchainCreateInfo.compositeAlpha = composite_alpha;
+ swapchainCreateInfo.presentMode = mode;
+ swapchainCreateInfo.clipped = true;
+ swapchainCreateInfo.oldSwapchain = fSwapchain;
+
+ res = fCreateSwapchainKHR(fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ // destroy the old swapchain
+ if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
+ fDeviceWaitIdle(fDevice);
+
+ this->destroyBuffers();
+
+ fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
+ }
+
+ this->createBuffers(swapchainCreateInfo.imageFormat, colorType);
+
+ return true;
+}
+
+void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType) {
+ fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
+ SkASSERT(fImageCount);
+ fImages = new VkImage[fImageCount];
+ fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, fImages);
+
+ // set up initial image layouts and create surfaces
+ fImageLayouts = new VkImageLayout[fImageCount];
+ fSurfaces = new sk_sp<SkSurface>[fImageCount];
+ for (uint32_t i = 0; i < fImageCount; ++i) {
+ fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ GrVkImageInfo info;
+ info.fImage = fImages[i];
+ info.fAlloc = GrVkAlloc();
+ info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+ info.fFormat = format;
+ info.fLevelCount = 1;
+ info.fCurrentQueueFamily = fPresentQueueIndex;
+
+ if (fSampleCount == 1) {
+ GrBackendRenderTarget backendRT(fWidth, fHeight, fSampleCount, info);
+
+ fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(
+ fContext.get(), backendRT, kTopLeft_GrSurfaceOrigin, colorType,
+ fDisplayParams.fColorSpace, &fDisplayParams.fSurfaceProps);
+ } else {
+ GrBackendTexture backendTexture(fWidth, fHeight, info);
+
+ // We don't set the sampled usage bit on the swapchain so this can't be a GrTexture.
+ fSurfaces[i] = SkSurface::MakeFromBackendTextureAsRenderTarget(
+ fContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, fSampleCount,
+ colorType, fDisplayParams.fColorSpace, &fDisplayParams.fSurfaceProps);
+
+ }
+ }
+
+ // set up the backbuffers
+ VkSemaphoreCreateInfo semaphoreInfo;
+ memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+
+ // we create one additional backbuffer structure here, because we want to
+ // give the command buffers they contain a chance to finish before we cycle back
+ fBackbuffers = new BackbufferInfo[fImageCount + 1];
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ fBackbuffers[i].fImageIndex = -1;
+ GR_VK_CALL_ERRCHECK(fInterface,
+ CreateSemaphore(fDevice, &semaphoreInfo,
+ nullptr, &fBackbuffers[i].fRenderSemaphore));
+ }
+ fCurrentBackbufferIndex = fImageCount;
+}
+
+void VulkanWindowContext::destroyBuffers() {
+
+ if (fBackbuffers) {
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ fBackbuffers[i].fImageIndex = -1;
+ GR_VK_CALL(fInterface,
+ DestroySemaphore(fDevice,
+ fBackbuffers[i].fRenderSemaphore,
+ nullptr));
+ }
+ }
+
+ delete[] fBackbuffers;
+ fBackbuffers = nullptr;
+
+ // Does this actually free the surfaces?
+ delete[] fSurfaces;
+ fSurfaces = nullptr;
+ delete[] fImageLayouts;
+ fImageLayouts = nullptr;
+ delete[] fImages;
+ fImages = nullptr;
+}
+
+VulkanWindowContext::~VulkanWindowContext() {
+ this->destroyContext();
+}
+
+void VulkanWindowContext::destroyContext() {
+ if (this->isValid()) {
+ fQueueWaitIdle(fPresentQueue);
+ fDeviceWaitIdle(fDevice);
+
+ this->destroyBuffers();
+
+ if (VK_NULL_HANDLE != fSwapchain) {
+ fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
+ fSwapchain = VK_NULL_HANDLE;
+ }
+
+ if (VK_NULL_HANDLE != fSurface) {
+ fDestroySurfaceKHR(fInstance, fSurface, nullptr);
+ fSurface = VK_NULL_HANDLE;
+ }
+ }
+
+ fContext.reset();
+ fInterface.reset();
+
+ if (VK_NULL_HANDLE != fDevice) {
+ fDestroyDevice(fDevice, nullptr);
+ fDevice = VK_NULL_HANDLE;
+ }
+
+#ifdef SK_ENABLE_VK_LAYERS
+ if (fDebugCallback != VK_NULL_HANDLE) {
+ fDestroyDebugReportCallbackEXT(fInstance, fDebugCallback, nullptr);
+ }
+#endif
+
+ fPhysicalDevice = VK_NULL_HANDLE;
+
+ if (VK_NULL_HANDLE != fInstance) {
+ fDestroyInstance(fInstance, nullptr);
+ fInstance = VK_NULL_HANDLE;
+ }
+}
+
+VulkanWindowContext::BackbufferInfo* VulkanWindowContext::getAvailableBackbuffer() {
+ SkASSERT(fBackbuffers);
+
+ ++fCurrentBackbufferIndex;
+ if (fCurrentBackbufferIndex > fImageCount) {
+ fCurrentBackbufferIndex = 0;
+ }
+
+ BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
+ return backbuffer;
+}
+
+sk_sp<SkSurface> VulkanWindowContext::getBackbufferSurface() {
+ BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
+ SkASSERT(backbuffer);
+
+ // semaphores should be in unsignaled state
+ VkSemaphoreCreateInfo semaphoreInfo;
+ memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+ GR_VK_CALL_ERRCHECK(fInterface, CreateSemaphore(fDevice, &semaphoreInfo,
+ nullptr, &semaphore));
+
+ // acquire the image
+ VkResult res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
+ semaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+ if (VK_ERROR_SURFACE_LOST_KHR == res) {
+ // need to figure out how to create a new vkSurface without the platformData*
+ // maybe use attach somehow? but need a Window
+ GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ if (VK_ERROR_OUT_OF_DATE_KHR == res) {
+ // tear swapchain down and try again
+ if (!this->createSwapchain(-1, -1, fDisplayParams)) {
+ GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ backbuffer = this->getAvailableBackbuffer();
+
+ // acquire the image
+ res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
+ semaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+
+ if (VK_SUCCESS != res) {
+ GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ }
+
+ SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
+
+ GrBackendSemaphore beSemaphore;
+ beSemaphore.initVulkan(semaphore);
+
+ surface->wait(1, &beSemaphore);
+
+ return sk_ref_sp(surface);
+}
+
+void VulkanWindowContext::swapBuffers() {
+
+ BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
+ SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
+
+ GrBackendSemaphore beSemaphore;
+ beSemaphore.initVulkan(backbuffer->fRenderSemaphore);
+
+ GrFlushInfo info;
+ info.fNumSemaphores = 1;
+ info.fSignalSemaphores = &beSemaphore;
+ surface->flush(SkSurface::BackendSurfaceAccess::kPresent, info);
+
+ // Submit present operation to present queue
+ const VkPresentInfoKHR presentInfo =
+ {
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
+ NULL, // pNext
+ 1, // waitSemaphoreCount
+ &backbuffer->fRenderSemaphore, // pWaitSemaphores
+ 1, // swapchainCount
+ &fSwapchain, // pSwapchains
+ &backbuffer->fImageIndex, // pImageIndices
+ NULL // pResults
+ };
+
+ fQueuePresentKHR(fPresentQueue, &presentInfo);
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/VulkanWindowContext.h b/src/third_party/skia/tools/sk_app/VulkanWindowContext.h
new file mode 100644
index 0000000..2db9e79
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/VulkanWindowContext.h
@@ -0,0 +1,121 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef VulkanWindowContext_DEFINED
+#define VulkanWindowContext_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#ifdef SK_VULKAN
+
+#include "include/gpu/vk/GrVkVulkan.h"
+
+#include "include/gpu/vk/GrVkBackendContext.h"
+#include "src/gpu/vk/GrVkInterface.h"
+#include "tools/gpu/vk/VkTestUtils.h"
+#include "tools/sk_app/WindowContext.h"
+
+class GrRenderTarget;
+
+namespace sk_app {
+
+class VulkanWindowContext : public WindowContext {
+public:
+ ~VulkanWindowContext() override;
+
+ sk_sp<SkSurface> getBackbufferSurface() override;
+ void swapBuffers() override;
+
+ bool isValid() override { return fDevice != VK_NULL_HANDLE; }
+
+ void resize(int w, int h) override {
+ this->createSwapchain(w, h, fDisplayParams);
+ }
+
+ void setDisplayParams(const DisplayParams& params) override {
+ this->destroyContext();
+ fDisplayParams = params;
+ this->initializeContext();
+ }
+
+ /** Platform specific function that creates a VkSurfaceKHR for a window */
+ using CreateVkSurfaceFn = std::function<VkSurfaceKHR(VkInstance)>;
+ /** Platform specific function that determines whether presentation will succeed. */
+ using CanPresentFn = sk_gpu_test::CanPresentFn;
+
+ VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn,
+ PFN_vkGetInstanceProcAddr, PFN_vkGetDeviceProcAddr);
+
+private:
+ void initializeContext();
+ void destroyContext();
+
+ struct BackbufferInfo {
+ uint32_t fImageIndex; // image this is associated with
+ VkSemaphore fRenderSemaphore; // we wait on this for rendering to be done
+ };
+
+ BackbufferInfo* getAvailableBackbuffer();
+ bool createSwapchain(int width, int height, const DisplayParams& params);
+ void createBuffers(VkFormat format, SkColorType colorType);
+ void destroyBuffers();
+
+ VkInstance fInstance = VK_NULL_HANDLE;
+ VkPhysicalDevice fPhysicalDevice = VK_NULL_HANDLE;
+ VkDevice fDevice = VK_NULL_HANDLE;
+ VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
+
+ // Create functions
+ CreateVkSurfaceFn fCreateVkSurfaceFn;
+ CanPresentFn fCanPresentFn;
+
+ // Vulkan GetProcAddr functions
+ PFN_vkGetInstanceProcAddr fGetInstanceProcAddr = nullptr;
+ PFN_vkGetDeviceProcAddr fGetDeviceProcAddr = nullptr;
+
+ // WSI interface functions
+ PFN_vkDestroySurfaceKHR fDestroySurfaceKHR = nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR fGetPhysicalDeviceSurfaceSupportKHR = nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fGetPhysicalDeviceSurfaceCapabilitiesKHR =nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fGetPhysicalDeviceSurfacePresentModesKHR =nullptr;
+
+ PFN_vkCreateSwapchainKHR fCreateSwapchainKHR = nullptr;
+ PFN_vkDestroySwapchainKHR fDestroySwapchainKHR = nullptr;
+ PFN_vkGetSwapchainImagesKHR fGetSwapchainImagesKHR = nullptr;
+ PFN_vkAcquireNextImageKHR fAcquireNextImageKHR = nullptr;
+ PFN_vkQueuePresentKHR fQueuePresentKHR = nullptr;
+
+ PFN_vkDestroyInstance fDestroyInstance = nullptr;
+ PFN_vkDeviceWaitIdle fDeviceWaitIdle = nullptr;
+ PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugReportCallbackEXT = nullptr;
+ PFN_vkQueueWaitIdle fQueueWaitIdle = nullptr;
+ PFN_vkDestroyDevice fDestroyDevice = nullptr;
+ PFN_vkGetDeviceQueue fGetDeviceQueue = nullptr;
+
+ sk_sp<const GrVkInterface> fInterface;
+
+ VkSurfaceKHR fSurface;
+ VkSwapchainKHR fSwapchain;
+ uint32_t fGraphicsQueueIndex;
+ VkQueue fGraphicsQueue;
+ uint32_t fPresentQueueIndex;
+ VkQueue fPresentQueue;
+
+ uint32_t fImageCount;
+ VkImage* fImages; // images in the swapchain
+ VkImageLayout* fImageLayouts; // layouts of these images when not color attachment
+ sk_sp<SkSurface>* fSurfaces; // surfaces client renders to (may not be based on rts)
+ BackbufferInfo* fBackbuffers;
+ uint32_t fCurrentBackbufferIndex;
+};
+
+} // namespace sk_app
+
+#endif // SK_VULKAN
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/Window.cpp b/src/third_party/skia/tools/sk_app/Window.cpp
new file mode 100644
index 0000000..2ccad55
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/Window.cpp
@@ -0,0 +1,159 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "tools/sk_app/Window.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
+#include "tools/sk_app/WindowContext.h"
+
+namespace sk_app {
+
+Window::Window() {}
+
+Window::~Window() {}
+
+void Window::detach() { fWindowContext = nullptr; }
+
+void Window::visitLayers(std::function<void(Layer*)> visitor) {
+ for (int i = 0; i < fLayers.count(); ++i) {
+ if (fLayers[i]->fActive) {
+ visitor(fLayers[i]);
+ }
+ }
+}
+
+bool Window::signalLayers(std::function<bool(Layer*)> visitor) {
+ for (int i = fLayers.count() - 1; i >= 0; --i) {
+ if (fLayers[i]->fActive && visitor(fLayers[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Window::onBackendCreated() {
+ this->visitLayers([](Layer* layer) { layer->onBackendCreated(); });
+}
+
+bool Window::onChar(SkUnichar c, skui::ModifierKey modifiers) {
+ return this->signalLayers([=](Layer* layer) { return layer->onChar(c, modifiers); });
+}
+
+bool Window::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {
+ return this->signalLayers([=](Layer* layer) { return layer->onKey(key, state, modifiers); });
+}
+
+bool Window::onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) {
+ return this->signalLayers([=](Layer* layer) { return layer->onMouse(x, y, state, modifiers); });
+}
+
+bool Window::onMouseWheel(float delta, skui::ModifierKey modifiers) {
+ return this->signalLayers([=](Layer* layer) { return layer->onMouseWheel(delta, modifiers); });
+}
+
+bool Window::onTouch(intptr_t owner, skui::InputState state, float x, float y) {
+ return this->signalLayers([=](Layer* layer) { return layer->onTouch(owner, state, x, y); });
+}
+
+bool Window::onFling(skui::InputState state) {
+ return this->signalLayers([=](Layer* layer) { return layer->onFling(state); });
+}
+
+bool Window::onPinch(skui::InputState state, float scale, float x, float y) {
+ return this->signalLayers([=](Layer* layer) { return layer->onPinch(state, scale, x, y); });
+}
+
+void Window::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
+ this->visitLayers([=](Layer* layer) { layer->onUIStateChanged(stateName, stateValue); });
+}
+
+void Window::onPaint() {
+ if (!fWindowContext) {
+ return;
+ }
+ markInvalProcessed();
+ this->visitLayers([](Layer* layer) { layer->onPrePaint(); });
+ sk_sp<SkSurface> backbuffer = fWindowContext->getBackbufferSurface();
+ if (backbuffer) {
+ // draw into the canvas of this surface
+ this->visitLayers([=](Layer* layer) { layer->onPaint(backbuffer.get()); });
+
+ backbuffer->flush();
+
+ fWindowContext->swapBuffers();
+ } else {
+ printf("no backbuffer!?\n");
+ // try recreating testcontext
+ }
+}
+
+void Window::onResize(int w, int h) {
+ if (!fWindowContext) {
+ return;
+ }
+ fWindowContext->resize(w, h);
+ this->visitLayers([=](Layer* layer) { layer->onResize(w, h); });
+}
+
+int Window::width() const {
+ if (!fWindowContext) {
+ return 0;
+ }
+ return fWindowContext->width();
+}
+
+int Window::height() const {
+ if (!fWindowContext) {
+ return 0;
+ }
+ return fWindowContext->height();
+}
+
+void Window::setRequestedDisplayParams(const DisplayParams& params, bool /* allowReattach */) {
+ fRequestedDisplayParams = params;
+ if (fWindowContext) {
+ fWindowContext->setDisplayParams(fRequestedDisplayParams);
+ }
+}
+
+int Window::sampleCount() const {
+ if (!fWindowContext) {
+ return 0;
+ }
+ return fWindowContext->sampleCount();
+}
+
+int Window::stencilBits() const {
+ if (!fWindowContext) {
+ return -1;
+ }
+ return fWindowContext->stencilBits();
+}
+
+GrContext* Window::getGrContext() const {
+ if (!fWindowContext) {
+ return nullptr;
+ }
+ return fWindowContext->getGrContext();
+}
+
+void Window::inval() {
+ if (!fWindowContext) {
+ return;
+ }
+ if (!fIsContentInvalidated) {
+ fIsContentInvalidated = true;
+ onInval();
+ }
+}
+
+void Window::markInvalProcessed() {
+ fIsContentInvalidated = false;
+}
+
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/Window.h b/src/third_party/skia/tools/sk_app/Window.h
new file mode 100644
index 0000000..76be662
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/Window.h
@@ -0,0 +1,154 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef Window_DEFINED
+#define Window_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTDArray.h"
+#include "tools/sk_app/DisplayParams.h"
+#include "tools/skui/InputState.h"
+#include "tools/skui/Key.h"
+#include "tools/skui/ModifierKey.h"
+
+class GrContext;
+class SkCanvas;
+class SkSurface;
+class SkSurfaceProps;
+
+namespace sk_app {
+
+class WindowContext;
+
+class Window {
+public:
+ static Window* CreateNativeWindow(void* platformData);
+
+ virtual ~Window();
+
+ virtual void setTitle(const char*) = 0;
+ virtual void show() = 0;
+
+ // JSON-formatted UI state for Android. Do nothing by default
+ virtual void setUIState(const char*) {}
+
+ // Shedules an invalidation event for window if one is not currently pending.
+ // Make sure that either onPaint or markInvalReceived is called when the client window consumes
+ // the the inval event. They unset fIsContentInvalided which allow future onInval.
+ void inval();
+
+ virtual bool scaleContentToFit() const { return false; }
+
+ enum BackendType {
+ kNativeGL_BackendType,
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ kANGLE_BackendType,
+#endif
+#ifdef SK_DAWN
+ kDawn_BackendType,
+#endif
+#ifdef SK_VULKAN
+ kVulkan_BackendType,
+#endif
+#ifdef SK_METAL
+ kMetal_BackendType,
+#endif
+ kRaster_BackendType,
+
+ kLast_BackendType = kRaster_BackendType
+ };
+ enum {
+ kBackendTypeCount = kLast_BackendType + 1
+ };
+
+ virtual bool attach(BackendType) = 0;
+ void detach();
+
+ // input handling
+
+ class Layer {
+ public:
+ Layer() : fActive(true) {}
+ virtual ~Layer() = default;
+
+ bool getActive() { return fActive; }
+ void setActive(bool active) { fActive = active; }
+
+ // return value of 'true' means 'I have handled this event'
+ virtual void onBackendCreated() {}
+ virtual void onAttach(Window* window) {}
+ virtual bool onChar(SkUnichar c, skui::ModifierKey) { return false; }
+ virtual bool onKey(skui::Key, skui::InputState, skui::ModifierKey) { return false; }
+ virtual bool onMouse(int x, int y, skui::InputState, skui::ModifierKey) { return false; }
+ virtual bool onMouseWheel(float delta, skui::ModifierKey) { return false; }
+ virtual bool onTouch(intptr_t owner, skui::InputState, float x, float y) { return false; }
+ // Platform-detected gesture events
+ virtual bool onFling(skui::InputState state) { return false; }
+ virtual bool onPinch(skui::InputState state, float scale, float x, float y) { return false; }
+ virtual void onUIStateChanged(const SkString& stateName, const SkString& stateValue) {}
+ virtual void onPrePaint() {}
+ virtual void onPaint(SkSurface*) {}
+ virtual void onResize(int width, int height) {}
+
+ private:
+ friend class Window;
+ bool fActive;
+ };
+
+ void pushLayer(Layer* layer) {
+ layer->onAttach(this);
+ fLayers.push_back(layer);
+ }
+
+ void onBackendCreated();
+ bool onChar(SkUnichar c, skui::ModifierKey modifiers);
+ bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers);
+ bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers);
+ bool onMouseWheel(float delta, skui::ModifierKey modifiers);
+ bool onTouch(intptr_t owner, skui::InputState state, float x, float y); // multi-owner = multi-touch
+ // Platform-detected gesture events
+ bool onFling(skui::InputState state);
+ bool onPinch(skui::InputState state, float scale, float x, float y);
+ void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
+ void onPaint();
+ void onResize(int width, int height);
+
+ int width() const;
+ int height() const;
+
+ virtual const DisplayParams& getRequestedDisplayParams() { return fRequestedDisplayParams; }
+ virtual void setRequestedDisplayParams(const DisplayParams&, bool allowReattach = true);
+
+ // Actual parameters in effect, obtained from the native window.
+ int sampleCount() const;
+ int stencilBits() const;
+
+ // Returns null if there is not a GPU backend or if the backend is not yet created.
+ GrContext* getGrContext() const;
+
+protected:
+ Window();
+
+ SkTDArray<Layer*> fLayers;
+ DisplayParams fRequestedDisplayParams;
+
+ std::unique_ptr<WindowContext> fWindowContext;
+
+ virtual void onInval() = 0;
+
+ // Uncheck fIsContentInvalided to allow future inval/onInval.
+ void markInvalProcessed();
+
+ bool fIsContentInvalidated = false; // use this to avoid duplicate invalidate events
+
+ void visitLayers(std::function<void(Layer*)> visitor);
+ bool signalLayers(std::function<bool(Layer*)> visitor);
+};
+
+} // namespace sk_app
+#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/WindowContext.h b/src/third_party/skia/tools/sk_app/WindowContext.h
similarity index 66%
rename from src/third_party/skia/tools/viewer/sk_app/WindowContext.h
rename to src/third_party/skia/tools/sk_app/WindowContext.h
index fbd2756..5b1058e 100644
--- a/src/third_party/skia/tools/viewer/sk_app/WindowContext.h
+++ b/src/third_party/skia/tools/sk_app/WindowContext.h
@@ -7,12 +7,12 @@
#ifndef WindowContext_DEFINED
#define WindowContext_DEFINED
-#include "DisplayParams.h"
-#include "GrTypes.h"
-#include "SkRefCnt.h"
-#include "SkSurfaceProps.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceProps.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/GrTypes.h"
+#include "tools/sk_app/DisplayParams.h"
-class GrContext;
class SkSurface;
class GrRenderTarget;
@@ -21,11 +21,10 @@
class WindowContext {
public:
WindowContext(const DisplayParams& params)
- : fContext(nullptr)
- , fDisplayParams(params)
- , fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
- , fSampleCount(0)
- , fStencilBits(0) {}
+ : fContext(nullptr)
+ , fDisplayParams(params)
+ , fSampleCount(1)
+ , fStencilBits(0) {}
virtual ~WindowContext() {}
@@ -40,13 +39,7 @@
const DisplayParams& getDisplayParams() { return fDisplayParams; }
virtual void setDisplayParams(const DisplayParams& params) = 0;
- SkSurfaceProps getSurfaceProps() const { return fSurfaceProps; }
- void setSurfaceProps(const SkSurfaceProps& props) {
- fSurfaceProps = props;
- }
-
- virtual GrBackendContext getBackendContext() = 0;
- GrContext* getGrContext() const { return fContext; }
+ GrContext* getGrContext() const { return fContext.get(); }
int width() const { return fWidth; }
int height() const { return fHeight; }
@@ -56,13 +49,11 @@
protected:
virtual bool isGpuContext() { return true; }
- GrContext* fContext;
+ sk_sp<GrContext> fContext;
int fWidth;
int fHeight;
DisplayParams fDisplayParams;
- GrPixelConfig fPixelConfig;
- SkSurfaceProps fSurfaceProps;
// parameters obtained from the native window
// Note that the platform .cpp file is responsible for
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp b/src/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
similarity index 71%
rename from src/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp
rename to src/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
index 12c12a7..624b8af 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp
+++ b/src/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
@@ -6,11 +6,11 @@
* found in the LICENSE file.
*/
-#include <GLES/gl.h>
-
-#include "WindowContextFactory_android.h"
-#include "../GLWindowContext.h"
#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/android/WindowContextFactory_android.h"
using sk_app::GLWindowContext;
using sk_app::DisplayParams;
@@ -25,7 +25,7 @@
void onSwapBuffers() override;
- void onInitializeContext() override;
+ sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@@ -57,7 +57,7 @@
this->destroyContext();
}
-void GLWindowContext_android::onInitializeContext() {
+sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
fWidth = ANativeWindow_getWidth(fNativeWindow);
fHeight = ANativeWindow_getHeight(fNativeWindow);
@@ -70,6 +70,8 @@
SkAssertResult(eglBindAPI(EGL_OPENGL_ES_API));
EGLint numConfigs = 0;
+ EGLint eglSampleCnt = fDisplayParams.fMSAASampleCount > 1 ? fDisplayParams.fMSAASampleCount > 1
+ : 0;
const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
@@ -78,8 +80,8 @@
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_STENCIL_SIZE, 8,
- EGL_SAMPLE_BUFFERS, fDisplayParams.fMSAASampleCount ? 1 : 0,
- EGL_SAMPLES, fDisplayParams.fMSAASampleCount,
+ EGL_SAMPLE_BUFFERS, eglSampleCnt ? 1 : 0,
+ EGL_SAMPLES, eglSampleCnt,
EGL_NONE
};
@@ -99,29 +101,11 @@
// SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR));
// SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS));
- // These values are the same as the corresponding VG colorspace attributes,
- // which were accepted starting in EGL 1.2. For some reason in 1.4, sRGB
- // became hidden behind an extension, but it looks like devices aren't
- // advertising that extension (including Nexus 5X). So just check version?
- const EGLint srgbWindowAttribs[] = {
- /*EGL_GL_COLORSPACE_KHR*/ 0x309D, /*EGL_GL_COLORSPACE_SRGB_KHR*/ 0x3089,
- EGL_NONE,
- };
- const EGLint* windowAttribs = nullptr;
- auto srgbColorSpace = SkColorSpace::MakeSRGB();
- if (srgbColorSpace == fDisplayParams.fColorSpace && majorVersion == 1 && minorVersion >= 2) {
- windowAttribs = srgbWindowAttribs;
- }
-
- fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, windowAttribs);
- if (EGL_NO_SURFACE == fSurfaceAndroid && windowAttribs) {
- // Try again without sRGB
- fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, nullptr);
- }
+ fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, nullptr);
SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid);
SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext));
- // GLWindowContext::initializeContext will call GrGLCreateNativeInterface so we
+ // GLWindowContext::initializeContext will call GrGLMakeNativeInterface so we
// won't call it here.
glClearStencil(0);
@@ -131,6 +115,11 @@
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
+
+ eglSwapInterval(fDisplay, fDisplayParams.fDisableVsync ? 0 : 1);
+
+ return GrGLMakeNativeInterface();
}
void GLWindowContext_android::onDestroyContext() {
@@ -155,10 +144,10 @@
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewGLForAndroid(ANativeWindow* window, const DisplayParams& params) {
- WindowContext* ctx = new GLWindowContext_android(window, params);
+std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow* window,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new GLWindowContext_android(window, params));
if (!ctx->isValid()) {
- delete ctx;
return nullptr;
}
return ctx;
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp b/src/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp
similarity index 87%
rename from src/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
rename to src/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp
index 101e51e..701963c 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
+++ b/src/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp
@@ -6,10 +6,10 @@
* found in the LICENSE file.
*/
-#include "WindowContextFactory_android.h"
-#include "../RasterWindowContext.h"
-#include "SkSurface.h"
-#include "SkTypes.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTypes.h"
+#include "tools/sk_app/RasterWindowContext.h"
+#include "tools/sk_app/android/WindowContextFactory_android.h"
using sk_app::RasterWindowContext;
using sk_app::DisplayParams;
@@ -95,10 +95,10 @@
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewRasterForAndroid(ANativeWindow* window, const DisplayParams& params) {
- WindowContext* ctx = new RasterWindowContext_android(window, params);
+std::unique_ptr<WindowContext> MakeRasterForAndroid(ANativeWindow* window,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new RasterWindowContext_android(window, params));
if (!ctx->isValid()) {
- delete ctx;
return nullptr;
}
return ctx;
diff --git a/src/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp b/src/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp
new file mode 100644
index 0000000..90466ad
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp
@@ -0,0 +1,61 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/vk/GrVkVulkan.h"
+
+#include "tools/sk_app/android/WindowContextFactory_android.h"
+
+#include "tools/sk_app/VulkanWindowContext.h"
+
+#include "tools/gpu/vk/VkTestUtils.h"
+
+namespace sk_app {
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeVulkanForAndroid(ANativeWindow* window,
+ const DisplayParams& params) {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [window, instProc] (VkInstance instance) -> VkSurfaceKHR {
+ PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR =
+ (PFN_vkCreateAndroidSurfaceKHR) instProc(instance, "vkCreateAndroidSurfaceKHR");
+
+ if (!window) {
+ return VK_NULL_HANDLE;
+ }
+ VkSurfaceKHR surface;
+
+ VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
+ memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.pNext = nullptr;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.window = window;
+
+ VkResult res = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
+ nullptr, &surface);
+ return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
+ };
+
+ auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
+
+ std::unique_ptr<WindowContext> ctx(
+ new VulkanWindowContext(params, createVkSurface, canPresent, instProc, devProc));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h b/src/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h
similarity index 61%
rename from src/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h
rename to src/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h
index 00198da..f7f2349 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h
+++ b/src/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h
@@ -11,6 +11,7 @@
#include <android/native_window_jni.h>
+#include <memory>
namespace sk_app {
@@ -19,11 +20,11 @@
namespace window_context_factory {
-WindowContext* NewVulkanForAndroid(ANativeWindow*, const DisplayParams&);
+std::unique_ptr<WindowContext> MakeVulkanForAndroid(ANativeWindow*, const DisplayParams&);
-WindowContext* NewGLForAndroid(ANativeWindow*, const DisplayParams&);
+std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow*, const DisplayParams&);
-WindowContext* NewRasterForAndroid(ANativeWindow*, const DisplayParams&);
+std::unique_ptr<WindowContext> MakeRasterForAndroid(ANativeWindow*, const DisplayParams&);
} // namespace window_context_factory
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp b/src/third_party/skia/tools/sk_app/android/Window_android.cpp
similarity index 71%
rename from src/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp
rename to src/third_party/skia/tools/sk_app/android/Window_android.cpp
index 16ad430..f1924c4 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp
+++ b/src/third_party/skia/tools/sk_app/android/Window_android.cpp
@@ -5,9 +5,9 @@
* found in the LICENSE file.
*/
-#include "Window_android.h"
-#include "WindowContextFactory_android.h"
-#include "../WindowContext.h"
+#include "tools/sk_app/WindowContext.h"
+#include "tools/sk_app/android/WindowContextFactory_android.h"
+#include "tools/sk_app/android/Window_android.h"
namespace sk_app {
@@ -31,7 +31,7 @@
fSkiaAndroidApp->setTitle(title);
}
-void Window_android::setUIState(const Json::Value& state) {
+void Window_android::setUIState(const char* state) {
fSkiaAndroidApp->setUIState(state);
}
@@ -49,17 +49,17 @@
switch (fBackendType) {
case kNativeGL_BackendType:
default:
- fWindowContext = window_context_factory::NewGLForAndroid(window,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeGLForAndroid(window, fRequestedDisplayParams);
break;
case kRaster_BackendType:
- fWindowContext = window_context_factory::NewRasterForAndroid(window,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeRasterForAndroid(window, fRequestedDisplayParams);
break;
#ifdef SK_VULKAN
case kVulkan_BackendType:
- fWindowContext = window_context_factory::NewVulkanForAndroid(window,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeVulkanForAndroid(window, fRequestedDisplayParams);
break;
#endif
}
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/Window_android.h b/src/third_party/skia/tools/sk_app/android/Window_android.h
similarity index 85%
rename from src/third_party/skia/tools/viewer/sk_app/android/Window_android.h
rename to src/third_party/skia/tools/sk_app/android/Window_android.h
index 7918011..23ec817 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/Window_android.h
+++ b/src/third_party/skia/tools/sk_app/android/Window_android.h
@@ -8,8 +8,8 @@
#ifndef Window_android_DEFINED
#define Window_android_DEFINED
-#include "../Window.h"
-#include "surface_glue_android.h"
+#include "tools/sk_app/Window.h"
+#include "tools/sk_app/android/surface_glue_android.h"
namespace sk_app {
@@ -27,7 +27,7 @@
bool attach(BackendType) override;
void onInval() override;
- void setUIState(const Json::Value& state) override;
+ void setUIState(const char* state) override;
void paintIfNeeded();
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/main_android.cpp b/src/third_party/skia/tools/sk_app/android/main_android.cpp
similarity index 95%
rename from src/third_party/skia/tools/viewer/sk_app/android/main_android.cpp
rename to src/third_party/skia/tools/sk_app/android/main_android.cpp
index cb8db6c..3eaea2c 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/main_android.cpp
+++ b/src/third_party/skia/tools/sk_app/android/main_android.cpp
@@ -10,8 +10,8 @@
#include <android_native_app_glue.h>
-#include "../Application.h"
-#include "Timer.h"
+#include "tools/sk_app/Application.h"
+#include "tools/timer/Timer.h"
using sk_app::Application;
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp b/src/third_party/skia/tools/sk_app/android/surface_glue_android.cpp
similarity index 80%
rename from src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp
rename to src/third_party/skia/tools/sk_app/android/surface_glue_android.cpp
index 4fb6c3d..840ce5a 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp
+++ b/src/third_party/skia/tools/sk_app/android/surface_glue_android.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "surface_glue_android.h"
+#include "tools/sk_app/android/surface_glue_android.h"
#include <jni.h>
#include <pthread.h>
@@ -13,32 +13,59 @@
#include <unistd.h>
#include <unordered_map>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
#include <android/input.h>
#include <android/keycodes.h>
#include <android/looper.h>
#include <android/native_window_jni.h>
-#include "../Application.h"
-#include "SkTypes.h"
-#include "SkUtils.h"
-#include "Window_android.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTo.h"
+#include "src/utils/SkUTF.h"
+#include "tools/ResourceFactory.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/android/Window_android.h"
+
namespace sk_app {
+static void config_resource_mgr(JNIEnv* env, jobject assetManager) {
+ static AAssetManager* gAAssetManager = nullptr;
+ SkASSERT(assetManager);
+ gAAssetManager = AAssetManager_fromJava(env, assetManager);
+ SkASSERT(gAAssetManager);
+ gResourceFactory = [](const char* resource) -> sk_sp<SkData> {
+ if (!gAAssetManager) {
+ return nullptr;
+ }
+ SkString path = SkStringPrintf("resources/%s", resource);
+ AAsset* asset = AAssetManager_open(gAAssetManager, path.c_str(), AASSET_MODE_STREAMING);
+ if (!asset) {
+ return nullptr;
+ }
+ size_t size = SkToSizeT(AAsset_getLength(asset));
+ sk_sp<SkData> data = SkData::MakeUninitialized(size);
+ (void)AAsset_read(asset, data->writable_data(), size);
+ AAsset_close(asset);
+ return data;
+ };
+}
+
static const int LOOPER_ID_MESSAGEPIPE = 1;
-static const std::unordered_map<int, Window::Key> ANDROID_TO_WINDOW_KEYMAP({
- {AKEYCODE_SOFT_LEFT, Window::Key::kLeft},
- {AKEYCODE_SOFT_RIGHT, Window::Key::kRight}
+static const std::unordered_map<int, skui::Key> ANDROID_TO_WINDOW_KEYMAP({
+ {AKEYCODE_SOFT_LEFT, skui::Key::kLeft },
+ {AKEYCODE_SOFT_RIGHT, skui::Key::kRight}
});
-static const std::unordered_map<int, Window::InputState> ANDROID_TO_WINDOW_STATEMAP({
- {AMOTION_EVENT_ACTION_DOWN, Window::kDown_InputState},
- {AMOTION_EVENT_ACTION_POINTER_DOWN, Window::kDown_InputState},
- {AMOTION_EVENT_ACTION_UP, Window::kUp_InputState},
- {AMOTION_EVENT_ACTION_POINTER_UP, Window::kUp_InputState},
- {AMOTION_EVENT_ACTION_MOVE, Window::kMove_InputState},
- {AMOTION_EVENT_ACTION_CANCEL, Window::kUp_InputState},
+static const std::unordered_map<int, skui::InputState> ANDROID_TO_WINDOW_STATEMAP({
+ {AMOTION_EVENT_ACTION_DOWN, skui::InputState::kDown },
+ {AMOTION_EVENT_ACTION_POINTER_DOWN, skui::InputState::kDown },
+ {AMOTION_EVENT_ACTION_UP, skui::InputState::kUp },
+ {AMOTION_EVENT_ACTION_POINTER_UP, skui::InputState::kUp },
+ {AMOTION_EVENT_ACTION_MOVE, skui::InputState::kMove },
+ {AMOTION_EVENT_ACTION_CANCEL, skui::InputState::kUp },
});
SkiaAndroidApp::SkiaAndroidApp(JNIEnv* env, jobject androidApp) {
@@ -71,8 +98,8 @@
fPThreadEnv->DeleteLocalRef(titleString);
}
-void SkiaAndroidApp::setUIState(const Json::Value& state) const {
- jstring jstr = fPThreadEnv->NewStringUTF(state.toStyledString().c_str());
+void SkiaAndroidApp::setUIState(const char* state) const {
+ jstring jstr = fPThreadEnv->NewStringUTF(state);
fPThreadEnv->CallVoidMethod(fAndroidApp, fSetStateMethodID, jstr);
fPThreadEnv->DeleteLocalRef(jstr);
}
@@ -139,8 +166,8 @@
auto it = ANDROID_TO_WINDOW_KEYMAP.find(message.fKeycode);
SkASSERT(it != ANDROID_TO_WINDOW_KEYMAP.end());
// No modifier is supported so far
- skiaAndroidApp->fWindow->onKey(it->second, Window::kDown_InputState, 0);
- skiaAndroidApp->fWindow->onKey(it->second, Window::kUp_InputState, 0);
+ skiaAndroidApp->fWindow->onKey(it->second, skui::InputState::kDown, skui::ModifierKey::kNone);
+ skiaAndroidApp->fWindow->onKey(it->second, skui::InputState::kUp, skui::ModifierKey::kNone);
break;
}
case kTouched: {
@@ -208,7 +235,10 @@
extern "C" // extern "C" is needed for JNI (although the method itself is in C++)
JNIEXPORT jlong JNICALL
- Java_org_skia_viewer_ViewerApplication_createNativeApp(JNIEnv* env, jobject application) {
+ Java_org_skia_viewer_ViewerApplication_createNativeApp(JNIEnv* env,
+ jobject application,
+ jobject assetManager) {
+ config_resource_mgr(env, assetManager);
SkiaAndroidApp* skiaAndroidApp = new SkiaAndroidApp(env, application);
return (jlong)((size_t)skiaAndroidApp);
}
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h b/src/third_party/skia/tools/sk_app/android/surface_glue_android.h
similarity index 91%
rename from src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h
rename to src/third_party/skia/tools/sk_app/android/surface_glue_android.h
index 3bbf3af..f73fe56 100644
--- a/src/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h
+++ b/src/third_party/skia/tools/sk_app/android/surface_glue_android.h
@@ -12,10 +12,10 @@
#include <android/native_window_jni.h>
-#include "SkString.h"
+#include "include/core/SkString.h"
-#include "../Application.h"
-#include "../Window.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/Window.h"
namespace sk_app {
@@ -57,7 +57,7 @@
// These must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive
void setTitle(const char* title) const;
- void setUIState(const Json::Value& state) const;
+ void setUIState(const char* state) const;
private:
pthread_t fThread;
diff --git a/src/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.mm b/src/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.mm
new file mode 100644
index 0000000..a21f88b
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.mm
@@ -0,0 +1,169 @@
+
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/ios/WindowContextFactory_ios.h"
+
+#import <OpenGLES/ES3/gl.h>
+#import <UIKit/UIKit.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::IOSWindowInfo;
+using sk_app::GLWindowContext;
+
+@interface GLView : MainView
+@end
+
+@implementation GLView
++ (Class) layerClass {
+ return [CAEAGLLayer class];
+}
+@end
+
+namespace {
+
+class GLWindowContext_ios : public GLWindowContext {
+public:
+ GLWindowContext_ios(const IOSWindowInfo&, const DisplayParams&);
+
+ ~GLWindowContext_ios() override;
+
+ void onSwapBuffers() override;
+
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+ void onDestroyContext() override;
+
+ void resize(int w, int h) override;
+
+private:
+ sk_app::Window_ios* fWindow;
+ UIViewController* fViewController;
+ GLView* fGLView;
+ EAGLContext* fGLContext;
+ GLuint fFramebuffer;
+ GLuint fRenderbuffer;
+
+ typedef GLWindowContext INHERITED;
+};
+
+GLWindowContext_ios::GLWindowContext_ios(const IOSWindowInfo& info, const DisplayParams& params)
+ : INHERITED(params)
+ , fWindow(info.fWindow)
+ , fViewController(info.fViewController)
+ , fGLContext(nil) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+GLWindowContext_ios::~GLWindowContext_ios() {
+ this->destroyContext();
+ [fGLView removeFromSuperview];
+ [fGLView release];
+}
+
+sk_sp<const GrGLInterface> GLWindowContext_ios::onInitializeContext() {
+ SkASSERT(nil != fViewController);
+ SkASSERT(!fGLContext);
+
+ CGRect frameRect = [fViewController.view frame];
+ fGLView = [[[GLView alloc] initWithFrame:frameRect] initWithWindow:fWindow];
+ [fViewController.view addSubview:fGLView];
+
+ fGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
+
+ if (!fGLContext)
+ {
+ SkDebugf("Could Not Create OpenGL ES Context\n");
+ return nullptr;
+ }
+
+ if (![EAGLContext setCurrentContext:fGLContext]) {
+ SkDebugf("Could Not Set OpenGL ES Context As Current\n");
+ this->onDestroyContext();
+ return nullptr;
+ }
+
+ // Set up EAGLLayer
+ CAEAGLLayer* eaglLayer = (CAEAGLLayer*)fGLView.layer;
+ eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO,
+ kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 };
+ eaglLayer.opaque = YES;
+ eaglLayer.frame = frameRect;
+ eaglLayer.contentsGravity = kCAGravityTopLeft;
+
+ // Set up framebuffer
+ glGenFramebuffers(1, &fFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, fFramebuffer);
+
+ glGenRenderbuffers(1, &fRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fRenderbuffer);
+
+ [fGLContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer];
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ SkDebugf("Invalid Framebuffer\n");
+ this->onDestroyContext();
+ return nullptr;
+ }
+
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 255);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ fStencilBits = 8;
+ fSampleCount = 1; // TODO: handle multisampling
+
+ fWidth = fViewController.view.frame.size.width;
+ fHeight = fViewController.view.frame.size.height;
+
+ glViewport(0, 0, fWidth, fHeight);
+
+ return GrGLMakeNativeInterface();
+}
+
+void GLWindowContext_ios::onDestroyContext() {
+ glDeleteFramebuffers(1, &fFramebuffer);
+ glDeleteRenderbuffers(1, &fRenderbuffer);
+ [EAGLContext setCurrentContext:nil];
+ [fGLContext release];
+ fGLContext = nil;
+}
+
+void GLWindowContext_ios::onSwapBuffers() {
+ glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer);
+ [fGLContext presentRenderbuffer:GL_RENDERBUFFER];
+}
+
+void GLWindowContext_ios::resize(int w, int h) {
+ // TODO: handle rotation
+ // [fGLContext update];
+ INHERITED::resize(w, h);
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeGLForIOS(const IOSWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new GLWindowContext_ios(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/ios/MetalWindowContext_ios.mm b/src/third_party/skia/tools/sk_app/ios/MetalWindowContext_ios.mm
new file mode 100644
index 0000000..f05ac20
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/MetalWindowContext_ios.mm
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/MetalWindowContext.h"
+#include "tools/sk_app/ios/WindowContextFactory_ios.h"
+
+#import <Metal/Metal.h>
+#import <UIKit/UIKit.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::IOSWindowInfo;
+using sk_app::MetalWindowContext;
+
+@interface MetalView : MainView
+@end
+
+@implementation MetalView
++ (Class) layerClass {
+ return [CAMetalLayer class];
+}
+@end
+
+namespace {
+
+class MetalWindowContext_ios : public MetalWindowContext {
+public:
+ MetalWindowContext_ios(const IOSWindowInfo&, const DisplayParams&);
+
+ ~MetalWindowContext_ios() override;
+
+ bool onInitializeContext() override;
+ void onDestroyContext() override;
+
+ void resize(int w, int h) override;
+
+private:
+ sk_app::Window_ios* fWindow;
+ UIViewController* fViewController;
+ MetalView* fMetalView;
+
+ typedef MetalWindowContext INHERITED;
+};
+
+MetalWindowContext_ios::MetalWindowContext_ios(const IOSWindowInfo& info,
+ const DisplayParams& params)
+ : INHERITED(params)
+ , fWindow(info.fWindow)
+ , fViewController(info.fViewController) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+MetalWindowContext_ios::~MetalWindowContext_ios() {
+ this->destroyContext();
+ [fMetalView removeFromSuperview];
+ [fMetalView release];
+}
+
+bool MetalWindowContext_ios::onInitializeContext() {
+ SkASSERT(nil != fWindow);
+ SkASSERT(nil != fViewController);
+
+ CGRect frameRect = [fViewController.view frame];
+ fMetalView = [[[MetalView alloc] initWithFrame:frameRect] initWithWindow:fWindow];
+ [fViewController.view addSubview:fMetalView];
+
+ fMetalLayer = (CAMetalLayer*)fMetalView.layer;
+ fMetalLayer.device = fDevice;
+ fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ fMetalLayer.drawableSize = frameRect.size;
+ fMetalLayer.frame = frameRect;
+
+ // TODO: need solution for iOS
+ // BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
+ // fMetalLayer.displaySyncEnabled = useVsync;
+ fMetalLayer.contentsGravity = kCAGravityTopLeft;
+
+ fWidth = frameRect.size.width;
+ fHeight = frameRect.size.height;
+
+ return true;
+}
+
+void MetalWindowContext_ios::onDestroyContext() {}
+
+void MetalWindowContext_ios::resize(int w, int h) {
+ // TODO: handle rotation
+ fMetalLayer.drawableSize = fMetalView.frame.size;
+ fMetalLayer.frame = fMetalView.frame;
+ fWidth = w;
+ fHeight = h;
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeMetalForIOS(const IOSWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new MetalWindowContext_ios(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.mm b/src/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.mm
new file mode 100644
index 0000000..16a21f4
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.mm
@@ -0,0 +1,196 @@
+
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColorFilter.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/ToolUtils.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/ios/WindowContextFactory_ios.h"
+
+#import <OpenGLES/ES3/gl.h>
+#import <UIKit/UIKit.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::IOSWindowInfo;
+using sk_app::GLWindowContext;
+
+@interface RasterView : MainView
+@end
+
+@implementation RasterView
++ (Class) layerClass {
+ return [CAEAGLLayer class];
+}
+@end
+
+namespace {
+
+// TODO: This still uses GL to handle the update rather than using a purely raster backend,
+// for historical reasons. Writing a pure raster backend would be better in the long run.
+
+class RasterWindowContext_ios : public GLWindowContext {
+public:
+ RasterWindowContext_ios(const IOSWindowInfo&, const DisplayParams&);
+
+ ~RasterWindowContext_ios() override;
+
+ sk_sp<SkSurface> getBackbufferSurface() override;
+
+ void onSwapBuffers() override;
+
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+ void onDestroyContext() override;
+
+ void resize(int w, int h) override;
+
+private:
+ sk_app::Window_ios* fWindow;
+ UIViewController* fViewController;
+ RasterView* fRasterView;
+ EAGLContext* fGLContext;
+ GLuint fFramebuffer;
+ GLuint fRenderbuffer;
+ sk_sp<SkSurface> fBackbufferSurface;
+
+ typedef GLWindowContext INHERITED;
+};
+
+RasterWindowContext_ios::RasterWindowContext_ios(const IOSWindowInfo& info,
+ const DisplayParams& params)
+ : INHERITED(params)
+ , fWindow(info.fWindow)
+ , fViewController(info.fViewController)
+ , fGLContext(nil) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+RasterWindowContext_ios::~RasterWindowContext_ios() {
+ this->destroyContext();
+ [fRasterView removeFromSuperview];
+ [fRasterView release];
+}
+
+sk_sp<const GrGLInterface> RasterWindowContext_ios::onInitializeContext() {
+ SkASSERT(nil != fViewController);
+ SkASSERT(!fGLContext);
+
+ CGRect frameRect = [fViewController.view frame];
+ fRasterView = [[[RasterView alloc] initWithFrame:frameRect] initWithWindow:fWindow];
+ [fViewController.view addSubview:fRasterView];
+
+ fGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
+
+ if (!fGLContext)
+ {
+ SkDebugf("Could Not Create OpenGL ES Context\n");
+ return nullptr;
+ }
+
+ if (![EAGLContext setCurrentContext:fGLContext]) {
+ SkDebugf("Could Not Set OpenGL ES Context As Current\n");
+ this->onDestroyContext();
+ return nullptr;
+ }
+
+ // Set up EAGLLayer
+ CAEAGLLayer* eaglLayer = (CAEAGLLayer*)fRasterView.layer;
+ eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO,
+ kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 };
+ eaglLayer.opaque = YES;
+ eaglLayer.frame = frameRect;
+ eaglLayer.contentsGravity = kCAGravityTopLeft;
+
+ // Set up framebuffer
+ glGenFramebuffers(1, &fFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, fFramebuffer);
+
+ glGenRenderbuffers(1, &fRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fRenderbuffer);
+
+ [fGLContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer];
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ SkDebugf("Invalid Framebuffer\n");
+ this->onDestroyContext();
+ return nullptr;
+ }
+
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 255);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ fStencilBits = 8;
+ fSampleCount = 1; // TODO: handle multisampling
+
+ fWidth = fViewController.view.frame.size.width;
+ fHeight = fViewController.view.frame.size.height;
+
+ glViewport(0, 0, fWidth, fHeight);
+
+ // make the offscreen image
+ SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
+ kPremul_SkAlphaType, fDisplayParams.fColorSpace);
+ fBackbufferSurface = SkSurface::MakeRaster(info);
+ return GrGLMakeNativeInterface();
+}
+
+void RasterWindowContext_ios::onDestroyContext() {
+ glDeleteFramebuffers(1, &fFramebuffer);
+ glDeleteRenderbuffers(1, &fRenderbuffer);
+ [EAGLContext setCurrentContext:nil];
+ [fGLContext release];
+ fGLContext = nil;
+}
+
+sk_sp<SkSurface> RasterWindowContext_ios::getBackbufferSurface() {
+ return fBackbufferSurface;
+}
+
+void RasterWindowContext_ios::onSwapBuffers() {
+ if (fBackbufferSurface) {
+ // We made/have an off-screen surface. Get the contents as an SkImage:
+ sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
+
+ sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface();
+ SkCanvas* gpuCanvas = gpuSurface->getCanvas();
+ gpuCanvas->drawImage(snapshot, 0, 0);
+ gpuCanvas->flush();
+ glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer);
+ [fGLContext presentRenderbuffer:GL_RENDERBUFFER];
+ }
+}
+
+void RasterWindowContext_ios::resize(int w, int h) {
+ // TODO: handle rotation
+ // [fGLContext update];
+ INHERITED::resize(w, h);
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeRasterForIOS(const IOSWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new RasterWindowContext_ios(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h b/src/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
new file mode 100644
index 0000000..513e23a
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
@@ -0,0 +1,46 @@
+
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_ios_DEFINED
+#define WindowContextFactory_ios_DEFINED
+
+#include "tools/sk_app/ios/Window_ios.h"
+
+#import <UIKit/UIKit.h>
+
+#include "tools/sk_app/WindowContext.h"
+
+#include <memory>
+
+namespace sk_app {
+
+struct DisplayParams;
+
+namespace window_context_factory {
+
+struct IOSWindowInfo {
+ sk_app::Window_ios* fWindow;
+ UIViewController* fViewController;
+};
+
+inline std::unique_ptr<WindowContext> MakeVulkanForIOS(const IOSWindowInfo&, const DisplayParams&) {
+ // No Vulkan support on iOS yet.
+ return nullptr;
+}
+
+std::unique_ptr<WindowContext> MakeMetalForIOS(const IOSWindowInfo&, const DisplayParams&);
+
+std::unique_ptr<WindowContext> MakeGLForIOS(const IOSWindowInfo&, const DisplayParams&);
+
+std::unique_ptr<WindowContext> MakeRasterForIOS(const IOSWindowInfo&, const DisplayParams&);
+
+} // namespace window_context_factory
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/ios/Window_ios.h b/src/third_party/skia/tools/sk_app/ios/Window_ios.h
new file mode 100644
index 0000000..037f992
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/Window_ios.h
@@ -0,0 +1,61 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef Window_ios_DEFINED
+#define Window_ios_DEFINED
+
+#include "include/private/SkChecksum.h"
+#include "src/core/SkTDynamicHash.h"
+#include "tools/sk_app/Window.h"
+
+#import <UIKit/UIKit.h>
+
+namespace sk_app {
+
+class Window_ios : public Window {
+public:
+ Window_ios()
+ : INHERITED()
+ , fWindow(nil) {}
+ ~Window_ios() override { this->closeWindow(); }
+
+ bool initWindow();
+
+ void setTitle(const char*) override {}
+ void show() override {}
+
+ bool attach(BackendType) override;
+
+ void onInval() override;
+
+ static void PaintWindow();
+
+ UIWindow* uiWindow() { return fWindow; }
+
+ static Window_ios* MainWindow() { return gWindow; }
+
+private:
+ void closeWindow();
+
+ UIWindow* fWindow;
+
+ static Window_ios* gWindow; // there should be only one
+
+ typedef Window INHERITED;
+};
+
+} // namespace sk_app
+
+//////////////////////////////////////////////////////////////////////////
+
+@interface MainView : UIView
+
+- (MainView*)initWithWindow:(sk_app::Window_ios*)initWindow;
+
+@end
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/ios/Window_ios.mm b/src/third_party/skia/tools/sk_app/ios/Window_ios.mm
new file mode 100644
index 0000000..82d8a73
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/Window_ios.mm
@@ -0,0 +1,251 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "tools/sk_app/ios/WindowContextFactory_ios.h"
+#include "tools/sk_app/ios/Window_ios.h"
+
+@interface WindowViewController : UIViewController
+
+- (WindowViewController*)initWithWindow:(sk_app::Window_ios*)initWindow;
+
+@end
+
+///////////////////////////////////////////////////////////////////////////////
+
+using sk_app::Window;
+
+namespace sk_app {
+
+Window_ios* Window_ios::gWindow = nullptr;
+
+Window* Window::CreateNativeWindow(void*) {
+ // already have a window
+ if (Window_ios::MainWindow()) {
+ return nullptr;
+ }
+
+ Window_ios* window = new Window_ios();
+ if (!window->initWindow()) {
+ delete window;
+ return nullptr;
+ }
+
+ return window;
+}
+
+bool Window_ios::initWindow() {
+ // we already have a window
+ if (fWindow) {
+ return true;
+ }
+
+ // Create a view controller to track certain events
+ WindowViewController* viewController = [[WindowViewController alloc] initWithWindow:this];
+ if (nil == viewController) {
+ return false;
+ }
+
+ fWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ if (nil == fWindow) {
+ [viewController release];
+ return false;
+ }
+ fWindow.backgroundColor = [UIColor whiteColor];
+
+ viewController.view = nil;
+ [fWindow setRootViewController:viewController];
+ [fWindow makeKeyAndVisible];
+
+ gWindow = this;
+
+ return true;
+}
+
+void Window_ios::closeWindow() {
+ if (nil != fWindow) {
+ gWindow = nullptr;
+ [fWindow release];
+ fWindow = nil;
+ }
+}
+
+bool Window_ios::attach(BackendType attachType) {
+ this->initWindow();
+
+ window_context_factory::IOSWindowInfo info;
+ info.fWindow = this;
+ info.fViewController = fWindow.rootViewController;
+ switch (attachType) {
+ case kRaster_BackendType:
+ fWindowContext = MakeRasterForIOS(info, fRequestedDisplayParams);
+ break;
+#ifdef SK_METAL
+ case kMetal_BackendType:
+ fWindowContext = MakeMetalForIOS(info, fRequestedDisplayParams);
+ break;
+#endif
+ case kNativeGL_BackendType:
+ default:
+ fWindowContext = MakeGLForIOS(info, fRequestedDisplayParams);
+ break;
+ }
+ this->onBackendCreated();
+
+ return (SkToBool(fWindowContext));
+}
+
+void Window_ios::PaintWindow() {
+ gWindow->onPaint();
+}
+
+void Window_ios::onInval() {
+ // TODO: send expose event
+}
+
+} // namespace sk_app
+
+///////////////////////////////////////////////////////////////////////////////
+
+@implementation WindowViewController {
+ sk_app::Window_ios* fWindow;
+}
+
+- (WindowViewController*)initWithWindow:(sk_app::Window_ios *)initWindow {
+ fWindow = initWindow;
+
+ return self;
+}
+
+- (void)viewDidLoad {
+ // nothing yet
+}
+
+- (void)didReceiveMemoryWarning {
+ // nothing yet
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+ withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+ // handle rotations here
+}
+@end
+
+///////////////////////////////////////////////////////////////////////////////
+
+@implementation MainView {
+ sk_app::Window_ios* fWindow;
+}
+
+- (IBAction)panGestureAction:(UIGestureRecognizer*)sender {
+ CGPoint location = [sender locationInView:self];
+ switch (sender.state) {
+ case UIGestureRecognizerStateBegan:
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kDown, skui::ModifierKey::kNone);
+ break;
+ case UIGestureRecognizerStateChanged:
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kMove, skui::ModifierKey::kNone);
+ break;
+ case UIGestureRecognizerStateEnded:
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kUp, skui::ModifierKey::kNone);
+ break;
+ case UIGestureRecognizerStateCancelled:
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kUp, skui::ModifierKey::kNone);
+ break;
+ default:
+ break;
+ }
+}
+
+- (IBAction)tapGestureAction:(UIGestureRecognizer*)sender {
+ CGPoint location = [sender locationInView:self];
+ switch (sender.state) {
+ case UIGestureRecognizerStateEnded:
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kDown, skui::ModifierKey::kNone);
+ fWindow->onMouse(location.x, location.y,
+ skui::InputState::kUp, skui::ModifierKey::kNone);
+ break;
+ default:
+ break;
+ }
+}
+
+- (IBAction)pinchGestureAction:(UIGestureRecognizer*)sender {
+ CGPoint location = [sender locationInView:self];
+ UIPinchGestureRecognizer* pinchGestureRecognizer = (UIPinchGestureRecognizer*) sender;
+ float scale = pinchGestureRecognizer.scale;
+ switch (sender.state) {
+ case UIGestureRecognizerStateBegan:
+ fWindow->onPinch(skui::InputState::kDown, scale, location.x, location.y);
+ break;
+ case UIGestureRecognizerStateChanged:
+ fWindow->onPinch(skui::InputState::kMove, scale, location.x, location.y);
+ break;
+ case UIGestureRecognizerStateEnded:
+ fWindow->onPinch(skui::InputState::kUp, scale, location.x, location.y);
+ break;
+ case UIGestureRecognizerStateCancelled:
+ fWindow->onPinch(skui::InputState::kUp, scale, location.x, location.y);
+ break;
+ default:
+ break;
+ }
+}
+
+- (IBAction)swipeRightGestureAction:(UIGestureRecognizer*)sender {
+ if (UIGestureRecognizerStateEnded == sender.state) {
+ fWindow->onFling(skui::InputState::kRight);
+ }
+}
+
+- (IBAction)swipeLeftGestureAction:(UIGestureRecognizer*)sender {
+ if (UIGestureRecognizerStateEnded == sender.state) {
+ fWindow->onFling(skui::InputState::kLeft);
+ }
+}
+
+- (MainView*)initWithWindow:(sk_app::Window_ios *)initWindow {
+ self = [super init];
+
+ UIPanGestureRecognizer* panGestureRecognizer = [[UIPanGestureRecognizer alloc] init];
+ panGestureRecognizer.maximumNumberOfTouches = 1;
+ [panGestureRecognizer addTarget:self action:@selector(panGestureAction:)];
+ [self addGestureRecognizer:panGestureRecognizer];
+
+ UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
+ [tapGestureRecognizer addTarget:self action:@selector(tapGestureAction:)];
+ [self addGestureRecognizer:tapGestureRecognizer];
+
+ UIPinchGestureRecognizer* pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] init];
+ [pinchGestureRecognizer addTarget:self action:@selector(pinchGestureAction:)];
+ [self addGestureRecognizer:pinchGestureRecognizer];
+
+ UISwipeGestureRecognizer* swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
+ swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
+ [swipeRightGestureRecognizer addTarget:self action:@selector(swipeRightGestureAction:)];
+ [self addGestureRecognizer:swipeRightGestureRecognizer];
+
+ UISwipeGestureRecognizer* swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
+ swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
+ [swipeLeftGestureRecognizer addTarget:self action:@selector(swipeLeftGestureAction:)];
+ [self addGestureRecognizer:swipeLeftGestureRecognizer];
+
+ // disable pan recognition until swipes fail
+ [panGestureRecognizer requireGestureRecognizerToFail:swipeLeftGestureRecognizer];
+ [panGestureRecognizer requireGestureRecognizerToFail:swipeRightGestureRecognizer];
+
+ fWindow = initWindow;
+
+ return self;
+}
+
+@end
+
diff --git a/src/third_party/skia/tools/sk_app/ios/main_ios.mm b/src/third_party/skia/tools/sk_app/ios/main_ios.mm
new file mode 100644
index 0000000..3bcc236
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/ios/main_ios.mm
@@ -0,0 +1,106 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "include/core/SkTypes.h"
+#include "include/private/SkTHash.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/ios/Window_ios.h"
+#include "tools/timer/Timer.h"
+
+#import <UIKit/UIKit.h>
+
+using sk_app::Application;
+
+////////////////////////////////////////////////////////////////////
+
+@interface AppDelegate : UIResponder<UIApplicationDelegate>
+
+@property (nonatomic, assign) BOOL done;
+@property (strong, nonatomic) UIWindow *window;
+
+@end
+
+@implementation AppDelegate
+
+@synthesize done = _done;
+@synthesize window = _window;
+
+- (void)applicationWillTerminate:(UIApplication *)sender {
+ _done = TRUE;
+}
+
+- (void)launchApp {
+ // Extract argc and argv from NSProcessInfo
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ int argc = arguments.count;
+ char** argv = (char **)malloc((argc+1) * sizeof(char *));
+ int i = 0;
+ for (NSString* string in arguments) {
+ size_t bufferSize = (string.length+1) * sizeof(char);
+ argv[i] = (char*)malloc(bufferSize);
+ [string getCString:argv[i]
+ maxLength:bufferSize
+ encoding:NSUTF8StringEncoding];
+ ++i;
+ }
+ argv[i] = NULL;
+
+ Application* app = Application::Create(argc, argv, nullptr);
+
+ // Free the memory we used for argc and argv
+ for (i = 0; i < argc; i++) {
+ free(argv[i]);
+ }
+ free(argv);
+
+ sk_app::Window_ios* mainWindow = sk_app::Window_ios::MainWindow();
+ if (!mainWindow) {
+ return;
+ }
+ self.window = mainWindow->uiWindow();
+
+ // take over the main event loop
+ bool done = false;
+ while (!done) {
+ // TODO: consider using a dispatch queue or CADisplayLink instead of this
+ const CFTimeInterval kSeconds = 0.000002;
+ CFRunLoopRunResult result;
+ do {
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kSeconds, TRUE);
+ } while (result == kCFRunLoopRunHandledSource);
+
+ // TODO: is this the right approach for iOS?
+ // Rather than depending on an iOS event to drive this, we treat our window
+ // invalidation flag as a separate event stream. Window::onPaint() will clear
+ // the invalidation flag, effectively removing it from the stream.
+ sk_app::Window_ios::PaintWindow();
+
+ app->onIdle();
+ }
+ delete app;
+}
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // let the system event loop run once, then launch into our main loop
+ [self performSelector:@selector(launchApp) withObject:nil afterDelay:0.0];
+
+ return YES;
+}
+
+@end
+
+///////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv) {
+ /* Give over control to run loop, AppDelegate will handle most things from here */
+ @autoreleasepool {
+ UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/third_party/skia/tools/sk_app/mac/DawnMTLWindowContext_mac.mm b/src/third_party/skia/tools/sk_app/mac/DawnMTLWindowContext_mac.mm
new file mode 100644
index 0000000..2ce22f3
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/DawnMTLWindowContext_mac.mm
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/DawnWindowContext.h"
+#include "tools/sk_app/mac/WindowContextFactory_mac.h"
+#include "common/SwapChainUtils.h"
+#include "dawn/dawncpp.h"
+#include "dawn/dawn_wsi.h"
+#include "dawn_native/DawnNative.h"
+#include "dawn_native/MetalBackend.h"
+
+#import <Metal/Metal.h>
+#import <QuartzCore/CAMetalLayer.h>
+#import <Cocoa/Cocoa.h>
+
+namespace sk_app {
+
+using sk_app::window_context_factory::MacWindowInfo;
+
+class DawnMTLWindowContext : public DawnWindowContext {
+public:
+ DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params);
+ ~DawnMTLWindowContext() override;
+ dawn::Device onInitializeContext() override;
+ void onDestroyContext() override;
+ DawnSwapChainImplementation createSwapChainImplementation(int width, int height,
+ const DisplayParams& params) override;
+ void onSwapBuffers() override;
+private:
+ NSView* fMainView;
+ id<MTLDevice> fMTLDevice;
+ CAMetalLayer* fLayer;
+};
+
+class SwapChainImplMTL {
+public:
+ typedef void WSIContext;
+ static DawnSwapChainImplementation Create(id<MTLDevice> device, CAMetalLayer* layer) {
+ auto impl = new SwapChainImplMTL(device, layer);
+ return CreateSwapChainImplementation<SwapChainImplMTL>(impl);
+ }
+
+ void Init(WSIContext* ctx) {}
+
+ SwapChainImplMTL(id<MTLDevice> device, CAMetalLayer* layer)
+ : fQueue([device newCommandQueue])
+ , fLayer(layer) {}
+
+ ~SwapChainImplMTL() {}
+
+ DawnSwapChainError Configure(DawnTextureFormat format, DawnTextureUsage,
+ uint32_t width, uint32_t height) {
+ if (format != DAWN_TEXTURE_FORMAT_RGBA8_UNORM) {
+ return "unsupported format";
+ }
+ SkASSERT(width > 0);
+ SkASSERT(height > 0);
+
+ return DAWN_SWAP_CHAIN_NO_ERROR;
+ }
+
+ DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture) {
+ fCurrentDrawable = [fLayer nextDrawable];
+
+ nextTexture->texture.ptr = reinterpret_cast<void*>(fCurrentDrawable.texture);
+
+ return DAWN_SWAP_CHAIN_NO_ERROR;
+ }
+
+ DawnSwapChainError Present() {
+ id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
+ [commandBuffer presentDrawable: fCurrentDrawable];
+ [commandBuffer commit];
+ return DAWN_SWAP_CHAIN_NO_ERROR;
+ }
+private:
+ id<MTLCommandQueue> fQueue;
+ CAMetalLayer* fLayer;
+ id<CAMetalDrawable> fCurrentDrawable = nil;
+};
+
+DawnMTLWindowContext::DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params)
+ : DawnWindowContext(params, dawn::TextureFormat::BGRA8Unorm)
+ , fMainView(info.fMainView) {
+ CGSize size = fMainView.bounds.size;
+ this->initializeContext(size.width, size.height);
+}
+
+DawnMTLWindowContext::~DawnMTLWindowContext() {
+ this->destroyContext();
+}
+
+DawnSwapChainImplementation DawnMTLWindowContext::createSwapChainImplementation(
+ int width, int height, const DisplayParams& params) {
+ return SwapChainImplMTL::Create(fMTLDevice, fLayer);
+}
+
+dawn::Device DawnMTLWindowContext::onInitializeContext() {
+ dawn::Device device = this->createDevice(dawn_native::BackendType::Metal);
+ if (!device) {
+ return nullptr;
+ }
+
+ fMTLDevice = dawn_native::metal::GetMetalDevice(device.Get());
+
+ CGSize size;
+ size.width = width();
+ size.height = height();
+
+ fLayer = [CAMetalLayer layer];
+ [fLayer setDevice:fMTLDevice];
+ [fLayer setPixelFormat: MTLPixelFormatBGRA8Unorm];
+ [fLayer setFramebufferOnly: YES];
+ [fLayer setDrawableSize: size];
+ [fLayer setColorspace: CGColorSpaceCreateDeviceRGB()];
+
+ [fMainView setWantsLayer: YES];
+ [fMainView setLayer: fLayer];
+
+ return device;
+}
+
+void DawnMTLWindowContext::onDestroyContext() {
+}
+
+void DawnMTLWindowContext::onSwapBuffers() {
+}
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeDawnMTLForMac(const MacWindowInfo& winInfo,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new DawnMTLWindowContext(winInfo, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.mm b/src/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.mm
new file mode 100644
index 0000000..0edcaa9
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.mm
@@ -0,0 +1,174 @@
+
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/mac/WindowContextFactory_mac.h"
+
+#include <OpenGL/gl.h>
+#include <Cocoa/Cocoa.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::MacWindowInfo;
+using sk_app::GLWindowContext;
+
+namespace {
+
+class GLWindowContext_mac : public GLWindowContext {
+public:
+ GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
+
+ ~GLWindowContext_mac() override;
+
+ void onSwapBuffers() override;
+
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+ void onDestroyContext() override;
+
+ void resize(int w, int h) override;
+
+private:
+ NSView* fMainView;
+ NSOpenGLContext* fGLContext;
+ NSOpenGLPixelFormat* fPixelFormat;
+
+ typedef GLWindowContext INHERITED;
+};
+
+GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
+ : INHERITED(params)
+ , fMainView(info.fMainView)
+ , fGLContext(nil) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+GLWindowContext_mac::~GLWindowContext_mac() {
+ [fPixelFormat release];
+ fPixelFormat = nil;
+ [fGLContext release];
+ fGLContext = nil;
+}
+
+sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
+ SkASSERT(nil != fMainView);
+
+ if (!fGLContext) {
+ // set up pixel format
+ constexpr int kMaxAttributes = 18;
+ NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
+ int numAttributes = 0;
+ attributes[numAttributes++] = NSOpenGLPFAAccelerated;
+ attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
+ attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
+ attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
+ attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
+ attributes[numAttributes++] = NSOpenGLPFAColorSize;
+ attributes[numAttributes++] = 24;
+ attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
+ attributes[numAttributes++] = 8;
+ attributes[numAttributes++] = NSOpenGLPFADepthSize;
+ attributes[numAttributes++] = 0;
+ attributes[numAttributes++] = NSOpenGLPFAStencilSize;
+ attributes[numAttributes++] = 8;
+ if (fDisplayParams.fMSAASampleCount > 1) {
+ attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
+ attributes[numAttributes++] = 1;
+ attributes[numAttributes++] = NSOpenGLPFASamples;
+ attributes[numAttributes++] = fDisplayParams.fMSAASampleCount;
+ } else {
+ attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
+ attributes[numAttributes++] = 0;
+ }
+ attributes[numAttributes++] = 0;
+ SkASSERT(numAttributes <= kMaxAttributes);
+
+ fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ if (nil == fPixelFormat) {
+ return nullptr;
+ }
+
+ // create context
+ fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
+ if (nil == fGLContext) {
+ [fPixelFormat release];
+ fPixelFormat = nil;
+ return nullptr;
+ }
+
+ // TODO: support Retina displays
+ [fMainView setWantsBestResolutionOpenGLSurface:NO];
+ [fGLContext setView:fMainView];
+ }
+
+ GLint swapInterval = fDisplayParams.fDisableVsync ? 0 : 1;
+ [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
+
+ // make context current
+ [fGLContext makeCurrentContext];
+
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 255);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ GLint stencilBits;
+ [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
+ fStencilBits = stencilBits;
+ GLint sampleCount;
+ [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+ fSampleCount = sampleCount;
+ fSampleCount = SkTMax(fSampleCount, 1);
+
+ const NSRect viewportRect = [fMainView frame];
+ fWidth = viewportRect.size.width;
+ fHeight = viewportRect.size.height;
+
+ glViewport(0, 0, fWidth, fHeight);
+
+ return GrGLMakeNativeInterface();
+}
+
+void GLWindowContext_mac::onDestroyContext() {
+ // We only need to tear down the GLContext if we've changed the sample count.
+ if (fGLContext && fSampleCount != fDisplayParams.fMSAASampleCount) {
+ [fPixelFormat release];
+ fPixelFormat = nil;
+ [fGLContext release];
+ fGLContext = nil;
+ }
+}
+
+void GLWindowContext_mac::onSwapBuffers() {
+ [fGLContext flushBuffer];
+}
+
+void GLWindowContext_mac::resize(int w, int h) {
+ [fGLContext update];
+ INHERITED::resize(w, h);
+}
+
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeGLForMac(const MacWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new GLWindowContext_mac(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/mac/MetalWindowContext_mac.mm b/src/third_party/skia/tools/sk_app/mac/MetalWindowContext_mac.mm
new file mode 100644
index 0000000..765980f
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/MetalWindowContext_mac.mm
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/MetalWindowContext.h"
+#include "tools/sk_app/mac/WindowContextFactory_mac.h"
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CAConstraintLayoutManager.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::MacWindowInfo;
+using sk_app::MetalWindowContext;
+
+namespace {
+
+class MetalWindowContext_mac : public MetalWindowContext {
+public:
+ MetalWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
+
+ ~MetalWindowContext_mac() override;
+
+ bool onInitializeContext() override;
+ void onDestroyContext() override;
+
+ void resize(int w, int h) override;
+
+private:
+ NSView* fMainView;
+
+ typedef MetalWindowContext INHERITED;
+};
+
+MetalWindowContext_mac::MetalWindowContext_mac(const MacWindowInfo& info,
+ const DisplayParams& params)
+ : INHERITED(params)
+ , fMainView(info.fMainView) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+MetalWindowContext_mac::~MetalWindowContext_mac() {
+ this->destroyContext();
+}
+
+bool MetalWindowContext_mac::onInitializeContext() {
+ SkASSERT(nil != fMainView);
+
+ fMetalLayer = [CAMetalLayer layer];
+ fMetalLayer.device = fDevice;
+ fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+
+ NSRect frameRect = [fMainView frame];
+ fMetalLayer.drawableSize = frameRect.size;
+ fMetalLayer.frame = frameRect;
+
+ BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
+ fMetalLayer.displaySyncEnabled = useVsync; // TODO: need solution for 10.12 or lower
+ fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
+ fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
+ fMetalLayer.contentsGravity = kCAGravityTopLeft;
+
+ fMainView.layer = fMetalLayer;
+ fMainView.wantsLayer = YES;
+
+ fWidth = frameRect.size.width;
+ fHeight = frameRect.size.height;
+
+ return true;
+}
+
+void MetalWindowContext_mac::onDestroyContext() {
+ fMainView.layer = nil;
+ fMainView.wantsLayer = NO;
+}
+
+void MetalWindowContext_mac::resize(int w, int h) {
+ fMetalLayer.drawableSize = fMainView.frame.size;
+ fMetalLayer.frame = fMainView.frame;
+ fWidth = w;
+ fHeight = h;
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeMetalForMac(const MacWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new MetalWindowContext_mac(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.mm b/src/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.mm
new file mode 100644
index 0000000..337a3fe
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.mm
@@ -0,0 +1,187 @@
+
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColorFilter.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/ToolUtils.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/mac/WindowContextFactory_mac.h"
+
+#include <OpenGL/gl.h>
+
+#include <Cocoa/Cocoa.h>
+
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::MacWindowInfo;
+using sk_app::GLWindowContext;
+
+namespace {
+
+// TODO: This still uses GL to handle the update rather than using a purely raster backend,
+// for historical reasons. Writing a pure raster backend would be better in the long run.
+
+class RasterWindowContext_mac : public GLWindowContext {
+public:
+ RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
+
+ ~RasterWindowContext_mac() override;
+
+ sk_sp<SkSurface> getBackbufferSurface() override;
+
+ void onSwapBuffers() override;
+
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+ void onDestroyContext() override {}
+
+ void resize(int w, int h) override;
+
+private:
+ NSView* fMainView;
+ NSOpenGLContext* fGLContext;
+ NSOpenGLPixelFormat* fPixelFormat;
+ sk_sp<SkSurface> fBackbufferSurface;
+
+ typedef GLWindowContext INHERITED;
+};
+
+RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
+ const DisplayParams& params)
+ : INHERITED(params)
+ , fMainView(info.fMainView)
+ , fGLContext(nil) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext();
+}
+
+RasterWindowContext_mac::~RasterWindowContext_mac() {
+ [fPixelFormat release];
+ fPixelFormat = nil;
+ [fGLContext release];
+ fGLContext = nil;
+}
+
+sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
+ SkASSERT(nil != fMainView);
+
+ if (!fGLContext) {
+ // set up pixel format
+ constexpr int kMaxAttributes = 18;
+ NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
+ int numAttributes = 0;
+ attributes[numAttributes++] = NSOpenGLPFAAccelerated;
+ attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
+ attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
+ attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
+ attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
+ attributes[numAttributes++] = NSOpenGLPFAColorSize;
+ attributes[numAttributes++] = 24;
+ attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
+ attributes[numAttributes++] = 8;
+ attributes[numAttributes++] = NSOpenGLPFADepthSize;
+ attributes[numAttributes++] = 0;
+ attributes[numAttributes++] = NSOpenGLPFAStencilSize;
+ attributes[numAttributes++] = 8;
+ if (fDisplayParams.fMSAASampleCount > 1) {
+ attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
+ attributes[numAttributes++] = 1;
+ attributes[numAttributes++] = NSOpenGLPFASamples;
+ attributes[numAttributes++] = fDisplayParams.fMSAASampleCount;
+ } else {
+ attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
+ attributes[numAttributes++] = 0;
+ }
+ attributes[numAttributes++] = 0;
+ SkASSERT(numAttributes <= kMaxAttributes);
+
+ fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ if (nil == fPixelFormat) {
+ return nullptr;
+ }
+
+ // create context
+ fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
+ if (nil == fGLContext) {
+ [fPixelFormat release];
+ fPixelFormat = nil;
+ return nullptr;
+ }
+
+ [fGLContext setView:fMainView];
+
+ GLint swapInterval = fDisplayParams.fDisableVsync ? 0 : 1;
+ [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
+ }
+
+ // make context current
+ [fGLContext makeCurrentContext];
+
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 255);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ GLint stencilBits;
+ [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
+ fStencilBits = stencilBits;
+ GLint sampleCount;
+ [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+ fSampleCount = sampleCount;
+ fSampleCount = SkTMax(fSampleCount, 1);
+
+ const NSRect viewportRect = [fMainView frame];
+ fWidth = viewportRect.size.width;
+ fHeight = viewportRect.size.height;
+ glViewport(0, 0, fWidth, fHeight);
+
+ // make the offscreen image
+ SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
+ kPremul_SkAlphaType, fDisplayParams.fColorSpace);
+ fBackbufferSurface = SkSurface::MakeRaster(info);
+ return GrGLMakeNativeInterface();
+}
+
+sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
+
+void RasterWindowContext_mac::onSwapBuffers() {
+ if (fBackbufferSurface) {
+ // We made/have an off-screen surface. Get the contents as an SkImage:
+ sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
+
+ sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface();
+ SkCanvas* gpuCanvas = gpuSurface->getCanvas();
+ gpuCanvas->drawImage(snapshot, 0, 0);
+ gpuCanvas->flush();
+
+ [fGLContext flushBuffer];
+ }
+}
+
+void RasterWindowContext_mac::resize(int w, int h) {
+ [fGLContext update];
+ INHERITED::resize(w, h);
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeRasterForMac(const MacWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new RasterWindowContext_mac(info, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h b/src/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
new file mode 100644
index 0000000..6833297
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_mac_DEFINED
+#define WindowContextFactory_mac_DEFINED
+
+#include "tools/sk_app/WindowContext.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include <memory>
+
+namespace sk_app {
+
+struct DisplayParams;
+
+namespace window_context_factory {
+
+struct MacWindowInfo {
+ NSView* fMainView;
+};
+
+#ifdef SK_VULKAN
+std::unique_ptr<WindowContext> MakeVulkanForMac(const MacWindowInfo&, const DisplayParams&);
+#else
+inline std::unique_ptr<WindowContext> MakeVulkanForMac(const MacWindowInfo&, const DisplayParams&) {
+ // No Vulkan support on Mac.
+ return nullptr;
+}
+#endif
+
+std::unique_ptr<WindowContext> MakeGLForMac(const MacWindowInfo&, const DisplayParams&);
+
+#ifdef SK_DAWN
+std::unique_ptr<WindowContext> MakeDawnMTLForMac(const MacWindowInfo&, const DisplayParams&);
+#endif
+
+std::unique_ptr<WindowContext> MakeRasterForMac(const MacWindowInfo&, const DisplayParams&);
+#ifdef SK_METAL
+std::unique_ptr<WindowContext> MakeMetalForMac(const MacWindowInfo&, const DisplayParams&);
+#endif
+
+} // namespace window_context_factory
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/mac/Window_mac.h b/src/third_party/skia/tools/sk_app/mac/Window_mac.h
new file mode 100644
index 0000000..761cd40
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/Window_mac.h
@@ -0,0 +1,60 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef Window_mac_DEFINED
+#define Window_mac_DEFINED
+
+#include "src/core/SkTDynamicHash.h"
+#include "tools/sk_app/Window.h"
+
+#import <Cocoa/Cocoa.h>
+
+namespace sk_app {
+
+class Window_mac : public Window {
+public:
+ Window_mac()
+ : INHERITED()
+ , fWindow(nil) {}
+ ~Window_mac() override {
+ this->closeWindow();
+ }
+
+ bool initWindow();
+
+ void setTitle(const char*) override;
+ void show() override;
+
+ bool attach(BackendType) override;
+
+ void onInval() override {}
+
+ static void PaintWindows();
+
+ static const NSInteger& GetKey(const Window_mac& w) {
+ return w.fWindowNumber;
+ }
+
+ static uint32_t Hash(const NSInteger& windowNumber) {
+ return windowNumber;
+ }
+
+ NSWindow* window() { return fWindow; }
+ void closeWindow();
+
+private:
+ NSWindow* fWindow;
+ NSInteger fWindowNumber;
+
+ static SkTDynamicHash<Window_mac, NSInteger> gWindowMap;
+
+ typedef Window INHERITED;
+};
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/sk_app/mac/Window_mac.mm b/src/third_party/skia/tools/sk_app/mac/Window_mac.mm
new file mode 100644
index 0000000..f3f5238
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/Window_mac.mm
@@ -0,0 +1,378 @@
+/*
+* Copyright 2019 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "src/core/SkUtils.h"
+#include "tools/sk_app/mac/WindowContextFactory_mac.h"
+#include "tools/sk_app/mac/Window_mac.h"
+#include "tools/skui/ModifierKey.h"
+
+@interface WindowDelegate : NSObject<NSWindowDelegate>
+
+- (WindowDelegate*)initWithWindow:(sk_app::Window_mac*)initWindow;
+
+@end
+
+@interface MainView : NSView
+
+- (MainView*)initWithWindow:(sk_app::Window_mac*)initWindow;
+
+@end
+
+///////////////////////////////////////////////////////////////////////////////
+
+using sk_app::Window;
+
+namespace sk_app {
+
+SkTDynamicHash<Window_mac, NSInteger> Window_mac::gWindowMap;
+
+Window* Window::CreateNativeWindow(void*) {
+ Window_mac* window = new Window_mac();
+ if (!window->initWindow()) {
+ delete window;
+ return nullptr;
+ }
+
+ return window;
+}
+
+bool Window_mac::initWindow() {
+ // we already have a window
+ if (fWindow) {
+ return true;
+ }
+
+ // Create a delegate to track certain events
+ WindowDelegate* delegate = [[WindowDelegate alloc] initWithWindow:this];
+ if (nil == delegate) {
+ return false;
+ }
+
+ // Create Cocoa window
+ constexpr int initialWidth = 1280;
+ constexpr int initialHeight = 960;
+ NSRect windowRect = NSMakeRect(100, 100, initialWidth, initialHeight);
+
+ NSUInteger windowStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask |
+ NSMiniaturizableWindowMask);
+
+ fWindow = [[NSWindow alloc] initWithContentRect:windowRect styleMask:windowStyle
+ backing:NSBackingStoreBuffered defer:NO];
+ if (nil == fWindow) {
+ [delegate release];
+ return false;
+ }
+
+ // create view
+ MainView* view = [[MainView alloc] initWithWindow:this] ;
+ if (nil == view) {
+ [fWindow release];
+ [delegate release];
+ return false;
+ }
+
+ [fWindow setContentView:view];
+ [fWindow makeFirstResponder:view];
+ [fWindow setDelegate:delegate];
+ [fWindow setAcceptsMouseMovedEvents:YES];
+ [fWindow setRestorable:NO];
+
+ // Should be retained by window now
+ [view release];
+
+ fWindowNumber = fWindow.windowNumber;
+ gWindowMap.add(this);
+
+ return true;
+}
+
+void Window_mac::closeWindow() {
+ if (nil != fWindow) {
+ gWindowMap.remove(fWindowNumber);
+ if (sk_app::Window_mac::gWindowMap.count() < 1) {
+ [NSApp terminate:fWindow];
+ }
+ [fWindow close];
+ fWindow = nil;
+ }
+}
+
+void Window_mac::setTitle(const char* title) {
+ NSString *titleString = [NSString stringWithCString:title encoding:NSUTF8StringEncoding];
+ [fWindow setTitle:titleString];
+}
+
+void Window_mac::show() {
+ [fWindow orderFront:nil];
+
+ [NSApp activateIgnoringOtherApps:YES];
+ [fWindow makeKeyAndOrderFront:NSApp];
+}
+
+bool Window_mac::attach(BackendType attachType) {
+ this->initWindow();
+
+ window_context_factory::MacWindowInfo info;
+ info.fMainView = [fWindow contentView];
+ switch (attachType) {
+ case kRaster_BackendType:
+ fWindowContext = MakeRasterForMac(info, fRequestedDisplayParams);
+ break;
+#ifdef SK_DAWN
+ case kDawn_BackendType:
+ fWindowContext = MakeDawnMTLForMac(info, fRequestedDisplayParams);
+ break;
+#endif
+#ifdef SK_VULKAN
+ case kVulkan_BackendType:
+ fWindowContext = MakeVulkanForMac(info, fRequestedDisplayParams);
+ break;
+#endif
+#ifdef SK_METAL
+ case kMetal_BackendType:
+ fWindowContext = MakeMetalForMac(info, fRequestedDisplayParams);
+ break;
+#endif
+ case kNativeGL_BackendType:
+ default:
+ fWindowContext = MakeGLForMac(info, fRequestedDisplayParams);
+ break;
+ }
+ this->onBackendCreated();
+
+ return (SkToBool(fWindowContext));
+}
+
+void Window_mac::PaintWindows() {
+ SkTDynamicHash<Window_mac, NSInteger>::Iter iter(&gWindowMap);
+ while (!iter.done()) {
+ if ((*iter).fIsContentInvalidated) {
+ (*iter).onPaint();
+ }
+ ++iter;
+ }
+}
+
+} // namespace sk_app
+
+///////////////////////////////////////////////////////////////////////////////
+
+@implementation WindowDelegate {
+ sk_app::Window_mac* fWindow;
+}
+
+- (WindowDelegate*)initWithWindow:(sk_app::Window_mac *)initWindow {
+ fWindow = initWindow;
+
+ return self;
+}
+
+- (void)windowDidResize:(NSNotification *)notification {
+ const NSRect mainRect = [fWindow->window().contentView bounds];
+
+ fWindow->onResize(mainRect.size.width, mainRect.size.height);
+ fWindow->inval();
+}
+
+- (BOOL)windowShouldClose:(NSWindow*)sender {
+ fWindow->closeWindow();
+
+ return FALSE;
+}
+
+@end
+
+///////////////////////////////////////////////////////////////////////////////
+
+static skui::Key get_key(unsigned short vk) {
+ // This will work with an ANSI QWERTY keyboard.
+ // Something more robust would be needed to support alternate keyboards.
+ static const struct {
+ unsigned short fVK;
+ skui::Key fKey;
+ } gPair[] = {
+ { 0x33, skui::Key::kBack },
+ { 0x24, skui::Key::kOK },
+ { 0x7E, skui::Key::kUp },
+ { 0x7D, skui::Key::kDown },
+ { 0x7B, skui::Key::kLeft },
+ { 0x7C, skui::Key::kRight },
+ { 0x30, skui::Key::kTab },
+ { 0x74, skui::Key::kPageUp },
+ { 0x79, skui::Key::kPageDown },
+ { 0x73, skui::Key::kHome },
+ { 0x77, skui::Key::kEnd },
+ { 0x75, skui::Key::kDelete },
+ { 0x35, skui::Key::kEscape },
+ { 0x38, skui::Key::kShift },
+ { 0x3C, skui::Key::kShift },
+ { 0x3B, skui::Key::kCtrl },
+ { 0x3E, skui::Key::kCtrl },
+ { 0x3A, skui::Key::kOption },
+ { 0x3D, skui::Key::kOption },
+ { 0x00, skui::Key::kA },
+ { 0x08, skui::Key::kC },
+ { 0x09, skui::Key::kV },
+ { 0x07, skui::Key::kX },
+ { 0x10, skui::Key::kY },
+ { 0x06, skui::Key::kZ },
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+ if (gPair[i].fVK == vk) {
+ return gPair[i].fKey;
+ }
+ }
+
+ return skui::Key::kNONE;
+}
+
+static skui::ModifierKey get_modifiers(const NSEvent* event) {
+ NSUInteger modifierFlags = [event modifierFlags];
+ skui::ModifierKey modifiers = skui::ModifierKey::kNone;
+
+ if (modifierFlags & NSEventModifierFlagCommand) {
+ modifiers |= skui::ModifierKey::kCommand;
+ }
+ if (modifierFlags & NSEventModifierFlagShift) {
+ modifiers |= skui::ModifierKey::kShift;
+ }
+ if (modifierFlags & NSEventModifierFlagControl) {
+ modifiers |= skui::ModifierKey::kControl;
+ }
+ if (modifierFlags & NSEventModifierFlagOption) {
+ modifiers |= skui::ModifierKey::kOption;
+ }
+
+ if ((NSKeyDown == [event type] || NSKeyUp == [event type]) &&
+ NO == [event isARepeat]) {
+ modifiers |= skui::ModifierKey::kFirstPress;
+ }
+
+ return modifiers;
+}
+
+@implementation MainView {
+ sk_app::Window_mac* fWindow;
+ // A TrackingArea prevents us from capturing events outside the view
+ NSTrackingArea* fTrackingArea;
+}
+
+- (MainView*)initWithWindow:(sk_app::Window_mac *)initWindow {
+ self = [super init];
+
+ fWindow = initWindow;
+ fTrackingArea = nil;
+
+ [self updateTrackingAreas];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [fTrackingArea release];
+ [super dealloc];
+}
+
+- (BOOL)isOpaque {
+ return YES;
+}
+
+- (BOOL)canBecomeKeyView {
+ return YES;
+}
+
+- (BOOL)acceptsFirstResponder {
+ return YES;
+}
+
+- (void)updateTrackingAreas {
+ if (fTrackingArea != nil) {
+ [self removeTrackingArea:fTrackingArea];
+ [fTrackingArea release];
+ }
+
+ const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow |
+ NSTrackingEnabledDuringMouseDrag |
+ NSTrackingCursorUpdate |
+ NSTrackingInVisibleRect |
+ NSTrackingAssumeInside;
+
+ fTrackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
+ options:options
+ owner:self
+ userInfo:nil];
+
+ [self addTrackingArea:fTrackingArea];
+ [super updateTrackingAreas];
+}
+
+- (void)keyDown:(NSEvent *)event {
+ skui::Key key = get_key([event keyCode]);
+ if (key != skui::Key::kNONE) {
+ if (!fWindow->onKey(key, skui::InputState::kDown, get_modifiers(event))) {
+ if (skui::Key::kEscape == key) {
+ [NSApp terminate:fWindow->window()];
+ }
+ }
+ }
+
+ NSString* characters = [event charactersIgnoringModifiers];
+ NSUInteger len = [characters length];
+ if (len > 0) {
+ unichar* charBuffer = new unichar[len+1];
+ [characters getCharacters:charBuffer range:NSMakeRange(0, len)];
+ for (NSUInteger i = 0; i < len; ++i) {
+ (void) fWindow->onChar((SkUnichar) charBuffer[i], get_modifiers(event));
+ }
+ delete [] charBuffer;
+ }
+}
+
+- (void)keyUp:(NSEvent *)event {
+ skui::Key key = get_key([event keyCode]);
+ if (key != skui::Key::kNONE) {
+ (void) fWindow->onKey(key, skui::InputState::kUp, get_modifiers(event));
+ }
+}
+
+- (void)mouseDown:(NSEvent *)event {
+ const NSPoint pos = [event locationInWindow];
+ const NSRect rect = [fWindow->window().contentView frame];
+ fWindow->onMouse(pos.x, rect.size.height - pos.y, skui::InputState::kDown,
+ get_modifiers(event));
+}
+
+- (void)mouseUp:(NSEvent *)event {
+ const NSPoint pos = [event locationInWindow];
+ const NSRect rect = [fWindow->window().contentView frame];
+ fWindow->onMouse(pos.x, rect.size.height - pos.y, skui::InputState::kUp,
+ get_modifiers(event));
+}
+
+- (void)mouseDragged:(NSEvent *)event {
+ [self mouseMoved:event];
+}
+
+- (void)mouseMoved:(NSEvent *)event {
+ const NSPoint pos = [event locationInWindow];
+ const NSRect rect = [fWindow->window().contentView frame];
+ fWindow->onMouse(pos.x, rect.size.height - pos.y, skui::InputState::kMove,
+ get_modifiers(event));
+}
+
+- (void)scrollWheel:(NSEvent *)event {
+ // TODO: support hasPreciseScrollingDeltas?
+ fWindow->onMouseWheel([event scrollingDeltaY], get_modifiers(event));
+}
+
+- (void)drawRect:(NSRect)rect {
+ fWindow->onPaint();
+}
+
+@end
diff --git a/src/third_party/skia/tools/sk_app/mac/main_mac.mm b/src/third_party/skia/tools/sk_app/mac/main_mac.mm
new file mode 100644
index 0000000..f200abf
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/mac/main_mac.mm
@@ -0,0 +1,113 @@
+/*
+* Copyright 2019 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#import <Cocoa/Cocoa.h>
+
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/mac/Window_mac.h"
+
+@interface AppDelegate : NSObject<NSApplicationDelegate, NSWindowDelegate>
+
+@property (nonatomic, assign) BOOL done;
+
+@end
+
+@implementation AppDelegate : NSObject
+
+@synthesize done = _done;
+
+- (id)init {
+ self = [super init];
+ _done = FALSE;
+ return self;
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+ _done = TRUE;
+ return NSTerminateCancel;
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification {
+ [NSApp stop:nil];
+}
+
+@end
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+using sk_app::Application;
+using sk_app::Window_mac;
+
+int main(int argc, char * argv[]) {
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
+ // we only run on systems that support at least Core Profile 3.2
+ return EXIT_FAILURE;
+#endif
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ [NSApplication sharedApplication];
+
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ //Create the application menu.
+ NSMenu* menuBar=[[NSMenu alloc] initWithTitle:@"AMainMenu"];
+ [NSApp setMainMenu:menuBar];
+
+ NSMenuItem* item;
+ NSMenu* subMenu;
+
+ item=[[NSMenuItem alloc] initWithTitle:@"Apple" action:NULL keyEquivalent:@""];
+ [menuBar addItem:item];
+ subMenu=[[NSMenu alloc] initWithTitle:@"Apple"];
+ [menuBar setSubmenu:subMenu forItem:item];
+ [item release];
+ item=[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
+ [subMenu addItem:item];
+ [item release];
+ [subMenu release];
+
+ // Set AppDelegate to catch certain global events
+ AppDelegate* appDelegate = [[AppDelegate alloc] init];
+ [NSApp setDelegate:appDelegate];
+
+ Application* app = Application::Create(argc, argv, nullptr);
+
+ // This will run until the application finishes launching, then lets us take over
+ [NSApp run];
+
+ // Now we process the events
+ while (![appDelegate done]) {
+ NSEvent* event;
+ do {
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ [NSApp sendEvent:event];
+ } while (event != nil);
+
+ [pool drain];
+ pool = [[NSAutoreleasePool alloc] init];
+
+ // Rather than depending on a Mac event to drive this, we treat our window
+ // invalidation flag as a separate event stream. Window::onPaint() will clear
+ // the invalidation flag, effectively removing it from the stream.
+ Window_mac::PaintWindows();
+
+ app->onIdle();
+ }
+
+ delete app;
+
+ [NSApp setDelegate:nil];
+ [appDelegate release];
+
+ [menuBar release];
+ [pool release];
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/third_party/skia/tools/sk_app/unix/DawnVulkanWindowContext_unix.cpp b/src/third_party/skia/tools/sk_app/unix/DawnVulkanWindowContext_unix.cpp
new file mode 100644
index 0000000..b8eee27
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/DawnVulkanWindowContext_unix.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/DawnWindowContext.h"
+#include "tools/sk_app/unix/WindowContextFactory_unix.h"
+#include "dawn_native/DawnNative.h"
+#include "dawn_native/VulkanBackend.h"
+#include "src/ports/SkOSLibrary.h"
+#include "tools/gpu/vk/VkTestUtils.h"
+
+#include <vulkan/vulkan.h>
+#include <X11/Xlib-xcb.h>
+
+using sk_app::window_context_factory::XlibWindowInfo;
+using sk_app::DisplayParams;
+using sk_app::DawnWindowContext;
+
+namespace sk_app {
+
+class DawnVulkanWindowContext_xlib : public DawnWindowContext {
+public:
+ DawnVulkanWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
+ ~DawnVulkanWindowContext_xlib() override {}
+ dawn::Device onInitializeContext() override;
+ void onDestroyContext() override {}
+ DawnSwapChainImplementation createSwapChainImplementation(
+ int width, int height, const DisplayParams& params) override;
+ void onSwapBuffers() override {}
+
+private:
+ Display* fDisplay;
+ XWindow fWindow;
+ VkSurfaceKHR fVkSurface = nullptr;
+
+ typedef DawnWindowContext INHERITED;
+};
+
+DawnVulkanWindowContext_xlib::DawnVulkanWindowContext_xlib(const XlibWindowInfo& winInfo,
+ const DisplayParams& params)
+ : INHERITED(params, dawn::TextureFormat::BGRA8Unorm)
+ , fDisplay(winInfo.fDisplay)
+ , fWindow(winInfo.fWindow) {
+ XWindow root;
+ int x, y;
+ unsigned int border_width, depth;
+ unsigned int width, height;
+ XGetGeometry(fDisplay, fWindow, &root, &x, &y, &width, &height, &border_width, &depth);
+ this->initializeContext(width, height);
+}
+
+DawnSwapChainImplementation DawnVulkanWindowContext_xlib::createSwapChainImplementation(
+ int width, int height, const DisplayParams& params) {
+ return dawn_native::vulkan::CreateNativeSwapChainImpl(fDevice.Get(), fVkSurface);
+}
+
+dawn::Device DawnVulkanWindowContext_xlib::onInitializeContext() {
+ dawn::Device device = this->createDevice(dawn_native::BackendType::Vulkan);
+ if (!device) {
+ return nullptr;
+ }
+
+ void *vkLib = DynamicLoadLibrary("libvulkan.so.1");
+ if (!vkLib) {
+ return nullptr;
+ }
+ VkInstance instance = dawn_native::vulkan::GetInstance(device.Get());
+ if (!instance) {
+ return nullptr;
+ }
+ auto createXcbSurfaceKHR =
+ reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(GetProcedureAddress(vkLib,
+ "vkCreateXcbSurfaceKHR"));
+ if (!createXcbSurfaceKHR) {
+ printf("couldn't get extensions :(\n");
+ return nullptr;
+ }
+
+ VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
+ memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.pNext = nullptr;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.connection = XGetXCBConnection(fDisplay);
+ surfaceCreateInfo.window = fWindow;
+
+ createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &fVkSurface);
+ return device;
+}
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeDawnVulkanForXlib(const XlibWindowInfo& winInfo,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new DawnVulkanWindowContext_xlib(winInfo, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+}
+
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp b/src/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
new file mode 100644
index 0000000..4de886d
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
@@ -0,0 +1,196 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/gl/GrGLInterface.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/unix/WindowContextFactory_unix.h"
+
+#include <GL/gl.h>
+
+using sk_app::window_context_factory::XlibWindowInfo;
+using sk_app::DisplayParams;
+using sk_app::GLWindowContext;
+
+namespace {
+
+static bool gCtxErrorOccurred = false;
+static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
+ gCtxErrorOccurred = true;
+ return 0;
+}
+
+class GLWindowContext_xlib : public GLWindowContext {
+public:
+ GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
+ ~GLWindowContext_xlib() override;
+
+ void onSwapBuffers() override;
+
+ void onDestroyContext() override;
+
+protected:
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+
+private:
+ GLWindowContext_xlib(void*, const DisplayParams&);
+
+ Display* fDisplay;
+ XWindow fWindow;
+ GLXFBConfig* fFBConfig;
+ XVisualInfo* fVisualInfo;
+ GLXContext fGLContext;
+
+ typedef GLWindowContext INHERITED;
+};
+
+GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
+ : INHERITED(params)
+ , fDisplay(winInfo.fDisplay)
+ , fWindow(winInfo.fWindow)
+ , fFBConfig(winInfo.fFBConfig)
+ , fVisualInfo(winInfo.fVisualInfo)
+ , fGLContext() {
+ fWidth = winInfo.fWidth;
+ fHeight = winInfo.fHeight;
+ this->initializeContext();
+}
+
+using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+
+sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
+ SkASSERT(fDisplay);
+ SkASSERT(!fGLContext);
+ sk_sp<const GrGLInterface> interface;
+ bool current = false;
+
+ // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
+ // created with this rather than glXCreateContext.
+ CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB(
+ (const GLubyte*)"glXCreateContextAttribsARB");
+ if (createContextAttribs && fFBConfig) {
+ // Install Xlib error handler that will set gCtxErrorOccurred
+ int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
+
+ // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features
+ // have been removed).
+ for (int minor = 2; minor >= 0 && !fGLContext; --minor) {
+ // Ganesh prefers a compatibility profile for possible NVPR support. However, RenderDoc
+ // requires a core profile. Edit this code to use RenderDoc.
+ for (int profile : {GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB}) {
+ gCtxErrorOccurred = false;
+ int attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor,
+ GLX_CONTEXT_PROFILE_MASK_ARB, profile,
+ 0
+ };
+ fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs);
+
+ // Sync to ensure any errors generated are processed.
+ XSync(fDisplay, False);
+ if (gCtxErrorOccurred) { continue; }
+
+ if (fGLContext && profile == GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&
+ glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
+ current = true;
+ // Look to see if RenderDoc is attached. If so, re-create the context with a
+ // core profile.
+ interface = GrGLMakeNativeInterface();
+ if (interface && interface->fExtensions.has("GL_EXT_debug_tool")) {
+ interface.reset();
+ glXMakeCurrent(fDisplay, None, nullptr);
+ glXDestroyContext(fDisplay, fGLContext);
+ current = false;
+ fGLContext = nullptr;
+ }
+ }
+ if (fGLContext) {
+ break;
+ }
+ }
+ }
+ // Restore the original error handler
+ XSetErrorHandler(oldHandler);
+ }
+ if (!fGLContext) {
+ fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
+ }
+ if (!fGLContext) {
+ return nullptr;
+ }
+
+ if (!current && !glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
+ return nullptr;
+ }
+
+ const char* glxExtensions = glXQueryExtensionsString(fDisplay, DefaultScreen(fDisplay));
+ if (glxExtensions) {
+ if (strstr(glxExtensions, "GLX_EXT_swap_control")) {
+ PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT =
+ (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB(
+ (const GLubyte*)"glXSwapIntervalEXT");
+ glXSwapIntervalEXT(fDisplay, fWindow, fDisplayParams.fDisableVsync ? 0 : 1);
+ }
+ }
+
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 0);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
+ glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
+
+ XWindow root;
+ int x, y;
+ unsigned int border_width, depth;
+ XGetGeometry(fDisplay, fWindow, &root, &x, &y, (unsigned int*)&fWidth, (unsigned int*)&fHeight,
+ &border_width, &depth);
+ glViewport(0, 0, fWidth, fHeight);
+
+ return interface ? interface : GrGLMakeNativeInterface();
+}
+
+GLWindowContext_xlib::~GLWindowContext_xlib() {
+ this->destroyContext();
+}
+
+void GLWindowContext_xlib::onDestroyContext() {
+ if (!fDisplay || !fGLContext) {
+ return;
+ }
+ glXMakeCurrent(fDisplay, None, nullptr);
+ glXDestroyContext(fDisplay, fGLContext);
+ fGLContext = nullptr;
+}
+
+void GLWindowContext_xlib::onSwapBuffers() {
+ if (fDisplay && fGLContext) {
+ glXSwapBuffers(fDisplay, fWindow);
+ }
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeGLForXlib(const XlibWindowInfo& winInfo,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new GLWindowContext_xlib(winInfo, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp b/src/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp
similarity index 83%
rename from src/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
rename to src/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp
index 6bfa6fd..e8ae942 100644
--- a/src/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
+++ b/src/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp
@@ -5,9 +5,9 @@
* found in the LICENSE file.
*/
-#include "WindowContextFactory_unix.h"
-#include "../RasterWindowContext.h"
-#include "SkSurface.h"
+#include "include/core/SkSurface.h"
+#include "tools/sk_app/RasterWindowContext.h"
+#include "tools/sk_app/unix/WindowContextFactory_unix.h"
using sk_app::RasterWindowContext;
using sk_app::DisplayParams;
@@ -54,7 +54,7 @@
void RasterWindowContext_xlib::resize(int w, int h) {
SkImageInfo info = SkImageInfo::Make(w, h, fDisplayParams.fColorType, kPremul_SkAlphaType,
fDisplayParams.fColorSpace);
- fBackbufferSurface = SkSurface::MakeRaster(info);
+ fBackbufferSurface = SkSurface::MakeRaster(info, &fDisplayParams.fSurfaceProps);
}
@@ -90,11 +90,11 @@
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewRasterForXlib(const XlibWindowInfo& info, const DisplayParams& params) {
- WindowContext* ctx = new RasterWindowContext_xlib(info.fDisplay, info.fWindow, info.fWidth,
- info.fHeight, params);
+std::unique_ptr<WindowContext> MakeRasterForXlib(const XlibWindowInfo& info,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new RasterWindowContext_xlib(
+ info.fDisplay, info.fWindow, info.fWidth, info.fHeight, params));
if (!ctx->isValid()) {
- delete ctx;
ctx = nullptr;
}
return ctx;
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp b/src/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp
similarity index 64%
rename from src/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
rename to src/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp
index b94e8ed..6f0ce0a 100644
--- a/src/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
+++ b/src/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp
@@ -6,26 +6,35 @@
* found in the LICENSE file.
*/
+#include "include/gpu/vk/GrVkVulkan.h"
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
+#include "src/gpu/vk/GrVkInterface.h"
+#include "src/gpu/vk/GrVkUtil.h"
+
+#include "tools/gpu/vk/VkTestUtils.h"
+
+#include "tools/sk_app/VulkanWindowContext.h"
+#include "tools/sk_app/unix/WindowContextFactory_unix.h"
#include <X11/Xlib-xcb.h>
-#include "WindowContextFactory_unix.h"
-#include "../VulkanWindowContext.h"
-
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewVulkanForXlib(const XlibWindowInfo& info, const DisplayParams& displayParams) {
- auto createVkSurface = [&info](VkInstance instance) -> VkSurfaceKHR {
+std::unique_ptr<WindowContext> MakeVulkanForXlib(const XlibWindowInfo& info,
+ const DisplayParams& displayParams) {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [&info, instProc](VkInstance instance) -> VkSurfaceKHR {
static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
if (!createXcbSurfaceKHR) {
createXcbSurfaceKHR =
- (PFN_vkCreateXcbSurfaceKHR) vkGetInstanceProcAddr(instance,
- "vkCreateXcbSurfaceKHR");
+ (PFN_vkCreateXcbSurfaceKHR) instProc(instance, "vkCreateXcbSurfaceKHR");
}
VkSurfaceKHR surface;
@@ -46,15 +55,14 @@
return surface;
};
- auto canPresent = [&info](VkInstance instance, VkPhysicalDevice physDev,
+ auto canPresent = [&info, instProc](VkInstance instance, VkPhysicalDevice physDev,
uint32_t queueFamilyIndex) {
static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
if (!getPhysicalDeviceXcbPresentationSupportKHR) {
getPhysicalDeviceXcbPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
- vkGetInstanceProcAddr(instance,
- "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+ instProc(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
}
@@ -66,12 +74,12 @@
visualID);
return (VK_FALSE != check);
};
- WindowContext* context = new VulkanWindowContext(displayParams, createVkSurface, canPresent);
- if (!context->isValid()) {
- delete context;
+ std::unique_ptr<WindowContext> ctx(
+ new VulkanWindowContext(displayParams, createVkSurface, canPresent, instProc, devProc));
+ if (!ctx->isValid()) {
return nullptr;
}
- return context;
+ return ctx;
}
} // namespace VulkanWindowContextFactory
diff --git a/src/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h b/src/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h
new file mode 100644
index 0000000..4731097
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_unix_DEFINED
+#define WindowContextFactory_unix_DEFINED
+
+// dawncpp.h and X.h don't get along. Include this first, before X11 defines None, Success etc.
+#ifdef SK_DAWN
+#include "dawn/dawncpp.h"
+#endif
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+#include <memory>
+
+typedef Window XWindow;
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+struct XlibWindowInfo {
+ Display* fDisplay;
+ XWindow fWindow;
+ GLXFBConfig* fFBConfig;
+ XVisualInfo* fVisualInfo;
+ int fWidth;
+ int fHeight;
+};
+
+std::unique_ptr<WindowContext> MakeVulkanForXlib(const XlibWindowInfo&, const DisplayParams&);
+
+std::unique_ptr<WindowContext> MakeGLForXlib(const XlibWindowInfo&, const DisplayParams&);
+
+#ifdef SK_DAWN
+std::unique_ptr<WindowContext> MakeDawnVulkanForXlib(const XlibWindowInfo&, const DisplayParams&);
+#endif
+
+std::unique_ptr<WindowContext> MakeRasterForXlib(const XlibWindowInfo&, const DisplayParams&);
+
+} // namespace window_context_factory
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp b/src/third_party/skia/tools/sk_app/unix/Window_unix.cpp
similarity index 73%
rename from src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp
rename to src/third_party/skia/tools/sk_app/unix/Window_unix.cpp
index ef0d85e..32e0447 100644
--- a/src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp
+++ b/src/third_party/skia/tools/sk_app/unix/Window_unix.cpp
@@ -2,20 +2,26 @@
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
+* f 49
+* Prev
+* Up
+*
+*
* found in the LICENSE file.
*/
//#include <tchar.h>
-#include "WindowContextFactory_unix.h"
+#include "tools/sk_app/unix/WindowContextFactory_unix.h"
-#include "SkUtils.h"
-#include "Timer.h"
-#include "../GLWindowContext.h"
-#include "Window_unix.h"
+#include "src/utils/SkUTF.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/unix/Window_unix.h"
+#include "tools/skui/ModifierKey.h"
+#include "tools/timer/Timer.h"
extern "C" {
- #include "keysym2ucs.h"
+ #include "tools/sk_app/unix/keysym2ucs.h"
}
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
@@ -37,8 +43,8 @@
return window;
}
-const long kEventMask = ExposureMask | StructureNotifyMask |
- KeyPressMask | KeyReleaseMask |
+const long kEventMask = ExposureMask | StructureNotifyMask |
+ KeyPressMask | KeyReleaseMask |
PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
bool Window_unix::initWindow(Display* display) {
@@ -72,7 +78,7 @@
None
};
SkASSERT(nullptr == fVisualInfo);
- if (fRequestedDisplayParams.fMSAASampleCount > 0) {
+ if (fRequestedDisplayParams.fMSAASampleCount > 1) {
static const GLint kChooseFBConifgAttCnt = SK_ARRAY_COUNT(kChooseFBConfigAtt);
GLint msaaChooseFBConfigAtt[kChooseFBConifgAttCnt + 4];
memcpy(msaaChooseFBConfigAtt, kChooseFBConfigAtt, sizeof(kChooseFBConfigAtt));
@@ -184,57 +190,57 @@
}
}
-static Window::Key get_key(KeySym keysym) {
+static skui::Key get_key(KeySym keysym) {
static const struct {
KeySym fXK;
- Window::Key fKey;
+ skui::Key fKey;
} gPair[] = {
- { XK_BackSpace, Window::Key::kBack },
- { XK_Clear, Window::Key::kBack },
- { XK_Return, Window::Key::kOK },
- { XK_Up, Window::Key::kUp },
- { XK_Down, Window::Key::kDown },
- { XK_Left, Window::Key::kLeft },
- { XK_Right, Window::Key::kRight },
- { XK_Tab, Window::Key::kTab },
- { XK_Page_Up, Window::Key::kPageUp },
- { XK_Page_Down, Window::Key::kPageDown },
- { XK_Home, Window::Key::kHome },
- { XK_End, Window::Key::kEnd },
- { XK_Delete, Window::Key::kDelete },
- { XK_Escape, Window::Key::kEscape },
- { XK_Shift_L, Window::Key::kShift },
- { XK_Shift_R, Window::Key::kShift },
- { XK_Control_L, Window::Key::kCtrl },
- { XK_Control_R, Window::Key::kCtrl },
- { XK_Alt_L, Window::Key::kOption },
- { XK_Alt_R, Window::Key::kOption },
- { 'A', Window::Key::kA },
- { 'C', Window::Key::kC },
- { 'V', Window::Key::kV },
- { 'X', Window::Key::kX },
- { 'Y', Window::Key::kY },
- { 'Z', Window::Key::kZ },
+ { XK_BackSpace, skui::Key::kBack },
+ { XK_Clear, skui::Key::kBack },
+ { XK_Return, skui::Key::kOK },
+ { XK_Up, skui::Key::kUp },
+ { XK_Down, skui::Key::kDown },
+ { XK_Left, skui::Key::kLeft },
+ { XK_Right, skui::Key::kRight },
+ { XK_Tab, skui::Key::kTab },
+ { XK_Page_Up, skui::Key::kPageUp },
+ { XK_Page_Down, skui::Key::kPageDown },
+ { XK_Home, skui::Key::kHome },
+ { XK_End, skui::Key::kEnd },
+ { XK_Delete, skui::Key::kDelete },
+ { XK_Escape, skui::Key::kEscape },
+ { XK_Shift_L, skui::Key::kShift },
+ { XK_Shift_R, skui::Key::kShift },
+ { XK_Control_L, skui::Key::kCtrl },
+ { XK_Control_R, skui::Key::kCtrl },
+ { XK_Alt_L, skui::Key::kOption },
+ { XK_Alt_R, skui::Key::kOption },
+ { 'A', skui::Key::kA },
+ { 'C', skui::Key::kC },
+ { 'V', skui::Key::kV },
+ { 'X', skui::Key::kX },
+ { 'Y', skui::Key::kY },
+ { 'Z', skui::Key::kZ },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
if (gPair[i].fXK == keysym) {
return gPair[i].fKey;
}
}
- return Window::Key::kNONE;
+ return skui::Key::kNONE;
}
-static uint32_t get_modifiers(const XEvent& event) {
+static skui::ModifierKey get_modifiers(const XEvent& event) {
static const struct {
unsigned fXMask;
- unsigned fSkMask;
+ skui::ModifierKey fSkMask;
} gModifiers[] = {
- { ShiftMask, Window::kShift_ModifierKey },
- { ControlMask, Window::kControl_ModifierKey },
- { Mod1Mask, Window::kOption_ModifierKey },
+ { ShiftMask, skui::ModifierKey::kShift },
+ { ControlMask, skui::ModifierKey::kControl },
+ { Mod1Mask, skui::ModifierKey::kOption },
};
- auto modifiers = 0;
+ skui::ModifierKey modifiers = skui::ModifierKey::kNone;
for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
if (event.xkey.state & gModifiers[i].fXMask) {
modifiers |= gModifiers[i].fSkMask;
@@ -262,7 +268,7 @@
switch (event.xbutton.button) {
case Button1:
this->onMouse(event.xbutton.x, event.xbutton.y,
- Window::kDown_InputState, get_modifiers(event));
+ skui::InputState::kDown, get_modifiers(event));
break;
case Button4:
this->onMouseWheel(1.0f, get_modifiers(event));
@@ -276,21 +282,21 @@
case ButtonRelease:
if (event.xbutton.button == Button1) {
this->onMouse(event.xbutton.x, event.xbutton.y,
- Window::kUp_InputState, get_modifiers(event));
+ skui::InputState::kUp, get_modifiers(event));
}
break;
case MotionNotify:
this->onMouse(event.xmotion.x, event.xmotion.y,
- Window::kMove_InputState, get_modifiers(event));
+ skui::InputState::kMove, get_modifiers(event));
break;
case KeyPress: {
int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0;
KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel);
- Window::Key key = get_key(keysym);
- if (key != Window::Key::kNONE) {
- if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) {
+ skui::Key key = get_key(keysym);
+ if (key != skui::Key::kNONE) {
+ if (!this->onKey(key, skui::InputState::kDown, get_modifiers(event))) {
if (keysym == XK_Escape) {
return true;
}
@@ -307,11 +313,11 @@
int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0;
KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode,
0, shiftLevel);
- Window::Key key = get_key(keysym);
- (void) this->onKey(key, Window::kUp_InputState,
+ skui::Key key = get_key(keysym);
+ (void) this->onKey(key, skui::InputState::kUp,
get_modifiers(event));
} break;
-
+
default:
// these events should be handled in the main event loop
@@ -325,7 +331,7 @@
void Window_unix::setTitle(const char* title) {
XTextProperty textproperty;
XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty);
- XSetWMName(fDisplay, fWindow, &textproperty);
+ XSetWMName(fDisplay, fWindow, &textproperty);
}
void Window_unix::show() {
@@ -333,6 +339,8 @@
}
bool Window_unix::attach(BackendType attachType) {
+ fBackend = attachType;
+
this->initWindow(fDisplay);
window_context_factory::XlibWindowInfo winInfo;
@@ -350,18 +358,25 @@
}
switch (attachType) {
+#ifdef SK_DAWN
+ case kDawn_BackendType:
+ fWindowContext =
+ window_context_factory::MakeDawnVulkanForXlib(winInfo, fRequestedDisplayParams);
+ break;
+#endif
#ifdef SK_VULKAN
case kVulkan_BackendType:
- fWindowContext = window_context_factory::NewVulkanForXlib(winInfo,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeVulkanForXlib(winInfo, fRequestedDisplayParams);
break;
#endif
case kNativeGL_BackendType:
- fWindowContext = window_context_factory::NewGLForXlib(winInfo, fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeGLForXlib(winInfo, fRequestedDisplayParams);
break;
case kRaster_BackendType:
- fWindowContext = window_context_factory::NewRasterForXlib(winInfo,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeRasterForXlib(winInfo, fRequestedDisplayParams);
break;
}
this->onBackendCreated();
@@ -380,8 +395,25 @@
event.xexpose.width = this->width();
event.xexpose.height = this->height();
event.xexpose.count = 0;
-
+
XSendEvent(fDisplay, fWindow, False, 0, &event);
}
+void Window_unix::setRequestedDisplayParams(const DisplayParams& params, bool allowReattach) {
+#if defined(SK_VULKAN)
+ // Vulkan on unix crashes if we try to reinitialize the vulkan context without remaking the
+ // window.
+ if (fBackend == kVulkan_BackendType && allowReattach) {
+ // Need to change these early, so attach() creates the window context correctly
+ fRequestedDisplayParams = params;
+
+ this->detach();
+ this->attach(fBackend);
+ return;
+ }
+#endif
+
+ INHERITED::setRequestedDisplayParams(params, allowReattach);
+}
+
} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h b/src/third_party/skia/tools/sk_app/unix/Window_unix.h
similarity index 70%
rename from src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h
rename to src/third_party/skia/tools/sk_app/unix/Window_unix.h
index 73f21af..417a79b 100644
--- a/src/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h
+++ b/src/third_party/skia/tools/sk_app/unix/Window_unix.h
@@ -8,11 +8,12 @@
#ifndef Window_unix_DEFINED
#define Window_unix_DEFINED
-#include <X11/Xlib.h>
+#include "include/private/SkChecksum.h"
+#include "src/core/SkTDynamicHash.h"
+#include "tools/sk_app/Window.h"
+
#include <GL/glx.h>
-#include "../Window.h"
-#include "SkChecksum.h"
-#include "SkTDynamicHash.h"
+#include <X11/Xlib.h>
typedef Window XWindow;
@@ -20,13 +21,14 @@
class Window_unix : public Window {
public:
- Window_unix() : Window()
- , fDisplay(nullptr)
- , fWindow(0)
- , fGC(nullptr)
- , fFBConfig(nullptr)
- , fVisualInfo(nullptr)
- , fMSAASampleCount(0) {}
+ Window_unix()
+ : Window()
+ , fDisplay(nullptr)
+ , fWindow(0)
+ , fGC(nullptr)
+ , fFBConfig(nullptr)
+ , fVisualInfo(nullptr)
+ , fMSAASampleCount(1) {}
~Window_unix() override { this->closeWindow(); }
bool initWindow(Display* display);
@@ -51,10 +53,10 @@
static SkTDynamicHash<Window_unix, XWindow> gWindowMap;
void markPendingPaint() { fPendingPaint = true; }
- void finishPaint() {
+ void finishPaint() {
if (fPendingPaint) {
- this->onPaint();
- fPendingPaint = false;
+ this->onPaint();
+ fPendingPaint = false;
}
}
@@ -65,13 +67,15 @@
fPendingHeight = height;
}
}
- void finishResize() {
+ void finishResize() {
if (fPendingResize) {
- this->onResize(fPendingWidth, fPendingHeight);
+ this->onResize(fPendingWidth, fPendingHeight);
fPendingResize = false;
- }
+ }
}
+ void setRequestedDisplayParams(const DisplayParams&, bool allowReattach) override;
+
private:
void closeWindow();
@@ -88,6 +92,10 @@
int fPendingWidth;
int fPendingHeight;
bool fPendingResize;
+
+ BackendType fBackend;
+
+ typedef Window INHERITED;
};
} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/unix/keysym2ucs.c b/src/third_party/skia/tools/sk_app/unix/keysym2ucs.c
new file mode 100644
index 0000000..00e3052
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/keysym2ucs.c
@@ -0,0 +1,848 @@
+/* $XFree86$
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
+ * therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * The keysym -> UTF-8 conversion will hopefully one day be provided
+ * by Xlib via XmbLookupString() and should ideally not have to be
+ * done in X applications. But we are not there yet.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * NOTE: The comments in the table below contain the actual character
+ * encoded in UTF-8, so for viewing and editing best use an editor in
+ * UTF-8 mode.
+ *
+ * Author: Markus G. Kuhn <http://www.cl.cam.ac.uk/~mgk25/>,
+ * University of Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ *
+ * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
+ */
+
+#include "tools/sk_app/unix/keysym2ucs.h"
+
+struct codepair {
+ unsigned short keysym;
+ unsigned short ucs;
+} keysymtab[] = {
+ { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+ { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */
+ { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+ { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+ { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+ { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+ { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+ { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+ { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+ { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+ { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+ { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+ { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */
+ { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */
+ { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */
+ { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */
+ { 0x01b7, 0x02c7 }, /* caron ˇ CARON */
+ { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */
+ { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+ { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */
+ { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+ { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */
+ { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */
+ { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+ { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+ { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+ { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+ { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+ { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+ { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+ { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+ { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+ { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+ { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+ { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+ { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+ { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+ { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+ { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+ { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+ { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+ { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */
+ { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+ { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */
+ { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */
+ { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+ { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */
+ { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */
+ { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */
+ { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */
+ { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */
+ { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+ { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */
+ { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+ { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+ { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+ { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */
+ { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+ { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+ { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+ { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+ { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+ { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+ { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+ { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */
+ { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+ { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+ { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+ { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+ { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+ { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+ { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+ { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+ { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+ { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+ { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+ { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+ { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+ { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+ { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */
+ { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+ { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+ { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+ { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+ { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+ { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+ { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+ { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+ { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+ { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */
+ { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+ { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+ { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */
+ { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */
+ { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+ { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+ { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+ { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+ { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+ { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+ { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+ { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+ { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+ { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+ { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */
+ { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */
+ { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+ { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */
+ { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+ { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */
+ { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+ { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+ { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */
+ { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */
+ { 0x047e, 0x203e }, /* overline ‾ OVERLINE */
+ { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+ { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */
+ { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */
+ { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */
+ { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */
+ { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */
+ { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */
+ { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */
+ { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */
+ { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */
+ { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */
+ { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */
+ { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */
+ { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */
+ { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */
+ { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+ { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */
+ { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */
+ { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */
+ { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */
+ { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */
+ { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */
+ { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */
+ { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */
+ { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */
+ { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */
+ { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */
+ { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */
+ { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */
+ { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */
+ { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */
+ { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */
+ { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */
+ { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */
+ { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */
+ { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */
+ { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */
+ { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */
+ { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */
+ { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */
+ { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */
+ { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */
+ { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */
+ { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */
+ { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */
+ { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */
+ { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */
+ { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */
+ { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */
+ { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */
+ { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */
+ { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */
+ { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */
+ { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */
+ { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */
+ { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */
+ { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */
+ { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */
+ { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */
+ { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */
+ { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */
+ { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+ { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+ { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */
+ { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */
+ { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */
+ { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */
+ { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+ { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+ { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+ { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+ { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+ { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */
+ { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */
+ { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+ { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */
+ { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */
+ { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */
+ { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */
+ { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */
+ { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */
+ { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */
+ { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */
+ { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */
+ { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */
+ { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */
+ { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */
+ { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */
+ { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */
+ { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */
+ { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */
+ { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */
+ { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */
+ { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */
+ { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */
+ { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */
+ { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */
+ { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */
+ { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */
+ { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */
+ { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */
+ { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+ { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */
+ { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */
+ { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */
+ { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */
+ { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */
+ { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */
+ { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */
+ { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */
+ { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */
+ { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+ { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+ { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+ { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+ { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+ { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+ { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+ { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+ { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+ { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+ { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+ { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+ { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+ { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+ { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */
+ { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+ { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+ { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+ { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+ { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+ { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+ { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+ { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+ { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+ { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+ { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+ { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+ { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+ { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+ { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+ { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */
+ { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */
+ { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+ { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */
+ { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+ { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+ { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+ { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+ { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */
+ { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+ { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+ { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */
+ { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */
+ { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */
+ { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */
+ { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+ { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+ { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */
+ { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */
+ { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */
+ { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */
+ { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+ { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+ { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+ { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+ { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+ { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+ { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */
+ { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+ { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+ { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+ { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+ { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+ { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+ { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+ { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+ { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+ { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+ { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+ { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+ { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+ { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+ { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+ { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+ { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+ { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+ { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+ { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+ { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+ { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+ { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+ { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+ { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+ { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+ { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+ { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+ { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+ { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+ { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+ { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+ { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+ { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+ { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+ { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+ { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+ { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+ { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+ { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+ { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+ { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+ { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+ { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+ { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+ { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */
+ { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+ { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+ { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+ { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+ { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+ { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+ { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+ { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+ { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+ { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+ { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+ { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+ { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */
+ { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+ { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+ { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+ { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+ { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */
+ { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+ { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+ { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+ { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+ { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */
+ { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */
+ { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */
+ { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+ { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */
+ { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+ { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+ { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+ { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+ { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+ { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+ { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+ { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+ { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */
+ { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */
+ { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */
+ { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */
+ { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+ { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */
+ { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */
+ { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */
+ { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */
+ { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */
+ { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */
+ { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */
+ { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */
+ { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */
+ { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */
+ { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */
+ { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */
+ { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */
+ { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+ { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */
+ { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+ { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */
+ { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */
+ { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */
+ { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */
+ { 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */
+ { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+ { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */
+ { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */
+ { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */
+ { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+ { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */
+ { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */
+ { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */
+ { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */
+ { 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */
+ { 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */
+ { 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */
+ { 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */
+ { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */
+ { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */
+/* 0x08b1 topleftsummation ? ??? */
+/* 0x08b2 botleftsummation ? ??? */
+/* 0x08b3 topvertsummationconnector ? ??? */
+/* 0x08b4 botvertsummationconnector ? ??? */
+/* 0x08b5 toprightsummation ? ??? */
+/* 0x08b6 botrightsummation ? ??? */
+/* 0x08b7 rightmiddlesummation ? ??? */
+ { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */
+ { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */
+ { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+ { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */
+ { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */
+ { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */
+ { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */
+ { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */
+ { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */
+ { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */
+ { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+ { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */
+ { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */
+ { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */
+ { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */
+ { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */
+ { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */
+ { 0x08dd, 0x222a }, /* union ∪ UNION */
+ { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */
+ { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */
+ { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */
+ { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */
+ { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */
+ { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */
+ { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */
+ { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */
+/* 0x09df blank ? ??? */
+ { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */
+ { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */
+ { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+ { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */
+ { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */
+ { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */
+ { 0x09e8, 0x2424 }, /* nl  SYMBOL FOR NEWLINE */
+ { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */
+ { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+ { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+ { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+ { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+ { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+ { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */
+ { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */
+ { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+ { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */
+ { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */
+ { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+ { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+ { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+ { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+ { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+ { 0x0aa1, 0x2003 }, /* emspace EM SPACE */
+ { 0x0aa2, 0x2002 }, /* enspace EN SPACE */
+ { 0x0aa3, 0x2004 }, /* em3space THREE-PER-EM SPACE */
+ { 0x0aa4, 0x2005 }, /* em4space FOUR-PER-EM SPACE */
+ { 0x0aa5, 0x2007 }, /* digitspace FIGURE SPACE */
+ { 0x0aa6, 0x2008 }, /* punctspace PUNCTUATION SPACE */
+ { 0x0aa7, 0x2009 }, /* thinspace THIN SPACE */
+ { 0x0aa8, 0x200a }, /* hairspace HAIR SPACE */
+ { 0x0aa9, 0x2014 }, /* emdash — EM DASH */
+ { 0x0aaa, 0x2013 }, /* endash – EN DASH */
+/* 0x0aac signifblank ? ??? */
+ { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
+ { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
+ { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */
+ { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+ { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+ { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+ { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+ { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+ { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+ { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+ { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */
+ { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */
+ { 0x0abc, 0x2329 }, /* leftanglebracket ⟨ LEFT-POINTING ANGLE BRACKET */
+/* 0x0abd decimalpoint ? ??? */
+ { 0x0abe, 0x232a }, /* rightanglebracket ⟩ RIGHT-POINTING ANGLE BRACKET */
+/* 0x0abf marker ? ??? */
+ { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+ { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+ { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+ { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+ { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */
+ { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */
+/* 0x0acb trademarkincircle ? ??? */
+ { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+ { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+ { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */
+ { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */
+ { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+ { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+ { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+ { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+ { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */
+ { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */
+ { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
+ { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */
+/* 0x0ada hexagram ? ??? */
+ { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */
+ { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+ { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+ { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */
+ { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */
+ { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */
+ { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */
+ { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */
+ { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */
+ { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+ { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */
+ { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */
+ { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */
+ { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+ { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+ { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */
+ { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */
+ { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */
+ { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */
+ { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */
+ { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */
+ { 0x0af1, 0x2020 }, /* dagger † DAGGER */
+ { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */
+ { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */
+ { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */
+ { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */
+ { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */
+ { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */
+ { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */
+ { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */
+ { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */
+ { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+ { 0x0afc, 0x2038 }, /* caret ‸ CARET */
+ { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+ { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+/* 0x0aff cursor ? ??? */
+ { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */
+ { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */
+ { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */
+ { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */
+ { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */
+ { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */
+ { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */
+ { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */
+ { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */
+ { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */
+ { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */
+ { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */
+ { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */
+ { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */
+ { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */
+ { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */
+ { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */
+ { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */
+ { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */
+ { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */
+ { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */
+ { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */
+ { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */
+ { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */
+ { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */
+ { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */
+ { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */
+ { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */
+ { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */
+ { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */
+ { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+ { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */
+ { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */
+ { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+ { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */
+ { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+ { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */
+ { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */
+ { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */
+ { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */
+ { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */
+ { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+ { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */
+ { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */
+ { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */
+ { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */
+ { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */
+ { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */
+ { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */
+ { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+ { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+ { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+ { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+ { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */
+ { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */
+ { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */
+ { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */
+ { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */
+ { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+ { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */
+ { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */
+ { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */
+ { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */
+ { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+ { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+ { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */
+ { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */
+ { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */
+ { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */
+ { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */
+ { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */
+ { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */
+ { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+ { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */
+ { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+ { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */
+ { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */
+ { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */
+ { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+ { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */
+ { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */
+ { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */
+ { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */
+ { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */
+ { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */
+ { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */
+ { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */
+ { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */
+ { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */
+ { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */
+ { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */
+ { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */
+ { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+ { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+ { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */
+ { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+ { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */
+ { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */
+ { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */
+ { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */
+ { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */
+ { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */
+ { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */
+ { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */
+ { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+/* 0x0dde Thai_maihanakat_maitho ? ??? */
+ { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+ { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */
+ { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */
+ { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */
+ { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+ { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+ { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+ { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+ { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+ { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */
+ { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */
+ { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */
+ { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+ { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+ { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+ { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */
+ { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */
+ { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */
+ { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */
+ { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */
+ { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */
+ { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */
+ { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */
+ { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */
+ { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */
+ { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+ { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+ { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+ { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+ { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+ { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+ { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+ { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+ { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+ { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+ { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+ { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+ { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+ { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+ { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+ { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+ { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+ { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+ { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+ { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+ { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */
+ { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+ { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+ { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+ { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+ { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+ { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+ { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+ { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+ { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+ { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */
+ { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */
+ { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */
+ { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */
+ { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */
+ { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */
+ { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */
+ { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */
+ { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */
+ { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */
+ { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */
+ { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */
+ { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */
+ { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */
+ { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */
+ { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */
+ { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */
+ { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */
+ { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */
+ { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */
+ { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */
+ { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+ { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+ { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+ { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+ { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+ { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+ { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+ { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+ { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+ { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+ { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+ { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+ { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+ { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+ { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+ { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+ { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+ { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+ { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+ { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+ { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+ { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+ { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+ { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+ { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+ { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+ { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+ { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+ { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+ { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+ { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+ { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
+ { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+ { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+ { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+ { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+ { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+ { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
+ { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+ { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */
+ { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */
+ { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */
+ { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */
+ { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+ { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */
+};
+
+long keysym2ucs(KeySym keysym)
+{
+ int min = 0;
+ int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+ int mid;
+
+ /* first check for Latin-1 characters (1:1 mapping) */
+ if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+ (keysym >= 0x00a0 && keysym <= 0x00ff))
+ return keysym;
+
+ /* also check for directly encoded 24-bit UCS characters */
+ if ((keysym & 0xff000000) == 0x01000000)
+ return keysym & 0x00ffffff;
+
+ /* binary search in table */
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (keysymtab[mid].keysym < keysym)
+ min = mid + 1;
+ else if (keysymtab[mid].keysym > keysym)
+ max = mid - 1;
+ else {
+ /* found it */
+ return keysymtab[mid].ucs;
+ }
+ }
+
+ /* no matching Unicode value found */
+ return -1;
+}
diff --git a/src/third_party/skia/tools/sk_app/unix/keysym2ucs.h b/src/third_party/skia/tools/sk_app/unix/keysym2ucs.h
new file mode 100644
index 0000000..0287f02
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/keysym2ucs.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*
+ * This module converts keysym values into the corresponding ISO 10646-1
+ * (UCS, Unicode) values.
+ */
+
+#include <X11/X.h>
+
+long keysym2ucs(KeySym keysym);
diff --git a/src/third_party/skia/tools/sk_app/unix/main_unix.cpp b/src/third_party/skia/tools/sk_app/unix/main_unix.cpp
new file mode 100644
index 0000000..ecdb021
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/unix/main_unix.cpp
@@ -0,0 +1,92 @@
+/*
+
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "include/core/SkTypes.h"
+#include "include/private/SkTHash.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/unix/Window_unix.h"
+#include "tools/timer/Timer.h"
+
+int main(int argc, char**argv) {
+ XInitThreads();
+ Display* display = XOpenDisplay(nullptr);
+
+ sk_app::Application* app = sk_app::Application::Create(argc, argv, (void*)display);
+
+ // Get the file descriptor for the X display
+ const int x11_fd = ConnectionNumber(display);
+
+ bool done = false;
+ while (!done) {
+ if (0 == XPending(display)) {
+ // Only call select() when we have no events.
+
+ // Create a file description set containing x11_fd
+ fd_set in_fds;
+ FD_ZERO(&in_fds);
+ FD_SET(x11_fd, &in_fds);
+
+ // Set a sleep timer
+ struct timeval tv;
+ tv.tv_usec = 10;
+ tv.tv_sec = 0;
+
+ // Wait for an event on the file descriptor or for timer expiration
+ (void)select(1, &in_fds, nullptr, nullptr, &tv);
+ }
+
+ // Handle all pending XEvents (if any) and flush the input
+ // Only handle a finite number of events before finishing resize and paint..
+ if (int count = XPending(display)) {
+ // collapse any Expose and Resize events.
+ SkTHashSet<sk_app::Window_unix*> pendingWindows;
+ while (count-- && !done) {
+ XEvent event;
+ XNextEvent(display, &event);
+
+ sk_app::Window_unix* win = sk_app::Window_unix::gWindowMap.find(event.xany.window);
+ if (!win) {
+ continue;
+ }
+
+ // paint and resize events get collapsed
+ switch (event.type) {
+ case Expose:
+ win->markPendingPaint();
+ pendingWindows.add(win);
+ break;
+ case ConfigureNotify:
+ win->markPendingResize(event.xconfigurerequest.width,
+ event.xconfigurerequest.height);
+ pendingWindows.add(win);
+ break;
+ default:
+ if (win->handleEvent(event)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ pendingWindows.foreach([](sk_app::Window_unix* win) {
+ win->finishResize();
+ win->finishPaint();
+ });
+ } else {
+ // We are only really "idle" when the timer went off with zero events.
+ app->onIdle();
+ }
+
+ XFlush(display);
+ }
+
+ delete app;
+
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp b/src/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
new file mode 100644
index 0000000..5fcccb2
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
@@ -0,0 +1,179 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#define EGL_EGL_PROTOTYPES 1
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "include/gpu/gl/GrGLAssembleInterface.h"
+#include "src/gpu/gl/GrGLDefines.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+
+using sk_app::GLWindowContext;
+using sk_app::DisplayParams;
+
+namespace {
+
+EGLDisplay get_angle_egl_display(HDC hdc) {
+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
+ eglGetPlatformDisplayEXT =
+ (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
+
+ // We expect ANGLE to support this extension
+ if (!eglGetPlatformDisplayEXT) {
+ return EGL_NO_DISPLAY;
+ }
+
+ // We currently only support D3D11 ANGLE.
+ static constexpr EGLint kType = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
+ static constexpr EGLint attribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, kType, EGL_NONE};
+ return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, hdc, attribs);
+}
+
+class ANGLEGLWindowContext_win : public GLWindowContext {
+public:
+ ANGLEGLWindowContext_win(HWND, const DisplayParams&);
+ ~ANGLEGLWindowContext_win() override;
+
+protected:
+ void onSwapBuffers() override;
+
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+ void onDestroyContext() override;
+
+private:
+ HWND fHWND;
+ EGLDisplay fDisplay = EGL_NO_DISPLAY;
+ EGLContext fEGLContext = EGL_NO_CONTEXT;
+ EGLSurface fEGLSurface = EGL_NO_SURFACE;
+
+ typedef GLWindowContext INHERITED;
+};
+
+ANGLEGLWindowContext_win::ANGLEGLWindowContext_win(HWND wnd, const DisplayParams& params)
+ : INHERITED(params), fHWND(wnd) {
+ this->initializeContext();
+}
+
+ANGLEGLWindowContext_win::~ANGLEGLWindowContext_win() { this->destroyContext(); }
+
+sk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
+ HDC dc = GetDC(fHWND);
+ fDisplay = get_angle_egl_display(dc);
+ if (EGL_NO_DISPLAY == fDisplay) {
+ return nullptr;
+ }
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
+ SkDebugf("Could not initialize display!\n");
+ return nullptr;
+ }
+ EGLint numConfigs;
+ fSampleCount = this->getDisplayParams().fMSAASampleCount;
+ const int sampleBuffers = fSampleCount > 1 ? 1 : 0;
+ const int eglSampleCnt = fSampleCount > 1 ? fSampleCount : 0;
+ const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
+ // We currently only support ES3.
+ EGL_OPENGL_ES3_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_SAMPLE_BUFFERS,
+ sampleBuffers,
+ EGL_SAMPLES,
+ eglSampleCnt,
+ EGL_NONE};
+
+ EGLConfig surfaceConfig;
+ if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
+ SkDebugf("Could not create choose config!\n");
+ return nullptr;
+ }
+ // We currently only support ES3.
+ const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+ fEGLContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
+ if (EGL_NO_CONTEXT == fEGLContext) {
+ SkDebugf("Could not create context!\n");
+ return nullptr;
+ }
+ fEGLSurface = eglCreateWindowSurface(fDisplay, surfaceConfig, fHWND, nullptr);
+ if (EGL_NO_SURFACE == fEGLSurface) {
+ SkDebugf("Could not create surface!\n");
+ return nullptr;
+ }
+ if (!eglMakeCurrent(fDisplay, fEGLSurface, fEGLSurface, fEGLContext)) {
+ SkDebugf("Could not make contxt current!\n");
+ return nullptr;
+ }
+
+ sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface(
+ nullptr,
+ [](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
+ if (interface) {
+ interface->fFunctions.fClearStencil(0);
+ interface->fFunctions.fClearColor(0, 0, 0, 0);
+ interface->fFunctions.fStencilMask(0xffffffff);
+ interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT);
+
+ // use DescribePixelFormat to get the stencil depth.
+ int pixelFormat = GetPixelFormat(dc);
+ PIXELFORMATDESCRIPTOR pfd;
+ DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
+ fStencilBits = pfd.cStencilBits;
+
+ RECT rect;
+ GetClientRect(fHWND, &rect);
+ fWidth = rect.right - rect.left;
+ fHeight = rect.bottom - rect.top;
+ interface->fFunctions.fViewport(0, 0, fWidth, fHeight);
+ }
+ return interface;
+}
+
+void ANGLEGLWindowContext_win::onDestroyContext() {
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (EGL_NO_CONTEXT != fEGLContext) {
+ eglDestroyContext(fDisplay, fEGLContext);
+ }
+ if (EGL_NO_SURFACE != fEGLSurface) {
+ eglDestroySurface(fDisplay, fEGLSurface);
+ }
+ if (EGL_NO_DISPLAY != fDisplay) {
+ eglTerminate(fDisplay);
+ }
+}
+
+void ANGLEGLWindowContext_win::onSwapBuffers() {
+ if (!eglSwapBuffers(fDisplay, fEGLSurface)) {
+ SkDebugf("Could not complete eglSwapBuffers.\n");
+ }
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeANGLEForWin(HWND wnd, const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new ANGLEGLWindowContext_win(wnd, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+} // namespace sk_app
diff --git a/src/third_party/skia/tools/sk_app/win/DawnD3D12WindowContext_win.cpp b/src/third_party/skia/tools/sk_app/win/DawnD3D12WindowContext_win.cpp
new file mode 100644
index 0000000..b5e8599
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/win/DawnD3D12WindowContext_win.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/sk_app/DawnWindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+#include "dawn/dawncpp.h"
+#include "dawn/dawn_wsi.h"
+#include "dawn_native/DawnNative.h"
+#include "dawn_native/D3D12Backend.h"
+#include "common/SwapChainUtils.h"
+
+namespace sk_app {
+
+class DawnD3D12WindowContext : public DawnWindowContext {
+public:
+ DawnD3D12WindowContext(HWND hwnd, const DisplayParams& params);
+ virtual ~DawnD3D12WindowContext();
+ dawn::Device onInitializeContext() override;
+ void onDestroyContext() override;
+ DawnSwapChainImplementation createSwapChainImplementation(
+ int width, int height, const DisplayParams& params) override;
+ void onSwapBuffers() override;
+private:
+ HWND fWindow;
+};
+
+// NOTE: this texture format must match the one in D3D12's swap chain impl
+DawnD3D12WindowContext::DawnD3D12WindowContext(HWND hwnd, const DisplayParams& params)
+ : DawnWindowContext(params, dawn::TextureFormat::RGBA8Unorm)
+ , fWindow(hwnd) {
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+ this->initializeContext(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+DawnD3D12WindowContext::~DawnD3D12WindowContext() {
+ this->destroyContext();
+}
+
+DawnSwapChainImplementation DawnD3D12WindowContext::createSwapChainImplementation(
+ int width, int height, const DisplayParams& params) {
+ return dawn_native::d3d12::CreateNativeSwapChainImpl(fDevice.Get(), fWindow);
+}
+
+dawn::Device DawnD3D12WindowContext::onInitializeContext() {
+ return this->createDevice(dawn_native::BackendType::D3D12);
+}
+
+void DawnD3D12WindowContext::onDestroyContext() {
+}
+
+void DawnD3D12WindowContext::onSwapBuffers() {
+}
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeDawnD3D12ForWin(HWND hwnd,
+ const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new DawnD3D12WindowContext(hwnd, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+}
+
+} //namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp b/src/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
similarity index 72%
rename from src/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp
rename to src/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
index 20c3d91..32c47b4 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp
+++ b/src/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
@@ -6,17 +6,29 @@
* found in the LICENSE file.
*/
-#include "WindowContextFactory_win.h"
+#include "include/gpu/gl/GrGLInterface.h"
+#include "src/utils/win/SkWGL.h"
+#include "tools/sk_app/GLWindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+
+#include <Windows.h>
#include <GL/gl.h>
- // windows stuff
-#include "win/SkWGL.h"
-
-#include "../GLWindowContext.h"
-
using sk_app::GLWindowContext;
using sk_app::DisplayParams;
+#if defined(_M_ARM64)
+
+namespace sk_app {
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeGLForWin(HWND, const DisplayParams&) { return nullptr; }
+
+} // namespace window_context_factory
+} // namespace sk_app
+
+#else
+
namespace {
class GLWindowContext_win : public GLWindowContext {
@@ -27,7 +39,7 @@
protected:
void onSwapBuffers() override;
- void onInitializeContext() override;
+ sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@@ -51,26 +63,31 @@
this->destroyContext();
}
-void GLWindowContext_win::onInitializeContext() {
+sk_sp<const GrGLInterface> GLWindowContext_win::onInitializeContext() {
HDC dc = GetDC(fHWND);
fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
kGLPreferCompatibilityProfile_SkWGLContextRequest);
if (NULL == fHGLRC) {
- return;
+ return nullptr;
+ }
+
+ SkWGLExtensions extensions;
+ if (extensions.hasExtension(dc, "WGL_EXT_swap_control")) {
+ extensions.swapInterval(fDisplayParams.fDisableVsync ? 0 : 1);
}
// Look to see if RenderDoc is attached. If so, re-create the context with a core profile
if (wglMakeCurrent(dc, fHGLRC)) {
- const GrGLInterface* glInterface = GrGLCreateNativeInterface();
- bool renderDocAttached = glInterface->hasExtension("GL_EXT_debug_tool");
- SkSafeUnref(glInterface);
+ auto interface = GrGLMakeNativeInterface();
+ bool renderDocAttached = interface->hasExtension("GL_EXT_debug_tool");
+ interface.reset(nullptr);
if (renderDocAttached) {
wglDeleteContext(fHGLRC);
fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
kGLPreferCoreProfile_SkWGLContextRequest);
if (NULL == fHGLRC) {
- return;
+ return nullptr;
}
}
}
@@ -88,7 +105,6 @@
fStencilBits = pfd.cStencilBits;
// Get sample count if the MSAA WGL extension is present
- SkWGLExtensions extensions;
if (extensions.hasExtension(dc, "WGL_ARB_multisample")) {
static const int kSampleCountAttr = SK_WGL_SAMPLES;
extensions.getPixelFormatAttribiv(dc,
@@ -97,8 +113,9 @@
1,
&kSampleCountAttr,
&fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
} else {
- fSampleCount = 0;
+ fSampleCount = 1;
}
RECT rect;
@@ -107,6 +124,7 @@
fHeight = rect.bottom - rect.top;
glViewport(0, 0, fWidth, fHeight);
}
+ return GrGLMakeNativeInterface();
}
@@ -128,10 +146,9 @@
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewGLForWin(HWND wnd, const DisplayParams& params) {
- GLWindowContext_win* ctx = new GLWindowContext_win(wnd, params);
+std::unique_ptr<WindowContext> MakeGLForWin(HWND wnd, const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new GLWindowContext_win(wnd, params));
if (!ctx->isValid()) {
- delete ctx;
return nullptr;
}
return ctx;
@@ -139,3 +156,5 @@
} // namespace window_context_factory
} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp b/src/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp
similarity index 87%
rename from src/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp
rename to src/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp
index 85bb65e..9548220 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp
+++ b/src/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp
@@ -5,10 +5,10 @@
* found in the LICENSE file.
*/
-#include "../RasterWindowContext.h"
-#include "SkAutoMalloc.h"
-#include "SkSurface.h"
-#include "WindowContextFactory_win.h"
+#include "include/core/SkSurface.h"
+#include "src/core/SkAutoMalloc.h"
+#include "tools/sk_app/RasterWindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
#include <Windows.h>
@@ -40,14 +40,14 @@
: INHERITED(params)
, fWnd(wnd) {
RECT rect;
- GetWindowRect(wnd, &rect);
+ GetClientRect(wnd, &rect);
this->resize(rect.right - rect.left, rect.bottom - rect.top);
}
void RasterWindowContext_win::setDisplayParams(const DisplayParams& params) {
fDisplayParams = params;
RECT rect;
- GetWindowRect(fWnd, &rect);
+ GetClientRect(fWnd, &rect);
this->resize(rect.right - rect.left, rect.bottom - rect.top);
}
@@ -87,10 +87,9 @@
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewRasterForWin(HWND wnd, const DisplayParams& params) {
- WindowContext* ctx = new RasterWindowContext_win(wnd, params);
+std::unique_ptr<WindowContext> MakeRasterForWin(HWND wnd, const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new RasterWindowContext_win(wnd, params));
if (!ctx->isValid()) {
- delete ctx;
ctx = nullptr;
}
return ctx;
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp b/src/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp
similarity index 61%
rename from src/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
rename to src/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp
index 521a1ee..909c961 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
+++ b/src/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp
@@ -6,24 +6,35 @@
* found in the LICENSE file.
*/
+#include "include/gpu/vk/GrVkVulkan.h"
+
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+
+#include "tools/sk_app/VulkanWindowContext.h"
+#include "tools/sk_app/win/Window_win.h"
+
+#include "src/gpu/vk/GrVkInterface.h"
+#include "src/gpu/vk/GrVkUtil.h"
+
+#include "tools/gpu/vk/VkTestUtils.h"
+
#include <Windows.h>
-#include "WindowContextFactory_win.h"
-
-#include "../VulkanWindowContext.h"
-#include "Window_win.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
namespace sk_app {
namespace window_context_factory {
-WindowContext* NewVulkanForWin(HWND hwnd, const DisplayParams& params) {
- auto createVkSurface = [hwnd] (VkInstance instance) -> VkSurfaceKHR {
+std::unique_ptr<WindowContext> MakeVulkanForWin(HWND hwnd, const DisplayParams& params) {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [hwnd, instProc] (VkInstance instance) -> VkSurfaceKHR {
static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
if (!createWin32SurfaceKHR) {
createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
- vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+ instProc(instance, "vkCreateWin32SurfaceKHR");
}
HINSTANCE hinstance = GetModuleHandle(0);
VkSurfaceKHR surface;
@@ -44,24 +55,23 @@
return surface;
};
- auto canPresent = [hwnd] (VkInstance instance, VkPhysicalDevice physDev,
- uint32_t queueFamilyIndex) {
+ auto canPresent = [instProc] (VkInstance instance, VkPhysicalDevice physDev,
+ uint32_t queueFamilyIndex) {
static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
if (!getPhysicalDeviceWin32PresentationSupportKHR) {
getPhysicalDeviceWin32PresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
- vkGetInstanceProcAddr(instance,
- "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+ instProc(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
}
VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
return (VK_FALSE != check);
};
- WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
+ std::unique_ptr<WindowContext> ctx(
+ new VulkanWindowContext(params, createVkSurface, canPresent, instProc, devProc));
if (!ctx->isValid()) {
- delete ctx;
return nullptr;
}
return ctx;
diff --git a/src/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h b/src/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
new file mode 100644
index 0000000..33dd6d4
--- /dev/null
+++ b/src/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_win_DEFINED
+#define WindowContextFactory_win_DEFINED
+
+#include <Windows.h>
+
+#include <memory>
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeVulkanForWin(HWND, const DisplayParams&);
+
+std::unique_ptr<WindowContext> MakeGLForWin(HWND, const DisplayParams&);
+
+std::unique_ptr<WindowContext> MakeANGLEForWin(HWND, const DisplayParams&);
+
+#ifdef SK_DAWN
+std::unique_ptr<WindowContext> MakeDawnD3D12ForWin(HWND, const DisplayParams&);
+#endif
+
+std::unique_ptr<WindowContext> MakeRasterForWin(HWND, const DisplayParams&);
+
+} // namespace window_context_factory
+
+} // namespace sk_app
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp b/src/third_party/skia/tools/sk_app/win/Window_win.cpp
similarity index 70%
rename from src/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp
rename to src/third_party/skia/tools/sk_app/win/Window_win.cpp
index 0fb6513..43ed343 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp
+++ b/src/third_party/skia/tools/sk_app/win/Window_win.cpp
@@ -5,17 +5,21 @@
* found in the LICENSE file.
*/
-#include "Window_win.h"
+#include "include/gpu/vk/GrVkVulkan.h"
+
+#include "tools/sk_app/win/Window_win.h"
#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
-#include "SkUtils.h"
-#include "../WindowContext.h"
-#include "WindowContextFactory_win.h"
+#include "src/core/SkUtils.h"
+#include "tools/sk_app/WindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+#include "tools/skui/ModifierKey.h"
+
#ifdef SK_VULKAN
-#include "../VulkanWindowContext.h"
+#include "tools/sk_app/VulkanWindowContext.h"
#endif
namespace sk_app {
@@ -72,11 +76,11 @@
wcex.cbWndExtra = 0;
wcex.hInstance = fHInstance;
wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);;
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = gSZWindowClass;
- wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);;
+ wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
if (!RegisterClassEx(&wcex)) {
return false;
@@ -101,7 +105,7 @@
// Set the position of the window to the top left corner.
posX = posY = 0;
- }
+ }
*/
// gIsFullscreen = fullscreen;
@@ -119,71 +123,71 @@
return true;
}
-static Window::Key get_key(WPARAM vk) {
+static skui::Key get_key(WPARAM vk) {
static const struct {
WPARAM fVK;
- Window::Key fKey;
+ skui::Key fKey;
} gPair[] = {
- { VK_BACK, Window::Key::kBack },
- { VK_CLEAR, Window::Key::kBack },
- { VK_RETURN, Window::Key::kOK },
- { VK_UP, Window::Key::kUp },
- { VK_DOWN, Window::Key::kDown },
- { VK_LEFT, Window::Key::kLeft },
- { VK_RIGHT, Window::Key::kRight },
- { VK_TAB, Window::Key::kTab },
- { VK_PRIOR, Window::Key::kPageUp },
- { VK_NEXT, Window::Key::kPageDown },
- { VK_HOME, Window::Key::kHome },
- { VK_END, Window::Key::kEnd },
- { VK_DELETE, Window::Key::kDelete },
- { VK_ESCAPE, Window::Key::kEscape },
- { VK_SHIFT, Window::Key::kShift },
- { VK_CONTROL, Window::Key::kCtrl },
- { VK_MENU, Window::Key::kOption },
- { 'A', Window::Key::kA },
- { 'C', Window::Key::kC },
- { 'V', Window::Key::kV },
- { 'X', Window::Key::kX },
- { 'Y', Window::Key::kY },
- { 'Z', Window::Key::kZ },
+ { VK_BACK, skui::Key::kBack },
+ { VK_CLEAR, skui::Key::kBack },
+ { VK_RETURN, skui::Key::kOK },
+ { VK_UP, skui::Key::kUp },
+ { VK_DOWN, skui::Key::kDown },
+ { VK_LEFT, skui::Key::kLeft },
+ { VK_RIGHT, skui::Key::kRight },
+ { VK_TAB, skui::Key::kTab },
+ { VK_PRIOR, skui::Key::kPageUp },
+ { VK_NEXT, skui::Key::kPageDown },
+ { VK_HOME, skui::Key::kHome },
+ { VK_END, skui::Key::kEnd },
+ { VK_DELETE, skui::Key::kDelete },
+ { VK_ESCAPE, skui::Key::kEscape },
+ { VK_SHIFT, skui::Key::kShift },
+ { VK_CONTROL, skui::Key::kCtrl },
+ { VK_MENU, skui::Key::kOption },
+ { 'A', skui::Key::kA },
+ { 'C', skui::Key::kC },
+ { 'V', skui::Key::kV },
+ { 'X', skui::Key::kX },
+ { 'Y', skui::Key::kY },
+ { 'Z', skui::Key::kZ },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
if (gPair[i].fVK == vk) {
return gPair[i].fKey;
}
}
- return Window::Key::kNONE;
+ return skui::Key::kNONE;
}
-static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
- uint32_t modifiers = 0;
+static skui::ModifierKey get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
+ skui::ModifierKey modifiers = skui::ModifierKey::kNone;
switch (message) {
case WM_UNICHAR:
case WM_CHAR:
if (0 == (lParam & (1 << 30))) {
- modifiers |= Window::kFirstPress_ModifierKey;
+ modifiers |= skui::ModifierKey::kFirstPress;
}
if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
+ modifiers |= skui::ModifierKey::kOption;
}
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (0 == (lParam & (1 << 30))) {
- modifiers |= Window::kFirstPress_ModifierKey;
+ modifiers |= skui::ModifierKey::kFirstPress;
}
if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
+ modifiers |= skui::ModifierKey::kOption;
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
+ modifiers |= skui::ModifierKey::kOption;
}
break;
@@ -192,10 +196,10 @@
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
if (wParam & MK_CONTROL) {
- modifiers |= Window::kControl_ModifierKey;
+ modifiers |= skui::ModifierKey::kControl;
}
if (wParam & MK_SHIFT) {
- modifiers |= Window::kShift_ModifierKey;
+ modifiers |= skui::ModifierKey::kShift;
}
break;
}
@@ -235,25 +239,25 @@
break;
case WM_UNICHAR:
- eventHandled = window->onChar((SkUnichar)wParam,
+ eventHandled = window->onChar((SkUnichar)wParam,
get_modifiers(message, wParam, lParam));
break;
case WM_CHAR: {
const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
- eventHandled = window->onChar(SkUTF16_NextUnichar(&c),
+ eventHandled = window->onChar(SkUTF16_NextUnichar(&c),
get_modifiers(message, wParam, lParam));
} break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
- eventHandled = window->onKey(get_key(wParam), Window::kDown_InputState,
+ eventHandled = window->onKey(get_key(wParam), skui::InputState::kDown,
get_modifiers(message, wParam, lParam));
break;
case WM_KEYUP:
case WM_SYSKEYUP:
- eventHandled = window->onKey(get_key(wParam), Window::kUp_InputState,
+ eventHandled = window->onKey(get_key(wParam), skui::InputState::kUp,
get_modifiers(message, wParam, lParam));
break;
@@ -270,10 +274,10 @@
// yPos -= rc.top;
//}
- Window::InputState istate = ((wParam & MK_LBUTTON) != 0) ? Window::kDown_InputState
- : Window::kUp_InputState;
+ skui::InputState istate = ((wParam & MK_LBUTTON) != 0) ? skui::InputState::kDown
+ : skui::InputState::kUp;
- eventHandled = window->onMouse(xPos, yPos, istate,
+ eventHandled = window->onMouse(xPos, yPos, istate,
get_modifiers(message, wParam, lParam));
} break;
@@ -289,7 +293,7 @@
// yPos -= rc.top;
//}
- eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
+ eventHandled = window->onMouse(xPos, yPos, skui::InputState::kMove,
get_modifiers(message, wParam, lParam));
} break;
@@ -303,24 +307,24 @@
std::unique_ptr<TOUCHINPUT[]> inputs(new TOUCHINPUT[numInputs]);
if (GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, inputs.get(),
sizeof(TOUCHINPUT))) {
- RECT rect;
- GetClientRect(hWnd, &rect);
+ POINT topLeft = {0, 0};
+ ClientToScreen(hWnd, &topLeft);
for (uint16_t i = 0; i < numInputs; ++i) {
TOUCHINPUT ti = inputs[i];
- Window::InputState state;
+ skui::InputState state;
if (ti.dwFlags & TOUCHEVENTF_DOWN) {
- state = Window::kDown_InputState;
+ state = skui::InputState::kDown;
} else if (ti.dwFlags & TOUCHEVENTF_MOVE) {
- state = Window::kMove_InputState;
+ state = skui::InputState::kMove;
} else if (ti.dwFlags & TOUCHEVENTF_UP) {
- state = Window::kUp_InputState;
+ state = skui::InputState::kUp;
} else {
continue;
}
// TOUCHINPUT coordinates are in 100ths of pixels
// Adjust for that, and make them window relative
- LONG tx = (ti.x / 100) - rect.left;
- LONG ty = (ti.y / 100) - rect.top;
+ LONG tx = (ti.x / 100) - topLeft.x;
+ LONG ty = (ti.y / 100) - topLeft.y;
eventHandled = window->onTouch(ti.dwID, state, tx, ty) || eventHandled;
}
}
@@ -347,16 +351,28 @@
switch (attachType) {
case kNativeGL_BackendType:
- fWindowContext = window_context_factory::NewGLForWin(fHWnd, fRequestedDisplayParams);
+ fWindowContext = window_context_factory::MakeGLForWin(fHWnd, fRequestedDisplayParams);
break;
+#if SK_ANGLE
+ case kANGLE_BackendType:
+ fWindowContext =
+ window_context_factory::MakeANGLEForWin(fHWnd, fRequestedDisplayParams);
+ break;
+#endif
+#ifdef SK_DAWN
+ case kDawn_BackendType:
+ fWindowContext =
+ window_context_factory::MakeDawnD3D12ForWin(fHWnd, fRequestedDisplayParams);
+ break;
+#endif
case kRaster_BackendType:
- fWindowContext = window_context_factory::NewRasterForWin(fHWnd,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeRasterForWin(fHWnd, fRequestedDisplayParams);
break;
#ifdef SK_VULKAN
case kVulkan_BackendType:
- fWindowContext = window_context_factory::NewVulkanForWin(fHWnd,
- fRequestedDisplayParams);
+ fWindowContext =
+ window_context_factory::MakeVulkanForWin(fHWnd, fRequestedDisplayParams);
break;
#endif
}
@@ -376,7 +392,7 @@
// Need to change these early, so attach() creates the window context correctly
fRequestedDisplayParams = params;
- delete fWindowContext;
+ fWindowContext = nullptr;
this->closeWindow();
this->init(fHInstance);
this->attach(fBackend);
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/Window_win.h b/src/third_party/skia/tools/sk_app/win/Window_win.h
similarity index 95%
rename from src/third_party/skia/tools/viewer/sk_app/win/Window_win.h
rename to src/third_party/skia/tools/sk_app/win/Window_win.h
index 139ab87..9e108e0 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/Window_win.h
+++ b/src/third_party/skia/tools/sk_app/win/Window_win.h
@@ -8,8 +8,9 @@
#ifndef Window_win_DEFINED
#define Window_win_DEFINED
+#include "tools/sk_app/Window.h"
+
#include <windows.h>
-#include "../Window.h"
namespace sk_app {
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/main_win.cpp b/src/third_party/skia/tools/sk_app/win/main_win.cpp
similarity index 77%
rename from src/third_party/skia/tools/viewer/sk_app/win/main_win.cpp
rename to src/third_party/skia/tools/sk_app/win/main_win.cpp
index 4800258..5a7fdc1 100644
--- a/src/third_party/skia/tools/viewer/sk_app/win/main_win.cpp
+++ b/src/third_party/skia/tools/sk_app/win/main_win.cpp
@@ -8,10 +8,10 @@
#include <windows.h>
#include <tchar.h>
-#include "SkTypes.h"
-#include "Timer.h"
-#include "Window_win.h"
-#include "../Application.h"
+#include "include/core/SkTypes.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/win/Window_win.h"
+#include "tools/timer/Timer.h"
using sk_app::Application;
@@ -62,15 +62,28 @@
Application* app = Application::Create(argc, argv, (void*)hInstance);
- MSG msg = { 0 };
+ MSG msg;
+ memset(&msg, 0, sizeof(msg));
+
+ bool idled = false;
// Main message loop
while (WM_QUIT != msg.message) {
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
+
+ if (WM_PAINT == msg.message) {
+ // Ensure that call onIdle at least once per WM_PAINT, or mouse events can
+ // overwhelm the message processing loop, and prevent animation from running.
+ if (!idled) {
+ app->onIdle();
+ }
+ idled = false;
+ }
DispatchMessage(&msg);
} else {
app->onIdle();
+ idled = true;
}
}
diff --git a/src/third_party/skia/tools/sk_tool_utils.cpp b/src/third_party/skia/tools/sk_tool_utils.cpp
deleted file mode 100644
index 47f4aae..0000000
--- a/src/third_party/skia/tools/sk_tool_utils.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "sk_tool_utils.h"
-#include "sk_tool_utils_flags.h"
-
-#include "Resources.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkFontMgr.h"
-#include "SkFontStyle.h"
-#include "SkPixelRef.h"
-#include "SkPoint3.h"
-#include "SkShader.h"
-#include "SkTestScalerContext.h"
-#include "SkTextBlob.h"
-
-DEFINE_bool(portableFonts, false, "Use portable fonts");
-
-namespace sk_tool_utils {
-
-/* these are the default fonts chosen by Chrome for serif, sans-serif, and monospace */
-static const char* gStandardFontNames[][3] = {
- { "Times", "Helvetica", "Courier" }, // Mac
- { "Times New Roman", "Helvetica", "Courier" }, // iOS
- { "Times New Roman", "Arial", "Courier New" }, // Win
- { "Times New Roman", "Arial", "Monospace" }, // Ubuntu
- { "serif", "sans-serif", "monospace" }, // Android
- { "Tinos", "Arimo", "Cousine" } // ChromeOS
-};
-
-const char* platform_font_name(const char* name) {
- SkString platform = major_platform_os_name();
- int index;
- if (!strcmp(name, "serif")) {
- index = 0;
- } else if (!strcmp(name, "san-serif")) {
- index = 1;
- } else if (!strcmp(name, "monospace")) {
- index = 2;
- } else {
- return name;
- }
- if (platform.equals("Mac")) {
- return gStandardFontNames[0][index];
- }
- if (platform.equals("iOS")) {
- return gStandardFontNames[1][index];
- }
- if (platform.equals("Win")) {
- return gStandardFontNames[2][index];
- }
- if (platform.equals("Ubuntu") || platform.equals("Debian")) {
- return gStandardFontNames[3][index];
- }
- if (platform.equals("Android")) {
- return gStandardFontNames[4][index];
- }
- if (platform.equals("ChromeOS")) {
- return gStandardFontNames[5][index];
- }
- return name;
-}
-
-const char* platform_os_emoji() {
- const char* osName = platform_os_name();
- if (!strcmp(osName, "Android") || !strcmp(osName, "Ubuntu") || !strcmp(osName, "Debian")) {
- return "CBDT";
- }
- if (!strncmp(osName, "Mac", 3) || !strncmp(osName, "iOS", 3)) {
- return "SBIX";
- }
- if (!strncmp(osName, "Win", 3)) {
- return "COLR";
- }
- return "";
-}
-
-sk_sp<SkTypeface> emoji_typeface() {
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "CBDT")) {
- return MakeResourceAsTypeface("/fonts/Funkster.ttf");
- }
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "SBIX")) {
- return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle());
- }
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "COLR")) {
- sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- const char *colorEmojiFontName = "Segoe UI Emoji";
- sk_sp<SkTypeface> typeface(fm->matchFamilyStyle(colorEmojiFontName, SkFontStyle()));
- if (typeface) {
- return typeface;
- }
- sk_sp<SkTypeface> fallback(fm->matchFamilyStyleCharacter(
- colorEmojiFontName, SkFontStyle(), nullptr /* bcp47 */, 0 /* bcp47Count */,
- 0x1f4b0 /* character: 💰 */));
- if (fallback) {
- return fallback;
- }
- // If we don't have Segoe UI Emoji and can't find a fallback, try Segoe UI Symbol.
- // Windows 7 does not have Segoe UI Emoji; Segoe UI Symbol has the (non - color) emoji.
- return SkTypeface::MakeFromName("Segoe UI Symbol", SkFontStyle());
- }
- return nullptr;
-}
-
-const char* emoji_sample_text() {
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "CBDT")) {
- return "Hamburgefons";
- }
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "SBIX") ||
- !strcmp(sk_tool_utils::platform_os_emoji(), "COLR"))
- {
- return "\xF0\x9F\x92\xB0" "\xF0\x9F\x8F\xA1" "\xF0\x9F\x8E\x85" // 💰🏡🎅
- "\xF0\x9F\x8D\xAA" "\xF0\x9F\x8D\x95" "\xF0\x9F\x9A\x80" // 🍪🍕🚀
- "\xF0\x9F\x9A\xBB" "\xF0\x9F\x92\xA9" "\xF0\x9F\x93\xB7" // 🚻💩📷
- "\xF0\x9F\x93\xA6" // 📦
- "\xF0\x9F\x87\xBA" "\xF0\x9F\x87\xB8" "\xF0\x9F\x87\xA6"; // 🇺🇸🇦
- }
- return "";
-}
-
-const char* platform_os_name() {
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("os", FLAGS_key[index])) {
- return FLAGS_key[index + 1];
- }
- }
- // when running SampleApp or dm without a --key pair, omit the platform name
- return "";
-}
-
-// omit version number in returned value
-SkString major_platform_os_name() {
- SkString name;
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("os", FLAGS_key[index])) {
- const char* platform = FLAGS_key[index + 1];
- const char* end = platform;
- while (*end && (*end < '0' || *end > '9')) {
- ++end;
- }
- name.append(platform, end - platform);
- break;
- }
- }
- return name;
-}
-
-const char* platform_extra_config(const char* config) {
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("extra_config", FLAGS_key[index]) && !strcmp(config, FLAGS_key[index + 1])) {
- return config;
- }
- }
- return "";
-}
-
-const char* colortype_name(SkColorType ct) {
- switch (ct) {
- case kUnknown_SkColorType: return "Unknown";
- case kAlpha_8_SkColorType: return "Alpha_8";
- case kARGB_4444_SkColorType: return "ARGB_4444";
- case kRGB_565_SkColorType: return "RGB_565";
- case kRGBA_8888_SkColorType: return "RGBA_8888";
- case kBGRA_8888_SkColorType: return "BGRA_8888";
- case kRGBA_F16_SkColorType: return "RGBA_F16";
- default:
- SkASSERT(false);
- return "unexpected colortype";
- }
-}
-
-SkColor color_to_565(SkColor color) {
- SkPMColor pmColor = SkPreMultiplyColor(color);
- U16CPU color16 = SkPixel32ToPixel16(pmColor);
- return SkPixel16ToColor(color16);
-}
-
-sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style) {
- return create_font(name, style);
-}
-
-void set_portable_typeface(SkPaint* paint, const char* name, SkFontStyle style) {
- paint->setTypeface(create_font(name, style));
-}
-
-void write_pixels(SkCanvas* canvas, const SkBitmap& bitmap, int x, int y,
- SkColorType colorType, SkAlphaType alphaType) {
- SkBitmap tmp(bitmap);
- const SkImageInfo info = SkImageInfo::Make(tmp.width(), tmp.height(), colorType, alphaType);
-
- canvas->writePixels(info, tmp.getPixels(), tmp.rowBytes(), x, y);
-}
-
-sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
- SkBitmap bm;
- bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
- bm.eraseColor(c1);
- bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
- bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
- return SkShader::MakeBitmapShader(
- bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
-}
-
-SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize) {
- SkBitmap bitmap;
- bitmap.allocPixels(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
- SkCanvas canvas(bitmap);
-
- sk_tool_utils::draw_checkerboard(&canvas, c1, c2, checkSize);
- return bitmap;
-}
-
-void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
- SkPaint paint;
- paint.setShader(create_checkerboard_shader(c1, c2, size));
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawPaint(paint);
-}
-
-SkBitmap create_string_bitmap(int w, int h, SkColor c, int x, int y,
- int textSize, const char* str) {
- SkBitmap bitmap;
- bitmap.allocN32Pixels(w, h);
- SkCanvas canvas(bitmap);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- sk_tool_utils::set_portable_typeface(&paint);
- paint.setColor(c);
- paint.setTextSize(SkIntToScalar(textSize));
-
- canvas.clear(0x00000000);
- canvas.drawString(str, SkIntToScalar(x), SkIntToScalar(y), paint);
-
- // Tag data as sRGB (without doing any color space conversion). Color-space aware configs
- // will process this correctly but legacy configs will render as if this returned N32.
- SkBitmap result;
- result.setInfo(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
- result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
- return result;
-}
-
-void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
- SkScalar x, SkScalar y) {
- SkPaint paint(origPaint);
- SkTDArray<uint16_t> glyphs;
-
- size_t len = strlen(text);
- glyphs.append(paint.textToGlyphs(text, len, nullptr));
- paint.textToGlyphs(text, len, glyphs.begin());
-
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- const SkTextBlobBuilder::RunBuffer& run = builder->allocRun(paint, glyphs.count(), x, y,
- nullptr);
- memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t));
-}
-
-static inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) {
- SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f));
- unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255);
- unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255);
- unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255);
- *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
-}
-
-void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) {
- const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f),
- dst.fTop + (dst.height() / 2.0f));
- const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f);
-
- SkVector3 norm;
-
- for (int y = dst.fTop; y < dst.fBottom; ++y) {
- for (int x = dst.fLeft; x < dst.fRight; ++x) {
- norm.fX = (x + 0.5f - center.fX) / halfSize.fX;
- norm.fY = (y + 0.5f - center.fY) / halfSize.fY;
-
- SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY;
- if (tmp >= 1.0f) {
- norm.set(0.0f, 0.0f, 1.0f);
- } else {
- norm.fZ = sqrtf(1.0f - tmp);
- }
-
- norm_to_rgb(bm, x, y, norm);
- }
- }
-}
-
-void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) {
- const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f),
- dst.fTop + (dst.height() / 2.0f));
-
- SkIRect inner = dst;
- inner.inset(dst.width()/4, dst.height()/4);
-
- SkPoint3 norm;
- const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
- const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
- const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
- const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
-
- for (int y = dst.fTop; y < dst.fBottom; ++y) {
- for (int x = dst.fLeft; x < dst.fRight; ++x) {
- if (inner.contains(x, y)) {
- norm.set(0.0f, 0.0f, 1.0f);
- } else {
- SkScalar locX = x + 0.5f - center.fX;
- SkScalar locY = y + 0.5f - center.fY;
-
- if (locX >= 0.0f) {
- if (locY > 0.0f) {
- norm = locX >= locY ? right : down; // LR corner
- } else {
- norm = locX > -locY ? right : up; // UR corner
- }
- } else {
- if (locY > 0.0f) {
- norm = -locX > locY ? left : down; // LL corner
- } else {
- norm = locX > locY ? up : left; // UL corner
- }
- }
- }
-
- norm_to_rgb(bm, x, y, norm);
- }
- }
-}
-
-void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
- const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f),
- dst.fTop + (dst.height() / 2.0f));
-
- static const SkScalar k1OverRoot3 = 0.5773502692f;
-
- SkPoint3 norm;
- const SkPoint3 leftUp = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3);
- const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3);
- const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
-
- for (int y = dst.fTop; y < dst.fBottom; ++y) {
- for (int x = dst.fLeft; x < dst.fRight; ++x) {
- SkScalar locX = x + 0.5f - center.fX;
- SkScalar locY = y + 0.5f - center.fY;
-
- if (locX >= 0.0f) {
- if (locY > 0.0f) {
- norm = locX >= locY ? rightUp : down; // LR corner
- } else {
- norm = rightUp;
- }
- } else {
- if (locY > 0.0f) {
- norm = -locX > locY ? leftUp : down; // LL corner
- } else {
- norm = leftUp;
- }
- }
-
- norm_to_rgb(bm, x, y, norm);
- }
- }
-}
-
-#if defined(_MSC_VER)
- // MSVC takes ~2 minutes to compile this function with optimization.
- // We don't really care to wait that long for this function.
- #pragma optimize("", off)
-#endif
-void make_big_path(SkPath& path) {
- #include "BigPathBench.inc"
-}
-
-static float gaussian2d_value(int x, int y, float sigma) {
- // don't bother with the scale term since we're just going to normalize the
- // kernel anyways
- float temp = expf(-(x*x + y*y)/(2*sigma*sigma));
- return temp;
-}
-
-static float* create_2d_kernel(float sigma, int* filterSize) {
- // We will actually take 2*halfFilterSize+1 samples (i.e., our filter kernel
- // sizes are always odd)
- int halfFilterSize = SkScalarCeilToInt(6*sigma)/2;
- int wh = *filterSize = 2*halfFilterSize + 1;
-
- float* temp = new float[wh*wh];
-
- float filterTot = 0.0f;
- for (int yOff = 0; yOff < wh; ++yOff) {
- for (int xOff = 0; xOff < wh; ++xOff) {
- temp[yOff*wh+xOff] = gaussian2d_value(xOff-halfFilterSize, yOff-halfFilterSize, sigma);
-
- filterTot += temp[yOff*wh+xOff];
- }
- }
-
- // normalize the kernel
- for (int yOff = 0; yOff < wh; ++yOff) {
- for (int xOff = 0; xOff < wh; ++xOff) {
- temp[yOff*wh+xOff] /= filterTot;
- }
- }
-
- return temp;
-}
-
-static SkPMColor blur_pixel(const SkBitmap& bm, int x, int y, float* kernel, int wh) {
- SkASSERT(wh & 0x1);
-
- int halfFilterSize = (wh-1)/2;
-
- float r = 0.0f, g = 0.0f, b = 0.0f;
- for (int yOff = 0; yOff < wh; ++yOff) {
- int ySamp = y + yOff - halfFilterSize;
-
- if (ySamp < 0) {
- ySamp = 0;
- } else if (ySamp > bm.height()-1) {
- ySamp = bm.height()-1;
- }
-
- for (int xOff = 0; xOff < wh; ++xOff) {
- int xSamp = x + xOff - halfFilterSize;
-
- if (xSamp < 0) {
- xSamp = 0;
- } else if (xSamp > bm.width()-1) {
- xSamp = bm.width()-1;
- }
-
- float filter = kernel[yOff*wh + xOff];
-
- SkPMColor c = *bm.getAddr32(xSamp, ySamp);
-
- r += SkGetPackedR32(c) * filter;
- g += SkGetPackedG32(c) * filter;
- b += SkGetPackedB32(c) * filter;
- }
- }
-
- U8CPU r8, g8, b8;
-
- r8 = (U8CPU) (r+0.5f);
- g8 = (U8CPU) (g+0.5f);
- b8 = (U8CPU) (b+0.5f);
-
- return SkPackARGB32(255, r8, g8, b8);
-}
-
-SkBitmap slow_blur(const SkBitmap& src, float sigma) {
- SkBitmap dst;
-
- dst.allocN32Pixels(src.width(), src.height(), true);
-
- int wh;
- std::unique_ptr<float[]> kernel(create_2d_kernel(sigma, &wh));
-
- for (int y = 0; y < src.height(); ++y) {
- for (int x = 0; x < src.width(); ++x) {
- *dst.getAddr32(x, y) = blur_pixel(src, x, y, kernel.get(), wh);
- }
- }
-
- return dst;
-}
-
-// compute the intersection point between the diagonal and the ellipse in the
-// lower right corner
-static SkPoint intersection(SkScalar w, SkScalar h) {
- SkASSERT(w > 0.0f || h > 0.0f);
-
- return SkPoint::Make(w / SK_ScalarSqrt2, h / SK_ScalarSqrt2);
-}
-
-// Use the intersection of the corners' diagonals with their ellipses to shrink
-// the bounding rect
-SkRect compute_central_occluder(const SkRRect& rr) {
- const SkRect r = rr.getBounds();
-
- SkScalar newL = r.fLeft, newT = r.fTop, newR = r.fRight, newB = r.fBottom;
-
- SkVector radii = rr.radii(SkRRect::kUpperLeft_Corner);
- if (!radii.isZero()) {
- SkPoint p = intersection(radii.fX, radii.fY);
-
- newL = SkTMax(newL, r.fLeft + radii.fX - p.fX);
- newT = SkTMax(newT, r.fTop + radii.fY - p.fY);
- }
-
- radii = rr.radii(SkRRect::kUpperRight_Corner);
- if (!radii.isZero()) {
- SkPoint p = intersection(radii.fX, radii.fY);
-
- newR = SkTMin(newR, r.fRight + p.fX - radii.fX);
- newT = SkTMax(newT, r.fTop + radii.fY - p.fY);
- }
-
- radii = rr.radii(SkRRect::kLowerRight_Corner);
- if (!radii.isZero()) {
- SkPoint p = intersection(radii.fX, radii.fY);
-
- newR = SkTMin(newR, r.fRight + p.fX - radii.fX);
- newB = SkTMin(newB, r.fBottom - radii.fY + p.fY);
- }
-
- radii = rr.radii(SkRRect::kLowerLeft_Corner);
- if (!radii.isZero()) {
- SkPoint p = intersection(radii.fX, radii.fY);
-
- newL = SkTMax(newL, r.fLeft + radii.fX - p.fX);
- newB = SkTMin(newB, r.fBottom - radii.fY + p.fY);
- }
-
- return SkRect::MakeLTRB(newL, newT, newR, newB);
-}
-
-// The widest inset rect
-SkRect compute_widest_occluder(const SkRRect& rr) {
- const SkRect& r = rr.getBounds();
-
- const SkVector& ul = rr.radii(SkRRect::kUpperLeft_Corner);
- const SkVector& ur = rr.radii(SkRRect::kUpperRight_Corner);
- const SkVector& lr = rr.radii(SkRRect::kLowerRight_Corner);
- const SkVector& ll = rr.radii(SkRRect::kLowerLeft_Corner);
-
- SkScalar maxT = SkTMax(ul.fY, ur.fY);
- SkScalar maxB = SkTMax(ll.fY, lr.fY);
-
- return SkRect::MakeLTRB(r.fLeft, r.fTop + maxT, r.fRight, r.fBottom - maxB);
-
-}
-
-// The tallest inset rect
-SkRect compute_tallest_occluder(const SkRRect& rr) {
- const SkRect& r = rr.getBounds();
-
- const SkVector& ul = rr.radii(SkRRect::kUpperLeft_Corner);
- const SkVector& ur = rr.radii(SkRRect::kUpperRight_Corner);
- const SkVector& lr = rr.radii(SkRRect::kLowerRight_Corner);
- const SkVector& ll = rr.radii(SkRRect::kLowerLeft_Corner);
-
- SkScalar maxL = SkTMax(ul.fX, ll.fX);
- SkScalar maxR = SkTMax(ur.fX, lr.fX);
-
- return SkRect::MakeLTRB(r.fLeft + maxL, r.fTop, r.fRight - maxR, r.fBottom);
-}
-
-bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
- SkPixmap srcPM;
- if (!src.peekPixels(&srcPM)) {
- return false;
- }
-
- SkBitmap tmpDst;
- SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
- if (!tmpDst.setInfo(dstInfo)) {
- return false;
- }
-
- if (!tmpDst.tryAllocPixels()) {
- return false;
- }
-
- SkPixmap dstPM;
- if (!tmpDst.peekPixels(&dstPM)) {
- return false;
- }
-
- if (!srcPM.readPixels(dstPM)) {
- return false;
- }
-
- dst->swap(tmpDst);
- return true;
-}
-
-void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
- SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
- kRGBA_8888_SkColorType == src.colorType());
-
- SkImageInfo grayInfo = src.info().makeColorType(kGray_8_SkColorType);
- dst->allocPixels(grayInfo);
- uint8_t* dst8 = (uint8_t*)dst->getPixels();
- const uint32_t* src32 = (const uint32_t*)src.getPixels();
-
- const int w = src.width();
- const int h = src.height();
- const bool isBGRA = (kBGRA_8888_SkColorType == src.colorType());
- for (int y = 0; y < h; ++y) {
- if (isBGRA) {
- // BGRA
- for (int x = 0; x < w; ++x) {
- uint32_t s = src32[x];
- dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
- }
- } else {
- // RGBA
- for (int x = 0; x < w; ++x) {
- uint32_t s = src32[x];
- dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
- }
- }
- src32 = (const uint32_t*)((const char*)src32 + src.rowBytes());
- dst8 += dst->rowBytes();
- }
-}
-
-} // namespace sk_tool_utils
diff --git a/src/third_party/skia/tools/sk_tool_utils.h b/src/third_party/skia/tools/sk_tool_utils.h
deleted file mode 100644
index 6283225..0000000
--- a/src/third_party/skia/tools/sk_tool_utils.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef sk_tool_utils_DEFINED
-#define sk_tool_utils_DEFINED
-
-#include "SkColor.h"
-#include "SkImageEncoder.h"
-#include "SkImageInfo.h"
-#include "SkPixelSerializer.h"
-#include "SkRandom.h"
-#include "SkStream.h"
-#include "SkTDArray.h"
-#include "SkTypeface.h"
-
-class SkBitmap;
-class SkCanvas;
-class SkColorFilter;
-class SkPaint;
-class SkPath;
-class SkRRect;
-class SkShader;
-class SkTestFont;
-class SkTextBlobBuilder;
-
-namespace sk_tool_utils {
-
- const char* colortype_name(SkColorType);
-
- /**
- * Map opaque colors from 8888 to 565.
- */
- SkColor color_to_565(SkColor color);
-
- /**
- * Return a color emoji typeface if available.
- */
- sk_sp<SkTypeface> emoji_typeface();
-
- /**
- * If the platform supports color emoji, return sample text the emoji can render.
- */
- const char* emoji_sample_text();
-
- /**
- * If the platform supports color emoji, return the type (i.e. "CBDT", "SBIX", "").
- */
- const char* platform_os_emoji();
-
- /**
- * Return the platform name with the version number ("Mac10.9", "Win8", etc.) if available.
- */
- const char* platform_os_name();
-
- /**
- * Return the platform name without the version number ("Mac", "Win", etc.) if available.
- */
- SkString major_platform_os_name();
-
- /**
- * Return the platform extra config (e.g. "GDI") if available.
- */
- const char* platform_extra_config(const char* config);
-
- /**
- * Map serif, san-serif, and monospace to the platform-specific font name.
- */
- const char* platform_font_name(const char* name);
-
- /**
- * Sets the paint to use a platform-independent text renderer
- */
- void set_portable_typeface(SkPaint* paint, const char* name = nullptr,
- SkFontStyle style = SkFontStyle());
-
- /**
- * Returns a platform-independent text renderer.
- */
- sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style);
-
- /** Call to clean up portable font references. */
- void release_portable_typefaces();
-
- /**
- * Call canvas->writePixels() by using the pixels from bitmap, but with an info that claims
- * the pixels are colorType + alphaType
- */
- void write_pixels(SkCanvas*, const SkBitmap&, int x, int y, SkColorType, SkAlphaType);
-
- // private to sk_tool_utils
- sk_sp<SkTypeface> create_font(const char* name, SkFontStyle);
-
- /** Returns a newly created CheckerboardShader. */
- sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size);
-
- /** Draw a checkerboard pattern in the current canvas, restricted to
- the current clip, using SkXfermode::kSrc_Mode. */
- void draw_checkerboard(SkCanvas* canvas,
- SkColor color1,
- SkColor color2,
- int checkSize);
-
- /** Make it easier to create a bitmap-based checkerboard */
- SkBitmap create_checkerboard_bitmap(int w, int h,
- SkColor c1, SkColor c2,
- int checkSize);
-
- /** A default checkerboard. */
- inline void draw_checkerboard(SkCanvas* canvas) {
- sk_tool_utils::draw_checkerboard(canvas, 0xFF999999, 0xFF666666, 8);
- }
-
- SkBitmap create_string_bitmap(int w, int h, SkColor c, int x, int y,
- int textSize, const char* str);
-
- // A helper for inserting a drawtext call into a SkTextBlobBuilder
- void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
- SkScalar x, SkScalar y);
-
- void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst);
-
- void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst);
-
- void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);
-
- void make_big_path(SkPath& path);
-
- // Return a blurred version of 'src'. This doesn't use a separable filter
- // so it is slow!
- SkBitmap slow_blur(const SkBitmap& src, float sigma);
-
- SkRect compute_central_occluder(const SkRRect& rr);
- SkRect compute_widest_occluder(const SkRRect& rr);
- SkRect compute_tallest_occluder(const SkRRect& rr);
-
- // A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
- class TopoTestNode {
- public:
- TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) { }
-
- void dependsOn(TopoTestNode* src) {
- *fDependencies.append() = src;
- }
-
- int id() const { return fID; }
- void reset() { fOutputPos = -1; }
-
- int outputPos() const { return fOutputPos; }
-
- // check that the topological sort is valid for this node
- bool check() {
- if (-1 == fOutputPos) {
- return false;
- }
-
- for (int i = 0; i < fDependencies.count(); ++i) {
- if (-1 == fDependencies[i]->outputPos()) {
- return false;
- }
- // This node should've been output after all the nodes on which it depends
- if (fOutputPos < fDependencies[i]->outputPos()) {
- return false;
- }
- }
-
- return true;
- }
-
- // The following 7 methods are needed by the topological sort
- static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; }
- static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; }
- static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; }
- static void Output(TopoTestNode* node, int outputPos) {
- SkASSERT(-1 != outputPos);
- node->fOutputPos = outputPos;
- }
- static bool WasOutput(TopoTestNode* node) { return (-1 != node->fOutputPos); }
- static int NumDependencies(TopoTestNode* node) { return node->fDependencies.count(); }
- static TopoTestNode* Dependency(TopoTestNode* node, int index) {
- return node->fDependencies[index];
- }
-
- // Helper functions for TopoSortBench & TopoSortTest
- static void AllocNodes(SkTDArray<TopoTestNode*>* graph, int num) {
- graph->setReserve(num);
-
- for (int i = 0; i < num; ++i) {
- *graph->append() = new TopoTestNode(i);
- }
- }
-
- static void DeallocNodes(SkTDArray<TopoTestNode*>* graph) {
- for (int i = 0; i < graph->count(); ++i) {
- delete (*graph)[i];
- }
- }
-
- #ifdef SK_DEBUG
- static void Print(const SkTDArray<TopoTestNode*>& graph) {
- for (int i = 0; i < graph.count(); ++i) {
- SkDebugf("%d, ", graph[i]->id());
- }
- SkDebugf("\n");
- }
- #endif
-
- // randomize the array
- static void Shuffle(SkTDArray<TopoTestNode*>* graph, SkRandom* rand) {
- for (int i = graph->count()-1; i > 0; --i) {
- int swap = rand->nextU() % (i+1);
-
- TopoTestNode* tmp = (*graph)[i];
- (*graph)[i] = (*graph)[swap];
- (*graph)[swap] = tmp;
- }
- }
-
- private:
- int fID;
- int fOutputPos;
- bool fTempMark;
-
- SkTDArray<TopoTestNode*> fDependencies;
- };
-
- template <typename T>
- inline bool EncodeImageToFile(const char* path, const T& src, SkEncodedImageFormat f, int q) {
- SkFILEWStream file(path);
- return file.isValid() && SkEncodeImage(&file, src, f, q);
- }
-
- template <typename T>
- inline sk_sp<SkData> EncodeImageToData(const T& src, SkEncodedImageFormat f, int q) {
- SkDynamicMemoryWStream buf;
- return SkEncodeImage(&buf, src , f, q) ? buf.detachAsData() : nullptr;
- }
-
- /**
- * Uses SkEncodeImage to serialize images that are not already
- * encoded as SkEncodedImageFormat::kPNG images.
- */
- inline sk_sp<SkPixelSerializer> MakePixelSerializer() {
- struct EncodeImagePixelSerializer final : SkPixelSerializer {
- bool onUseEncodedData(const void*, size_t) override { return true; }
- SkData* onEncode(const SkPixmap& pmap) override {
- return EncodeImageToData(pmap, SkEncodedImageFormat::kPNG, 100).release();
- }
- };
- return sk_make_sp<EncodeImagePixelSerializer>();
- }
-
- bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
- void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
-
-} // namespace sk_tool_utils
-
-#endif // sk_tool_utils_DEFINED
diff --git a/src/third_party/skia/tools/sk_tool_utils_flags.h b/src/third_party/skia/tools/sk_tool_utils_flags.h
deleted file mode 100644
index ee15fbd..0000000
--- a/src/third_party/skia/tools/sk_tool_utils_flags.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef sk_tool_utils_flags_DEFINED
-#define sk_tool_utils_flags_DEFINED
-
-#include "SkCommandLineFlags.h"
-
-DECLARE_bool(portableFonts);
-DECLARE_bool(resourceFonts);
-
-#endif // sk_tool_utils_flags_DEFINED
diff --git a/src/third_party/skia/tools/sk_tool_utils_font.cpp b/src/third_party/skia/tools/sk_tool_utils_font.cpp
deleted file mode 100644
index bdd88d0..0000000
--- a/src/third_party/skia/tools/sk_tool_utils_font.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Resources.h"
-#include "SkFontMgr.h"
-#include "SkMutex.h"
-#include "SkOSFile.h"
-#include "SkTestScalerContext.h"
-#include "SkUtils.h"
-#include "sk_tool_utils.h"
-
-namespace sk_tool_utils {
-
-#include "test_font_monospace.inc"
-#include "test_font_sans_serif.inc"
-#include "test_font_serif.inc"
-#include "test_font_index.inc"
-
-void release_portable_typefaces() {
- for (int index = 0; index < gTestFontsCount; ++index) {
- SkTestFontData& fontData = gTestFonts[index];
- fontData.fCachedFont.reset();
- }
-}
-
-SK_DECLARE_STATIC_MUTEX(gTestFontMutex);
-
-sk_sp<SkTypeface> create_font(const char* name, SkFontStyle style) {
- SkTestFontData* fontData = nullptr;
- const SubFont* sub;
- if (name) {
- for (int index = 0; index < gSubFontsCount; ++index) {
- sub = &gSubFonts[index];
- if (!strcmp(name, sub->fName) && sub->fStyle == style) {
- fontData = &sub->fFont;
- break;
- }
- }
- if (!fontData) {
- // Once all legacy callers to portable fonts are converted, replace this with
- // SK_ABORT();
- SkDebugf("missing %s weight %d, width %d, slant %d\n",
- name, style.weight(), style.width(), style.slant());
- // If we called SkTypeface::CreateFromName() here we'd recurse infinitely,
- // so we reimplement its core logic here inline without the recursive aspect.
- sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- return sk_sp<SkTypeface>(fm->legacyCreateTypeface(name, style));
- }
- } else {
- sub = &gSubFonts[gDefaultFontIndex];
- fontData = &sub->fFont;
- }
- sk_sp<SkTestFont> font;
- {
- SkAutoMutexAcquire ac(gTestFontMutex);
- if (fontData->fCachedFont) {
- font = fontData->fCachedFont;
- } else {
- font = sk_make_sp<SkTestFont>(*fontData);
- SkDEBUGCODE(font->fDebugName = sub->fName);
- SkDEBUGCODE(font->fDebugStyle = sub->fStyle);
- fontData->fCachedFont = font;
- }
- }
- return sk_make_sp<SkTestTypeface>(std::move(font), style);
-}
-
-}
diff --git a/src/third_party/skia/tools/skdiff/skdiff.cpp b/src/third_party/skia/tools/skdiff/skdiff.cpp
index c7ddf7d..f1abc9f 100644
--- a/src/third_party/skia/tools/skdiff/skdiff.cpp
+++ b/src/third_party/skia/tools/skdiff/skdiff.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "skdiff.h"
-#include "SkBitmap.h"
-#include "SkColor.h"
-#include "SkColorPriv.h"
-#include "SkTypes.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkColorPriv.h"
+#include "include/core/SkTypes.h"
+#include "tools/skdiff/skdiff.h"
/*static*/ char const * const DiffRecord::ResultNames[DiffRecord::kResultCount] = {
"EqualBits",
diff --git a/src/third_party/skia/tools/skdiff/skdiff.h b/src/third_party/skia/tools/skdiff/skdiff.h
index 6bdaadc..4ab79b8 100644
--- a/src/third_party/skia/tools/skdiff/skdiff.h
+++ b/src/third_party/skia/tools/skdiff/skdiff.h
@@ -8,13 +8,13 @@
#ifndef skdiff_DEFINED
#define skdiff_DEFINED
-#include "SkBitmap.h"
-#include "SkColor.h"
-#include "SkColorPriv.h"
-#include "SkString.h"
-#include "../private/SkTDArray.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkColorPriv.h"
+#include "include/core/SkString.h"
+#include "include/private/SkTDArray.h"
-#if defined(SK_BUILD_FOR_WIN32)
+#if defined(SK_BUILD_FOR_WIN)
#define PATH_DIV_STR "\\"
#define PATH_DIV_CHAR '\\'
#else
diff --git a/src/third_party/skia/tools/skdiff/skdiff_html.cpp b/src/third_party/skia/tools/skdiff/skdiff_html.cpp
index 6f3c3b0..4e5a83c 100644
--- a/src/third_party/skia/tools/skdiff/skdiff_html.cpp
+++ b/src/third_party/skia/tools/skdiff/skdiff_html.cpp
@@ -5,10 +5,10 @@
* found in the LICENSE file.
*/
-#include "skdiff.h"
-#include "skdiff_html.h"
-#include "SkStream.h"
-#include "SkTime.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTime.h"
+#include "tools/skdiff/skdiff.h"
+#include "tools/skdiff/skdiff_html.h"
/// Make layout more consistent by scaling image to 240 height, 360 width,
/// or natural size, whichever is smallest.
@@ -245,7 +245,7 @@
if (outputDir.size() > 0 && PATH_DIV_CHAR == outputDir[0]) {
isPathAbsolute = true;
}
-#ifdef SK_BUILD_FOR_WIN32
+#ifdef SK_BUILD_FOR_WIN
// On Windows, absolute paths can also start with "x:", where x is any
// drive letter.
if (outputDir.size() > 1 && ':' == outputDir[1]) {
diff --git a/src/third_party/skia/tools/skdiff/skdiff_html.h b/src/third_party/skia/tools/skdiff/skdiff_html.h
index eefbebf..a881498 100644
--- a/src/third_party/skia/tools/skdiff/skdiff_html.h
+++ b/src/third_party/skia/tools/skdiff/skdiff_html.h
@@ -8,7 +8,7 @@
#ifndef skdiff_html_DEFINED
#define skdiff_html_DEFINED
-#include "skdiff.h"
+#include "tools/skdiff/skdiff.h"
class SkString;
void print_diff_page(const int matchCount,
diff --git a/src/third_party/skia/tools/skdiff/skdiff_image.cpp b/src/third_party/skia/tools/skdiff/skdiff_image.cpp
deleted file mode 100644
index cb446d4..0000000
--- a/src/third_party/skia/tools/skdiff/skdiff_image.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "skdiff.h"
-#include "skdiff_utils.h"
-#include "SkBitmap.h"
-#include "SkData.h"
-#include "SkImageEncoder.h"
-#include "SkOSFile.h"
-#include "SkTypes.h"
-
-#include <stdio.h>
-
-/// If outputDir.isEmpty(), don't write out diff files.
-static void create_diff_images (DiffMetricProc dmp,
- const int colorThreshold,
- const SkString& baseFile,
- const SkString& comparisonFile,
- const SkString& outputDir,
- const SkString& outputFilename,
- DiffRecord* drp) {
- SkASSERT(!baseFile.isEmpty());
- SkASSERT(!comparisonFile.isEmpty());
-
- drp->fBase.fFilename = baseFile;
- drp->fBase.fFullPath = baseFile;
- drp->fBase.fStatus = DiffResource::kSpecified_Status;
-
- drp->fComparison.fFilename = comparisonFile;
- drp->fComparison.fFullPath = comparisonFile;
- drp->fComparison.fStatus = DiffResource::kSpecified_Status;
-
- sk_sp<SkData> baseFileBits = read_file(drp->fBase.fFullPath.c_str());
- if (baseFileBits) {
- drp->fBase.fStatus = DiffResource::kRead_Status;
- }
- sk_sp<SkData> comparisonFileBits = read_file(drp->fComparison.fFullPath.c_str());
- if (comparisonFileBits) {
- drp->fComparison.fStatus = DiffResource::kRead_Status;
- }
- if (nullptr == baseFileBits || nullptr == comparisonFileBits) {
- if (nullptr == baseFileBits) {
- drp->fBase.fStatus = DiffResource::kCouldNotRead_Status;
- }
- if (nullptr == comparisonFileBits) {
- drp->fComparison.fStatus = DiffResource::kCouldNotRead_Status;
- }
- drp->fResult = DiffRecord::kCouldNotCompare_Result;
- return;
- }
-
- if (are_buffers_equal(baseFileBits.get(), comparisonFileBits.get())) {
- drp->fResult = DiffRecord::kEqualBits_Result;
- return;
- }
-
- get_bitmap(baseFileBits, drp->fBase, false);
- get_bitmap(comparisonFileBits, drp->fComparison, false);
- if (DiffResource::kDecoded_Status != drp->fBase.fStatus ||
- DiffResource::kDecoded_Status != drp->fComparison.fStatus)
- {
- drp->fResult = DiffRecord::kCouldNotCompare_Result;
- return;
- }
-
- create_and_write_diff_image(drp, dmp, colorThreshold, outputDir, outputFilename);
- //TODO: copy fBase.fFilename and fComparison.fFilename to outputDir
- // svn and git often present tmp files to diff tools which are promptly deleted
-
- //TODO: serialize drp to outputDir
- // write a tool to deserialize them and call print_diff_page
-
- SkASSERT(DiffRecord::kUnknown_Result != drp->fResult);
-}
-
-static void usage (char * argv0) {
- SkDebugf("Skia image diff tool\n");
- SkDebugf("\n"
-"Usage: \n"
-" %s <baseFile> <comparisonFile>\n" , argv0);
- SkDebugf(
-"\nArguments:"
-"\n --failonresult <result>: After comparing all file pairs, exit with nonzero"
-"\n return code (number of file pairs yielding this"
-"\n result) if any file pairs yielded this result."
-"\n This flag may be repeated, in which case the"
-"\n return code will be the number of fail pairs"
-"\n yielding ANY of these results."
-"\n --failonstatus <baseStatus> <comparisonStatus>: exit with nonzero return"
-"\n code if any file pairs yeilded this status."
-"\n --help: display this info"
-"\n --listfilenames: list all filenames for each result type in stdout"
-"\n --nodiffs: don't write out image diffs, just generate report on stdout"
-"\n --outputdir: directory to write difference images"
-"\n --threshold <n>: only report differences > n (per color channel) [default 0]"
-"\n -u: ignored. Recognized for compatibility with svn diff."
-"\n -L: first occurrence label for base, second occurrence label for comparison."
-"\n Labels must be of the form \"<filename>(\t<specifier>)?\"."
-"\n The base <filename> will be used to create files in outputdir."
-"\n"
-"\n baseFile: baseline image file."
-"\n comparisonFile: comparison image file"
-"\n"
-"\nIf no sort is specified, it will sort by fraction of pixels mismatching."
-"\n");
-}
-
-const int kNoError = 0;
-const int kGenericError = -1;
-
-int main(int argc, char** argv) {
- DiffMetricProc diffProc = compute_diff_pmcolor;
-
- // Maximum error tolerated in any one color channel in any one pixel before
- // a difference is reported.
- int colorThreshold = 0;
- SkString baseFile;
- SkString baseLabel;
- SkString comparisonFile;
- SkString comparisonLabel;
- SkString outputDir;
-
- bool listFilenames = false;
-
- bool failOnResultType[DiffRecord::kResultCount];
- for (int i = 0; i < DiffRecord::kResultCount; i++) {
- failOnResultType[i] = false;
- }
-
- bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount];
- for (int base = 0; base < DiffResource::kStatusCount; ++base) {
- for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
- failOnStatusType[base][comparison] = false;
- }
- }
-
- int i;
- int numUnflaggedArguments = 0;
- int numLabelArguments = 0;
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "--failonresult")) {
- if (argc == ++i) {
- SkDebugf("failonresult expects one argument.\n");
- continue;
- }
- DiffRecord::Result type = DiffRecord::getResultByName(argv[i]);
- if (type != DiffRecord::kResultCount) {
- failOnResultType[type] = true;
- } else {
- SkDebugf("ignoring unrecognized result <%s>\n", argv[i]);
- }
- continue;
- }
- if (!strcmp(argv[i], "--failonstatus")) {
- if (argc == ++i) {
- SkDebugf("failonstatus missing base status.\n");
- continue;
- }
- bool baseStatuses[DiffResource::kStatusCount];
- if (!DiffResource::getMatchingStatuses(argv[i], baseStatuses)) {
- SkDebugf("unrecognized base status <%s>\n", argv[i]);
- }
-
- if (argc == ++i) {
- SkDebugf("failonstatus missing comparison status.\n");
- continue;
- }
- bool comparisonStatuses[DiffResource::kStatusCount];
- if (!DiffResource::getMatchingStatuses(argv[i], comparisonStatuses)) {
- SkDebugf("unrecognized comarison status <%s>\n", argv[i]);
- }
-
- for (int base = 0; base < DiffResource::kStatusCount; ++base) {
- for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
- failOnStatusType[base][comparison] |=
- baseStatuses[base] && comparisonStatuses[comparison];
- }
- }
- continue;
- }
- if (!strcmp(argv[i], "--help")) {
- usage(argv[0]);
- return kNoError;
- }
- if (!strcmp(argv[i], "--listfilenames")) {
- listFilenames = true;
- continue;
- }
- if (!strcmp(argv[i], "--outputdir")) {
- if (argc == ++i) {
- SkDebugf("outputdir expects one argument.\n");
- continue;
- }
- outputDir.set(argv[i]);
- continue;
- }
- if (!strcmp(argv[i], "--threshold")) {
- colorThreshold = atoi(argv[++i]);
- continue;
- }
- if (!strcmp(argv[i], "-u")) {
- //we don't produce unified diffs, ignore parameter to work with svn diff
- continue;
- }
- if (!strcmp(argv[i], "-L")) {
- if (argc == ++i) {
- SkDebugf("label expects one argument.\n");
- continue;
- }
- switch (numLabelArguments++) {
- case 0:
- baseLabel.set(argv[i]);
- continue;
- case 1:
- comparisonLabel.set(argv[i]);
- continue;
- default:
- SkDebugf("extra label argument <%s>\n", argv[i]);
- usage(argv[0]);
- return kGenericError;
- }
- continue;
- }
- if (argv[i][0] != '-') {
- switch (numUnflaggedArguments++) {
- case 0:
- baseFile.set(argv[i]);
- continue;
- case 1:
- comparisonFile.set(argv[i]);
- continue;
- default:
- SkDebugf("extra unflagged argument <%s>\n", argv[i]);
- usage(argv[0]);
- return kGenericError;
- }
- }
-
- SkDebugf("Unrecognized argument <%s>\n", argv[i]);
- usage(argv[0]);
- return kGenericError;
- }
-
- if (numUnflaggedArguments != 2) {
- usage(argv[0]);
- return kGenericError;
- }
-
- if (listFilenames) {
- printf("Base file is [%s]\n", baseFile.c_str());
- }
-
- if (listFilenames) {
- printf("Comparison file is [%s]\n", comparisonFile.c_str());
- }
-
- if (outputDir.isEmpty()) {
- if (listFilenames) {
- printf("Not writing any diffs. No output dir specified.\n");
- }
- } else {
- if (!outputDir.endsWith(PATH_DIV_STR)) {
- outputDir.append(PATH_DIV_STR);
- }
- if (listFilenames) {
- printf("Writing diffs. Output dir is [%s]\n", outputDir.c_str());
- }
- }
-
- // Some obscure documentation about diff/patch labels:
- //
- // Posix says the format is: <filename><tab><date>
- // It also states that if a filename contains <tab> or <newline>
- // the result is implementation defined
- //
- // Svn diff --diff-cmd provides labels of the form: <filename><tab><revision>
- //
- // Git diff --ext-diff does not supply arguments compatible with diff.
- // However, it does provide the filename directly.
- // skimagediff_git.sh: skimagediff %2 %5 -L "%1\t(%3)" -L "%1\t(%6)"
- //
- // Git difftool sets $LOCAL, $REMOTE, $MERGED, and $BASE instead of command line parameters.
- // difftool.<>.cmd: skimagediff $LOCAL $REMOTE -L "$MERGED\t(local)" -L "$MERGED\t(remote)"
- //
- // Diff will write any specified label verbatim. Without a specified label diff will write
- // <filename><tab><date>
- // However, diff will encode the filename as a cstring if the filename contains
- // Any of <space> or <double quote>
- // A char less than 32
- // Any escapable character \\, \a, \b, \t, \n, \v, \f, \r
- //
- // Patch decodes:
- // If first <non-white-space> is <double quote>, parse filename from cstring.
- // If there is a <tab> after the first <non-white-space>, filename is
- // [first <non-white-space>, the next run of <white-space> with an embedded <tab>).
- // Otherwise the filename is [first <non-space>, the next <white-space>).
- //
- // The filename /dev/null means the file does not exist (used in adds and deletes).
-
- // Considering the above, skimagediff will consider the contents of a -L parameter as
- // <filename>(\t<specifier>)?
- SkString outputFile;
-
- if (baseLabel.isEmpty()) {
- baseLabel.set(baseFile);
- outputFile = baseLabel;
- } else {
- const char* baseLabelCstr = baseLabel.c_str();
- const char* tab = strchr(baseLabelCstr, '\t');
- if (nullptr == tab) {
- outputFile = baseLabel;
- } else {
- outputFile.set(baseLabelCstr, tab - baseLabelCstr);
- }
- }
- if (comparisonLabel.isEmpty()) {
- comparisonLabel.set(comparisonFile);
- }
- printf("Base: %s\n", baseLabel.c_str());
- printf("Comparison: %s\n", comparisonLabel.c_str());
-
- DiffRecord dr;
- create_diff_images(diffProc, colorThreshold, baseFile, comparisonFile, outputDir, outputFile,
- &dr);
-
- if (DiffResource::isStatusFailed(dr.fBase.fStatus)) {
- printf("Base %s.\n", DiffResource::getStatusDescription(dr.fBase.fStatus));
- }
- if (DiffResource::isStatusFailed(dr.fComparison.fStatus)) {
- printf("Comparison %s.\n", DiffResource::getStatusDescription(dr.fComparison.fStatus));
- }
- printf("Base and Comparison %s.\n", DiffRecord::getResultDescription(dr.fResult));
-
- if (DiffRecord::kDifferentPixels_Result == dr.fResult) {
- printf("%.4f%% of pixels differ", 100 * dr.fFractionDifference);
- printf(" (%.4f%% weighted)", 100 * dr.fWeightedFraction);
- if (dr.fFractionDifference < 0.01) {
- printf(" %d pixels", static_cast<int>(dr.fFractionDifference *
- dr.fBase.fBitmap.width() *
- dr.fBase.fBitmap.height()));
- }
-
- printf("\nAverage color mismatch: ");
- printf("%d", static_cast<int>(MAX3(dr.fAverageMismatchR,
- dr.fAverageMismatchG,
- dr.fAverageMismatchB)));
- printf("\nMax color mismatch: ");
- printf("%d", MAX3(dr.fMaxMismatchR,
- dr.fMaxMismatchG,
- dr.fMaxMismatchB));
- printf("\n");
- }
- printf("\n");
-
- int num_failing_results = 0;
- if (failOnResultType[dr.fResult]) {
- ++num_failing_results;
- }
- if (failOnStatusType[dr.fBase.fStatus][dr.fComparison.fStatus]) {
- ++num_failing_results;
- }
-
- return num_failing_results;
-}
diff --git a/src/third_party/skia/tools/skdiff/skdiff_main.cpp b/src/third_party/skia/tools/skdiff/skdiff_main.cpp
index 59e9b0a..df6e2a1 100644
--- a/src/third_party/skia/tools/skdiff/skdiff_main.cpp
+++ b/src/third_party/skia/tools/skdiff/skdiff_main.cpp
@@ -4,18 +4,18 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "skdiff.h"
-#include "skdiff_html.h"
-#include "skdiff_utils.h"
-#include "SkBitmap.h"
-#include "SkData.h"
-#include "SkImageEncoder.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkStream.h"
-#include "SkPixelRef.h"
-#include "../private/SkTDArray.h"
-#include "../private/SkTSearch.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+#include "include/core/SkImageEncoder.h"
+#include "include/core/SkPixelRef.h"
+#include "include/core/SkStream.h"
+#include "include/private/SkTDArray.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkTSearch.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/skdiff/skdiff.h"
+#include "tools/skdiff/skdiff_html.h"
+#include "tools/skdiff/skdiff_utils.h"
#include <stdlib.h>
@@ -183,14 +183,14 @@
uint32_t mismatchValue;
if (drp->fBase.fFilename.equals(drp->fComparison.fFilename)) {
- fResultsOfType[drp->fResult].push(new SkString(drp->fBase.fFilename));
+ fResultsOfType[drp->fResult].push_back(new SkString(drp->fBase.fFilename));
} else {
SkString* blame = new SkString("(");
blame->append(drp->fBase.fFilename);
blame->append(", ");
blame->append(drp->fComparison.fFilename);
blame->append(")");
- fResultsOfType[drp->fResult].push(blame);
+ fResultsOfType[drp->fResult].push_back(blame);
}
switch (drp->fResult) {
case DiffRecord::kEqualBits_Result:
@@ -215,7 +215,7 @@
break;
case DiffRecord::kCouldNotCompare_Result:
fNumMismatches++;
- fStatusOfType[drp->fBase.fStatus][drp->fComparison.fStatus].push(
+ fStatusOfType[drp->fBase.fStatus][drp->fComparison.fStatus].push_back(
new SkString(drp->fBase.fFilename));
break;
case DiffRecord::kUnknown_Result:
@@ -274,7 +274,7 @@
pathRelativeToRootDir.append(fileName);
if (string_contains_any_of(pathRelativeToRootDir, matchSubstrings) &&
!string_contains_any_of(pathRelativeToRootDir, nomatchSubstrings)) {
- files->push(new SkString(pathRelativeToRootDir));
+ files->push_back(new SkString(pathRelativeToRootDir));
}
}
@@ -344,7 +344,7 @@
if (resource.fBitmap.empty() && !DiffResource::isStatusFailed(resource.fStatus)) {
sk_sp<SkData> fileBits(read_file(resource.fFullPath.c_str()));
if (fileBits) {
- get_bitmap(fileBits, resource, true);
+ get_bitmap(fileBits, resource, true, true);
} else {
SkDebugf("WARNING: couldn't read %s file <%s>\n", name, resource.fFullPath.c_str());
resource.fStatus = DiffResource::kCouldNotRead_Status;
@@ -375,6 +375,7 @@
/// If outputDir.isEmpty(), don't write out diff files.
static void create_diff_images (DiffMetricProc dmp,
const int colorThreshold,
+ bool ignoreColorSpace,
RecordArray* differences,
const SkString& baseDir,
const SkString& comparisonDir,
@@ -495,8 +496,8 @@
VERBOSE_STATUS("MATCH", ANSI_COLOR_GREEN, baseFiles[i]);
} else {
AutoReleasePixels arp(drp);
- get_bitmap(baseFileBits, drp->fBase, false);
- get_bitmap(comparisonFileBits, drp->fComparison, false);
+ get_bitmap(baseFileBits, drp->fBase, false, ignoreColorSpace);
+ get_bitmap(comparisonFileBits, drp->fComparison, false, ignoreColorSpace);
VERBOSE_STATUS("DIFFERENT", ANSI_COLOR_RED, baseFiles[i]);
if (DiffResource::kDecoded_Status == drp->fBase.fStatus &&
DiffResource::kDecoded_Status == drp->fComparison.fStatus) {
@@ -515,7 +516,7 @@
get_bounds(*drp);
}
SkASSERT(DiffRecord::kUnknown_Result != drp->fResult);
- differences->push(drp);
+ differences->push_back(drp);
summary->add(drp);
}
@@ -536,7 +537,7 @@
if (getBounds) {
get_bounds(*drp);
}
- differences->push(drp);
+ differences->push_back(drp);
summary->add(drp);
}
@@ -557,7 +558,7 @@
if (getBounds) {
get_bounds(*drp);
}
- differences->push(drp);
+ differences->push_back(drp);
summary->add(drp);
}
@@ -585,6 +586,7 @@
"\n --match <substring>: compare files whose filenames contain this substring;"
"\n if unspecified, compare ALL files."
"\n this flag may be repeated."
+"\n --nocolorspace: Ignore color space of images."
"\n --nodiffs: don't write out image diffs or index.html, just generate"
"\n report on stdout"
"\n --nomatch <substring>: regardless of --match, DO NOT compare files whose"
@@ -630,6 +632,7 @@
bool recurseIntoSubdirs = true;
bool verbose = false;
bool listFailingBase = false;
+ bool ignoreColorSpace = false;
RecordArray differences;
DiffSummary summary;
@@ -702,7 +705,11 @@
continue;
}
if (!strcmp(argv[i], "--match")) {
- matchSubstrings.push(new SkString(argv[++i]));
+ matchSubstrings.push_back(new SkString(argv[++i]));
+ continue;
+ }
+ if (!strcmp(argv[i], "--nocolorspace")) {
+ ignoreColorSpace = true;
continue;
}
if (!strcmp(argv[i], "--nodiffs")) {
@@ -710,7 +717,7 @@
continue;
}
if (!strcmp(argv[i], "--nomatch")) {
- nomatchSubstrings.push(new SkString(argv[++i]));
+ nomatchSubstrings.push_back(new SkString(argv[++i]));
continue;
}
if (!strcmp(argv[i], "--noprintdirs")) {
@@ -802,10 +809,10 @@
// If no matchSubstrings were specified, match ALL strings
// (except for whatever nomatchSubstrings were specified, if any).
if (matchSubstrings.isEmpty()) {
- matchSubstrings.push(new SkString(""));
+ matchSubstrings.push_back(new SkString(""));
}
- create_diff_images(diffProc, colorThreshold, &differences,
+ create_diff_images(diffProc, colorThreshold, ignoreColorSpace, &differences,
baseDir, comparisonDir, outputDir,
matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, generateDiffs,
verbose, &summary);
diff --git a/src/third_party/skia/tools/skdiff/skdiff_utils.cpp b/src/third_party/skia/tools/skdiff/skdiff_utils.cpp
index 7a1b7e8..38468dc 100644
--- a/src/third_party/skia/tools/skdiff/skdiff_utils.cpp
+++ b/src/third_party/skia/tools/skdiff/skdiff_utils.cpp
@@ -4,15 +4,15 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "skdiff.h"
-#include "skdiff_utils.h"
-#include "sk_tool_utils.h"
-#include "SkBitmap.h"
-#include "SkCodec.h"
-#include "SkData.h"
-#include "SkImageEncoder.h"
-#include "SkStream.h"
-#include "SkTypes.h"
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+#include "include/core/SkImageEncoder.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypes.h"
+#include "tools/ToolUtils.h"
+#include "tools/skdiff/skdiff.h"
+#include "tools/skdiff/skdiff_utils.h"
#include <memory>
@@ -34,15 +34,27 @@
return data;
}
-bool get_bitmap(sk_sp<SkData> fileBits, DiffResource& resource, bool sizeOnly) {
- std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(fileBits));
+bool get_bitmap(sk_sp<SkData> fileBits, DiffResource& resource, bool sizeOnly,
+ bool ignoreColorSpace) {
+ auto codec = SkCodec::MakeFromData(fileBits);
if (!codec) {
SkDebugf("ERROR: could not create codec for <%s>\n", resource.fFullPath.c_str());
resource.fStatus = DiffResource::kCouldNotDecode_Status;
return false;
}
- if (!resource.fBitmap.setInfo(codec->getInfo().makeColorType(kN32_SkColorType))) {
+ // If we're "ignoring" color space, then we want the raw pixel values from each image, so we
+ // decode to the original color space. If we want to account for color spaces, then we want to
+ // decode each image to the same color space, so that colors that are the "same" (but encoded
+ // differently) are transformed to some canonical representation prior to comparison.
+ //
+ // TODO: Use something wider than sRGB to avoid clipping with out-of-gamut colors.
+ SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
+ if (!ignoreColorSpace) {
+ info = info.makeColorSpace(SkColorSpace::MakeSRGB());
+ }
+
+ if (!resource.fBitmap.setInfo(info.makeColorType(kN32_SkColorType))) {
SkDebugf("ERROR: could not set bitmap info for <%s>\n", resource.fFullPath.c_str());
resource.fStatus = DiffResource::kCouldNotDecode_Status;
return false;
@@ -80,10 +92,9 @@
bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
SkBitmap copy;
- sk_tool_utils::copy_to(©, kN32_SkColorType, bitmap);
+ ToolUtils::copy_to(©, kN32_SkColorType, bitmap);
force_all_opaque(copy);
- return sk_tool_utils::EncodeImageToFile(path.c_str(), copy,
- SkEncodedImageFormat::kPNG, 100);
+ return ToolUtils::EncodeImageToFile(path.c_str(), copy, SkEncodedImageFormat::kPNG, 100);
}
/// Return a copy of the "input" string, within which we have replaced all instances
diff --git a/src/third_party/skia/tools/skdiff/skdiff_utils.h b/src/third_party/skia/tools/skdiff/skdiff_utils.h
index c799325..9a6385c 100644
--- a/src/third_party/skia/tools/skdiff/skdiff_utils.h
+++ b/src/third_party/skia/tools/skdiff/skdiff_utils.h
@@ -8,7 +8,7 @@
#ifndef skdiff_utils_DEFINED
#define skdiff_utils_DEFINED
-#include "skdiff.h"
+#include "tools/skdiff/skdiff.h"
class SkBitmap;
class SkData;
@@ -25,7 +25,8 @@
sk_sp<SkData> read_file(const char* file_path);
/** Decodes the fileBits into the resource.fBitmap. Returns false on failure. */
-bool get_bitmap(sk_sp<SkData> fileBits, DiffResource& resource, bool sizeOnly);
+bool get_bitmap(sk_sp<SkData> fileBits, DiffResource& resource, bool sizeOnly,
+ bool ignoreColorSpace);
/** Writes the bitmap as a PNG to the path specified. */
bool write_bitmap(const SkString& path, const SkBitmap& bitmap);
diff --git a/src/third_party/skia/tools/skhello.cpp b/src/third_party/skia/tools/skhello.cpp
index 2ab8069..cd84eab 100644
--- a/src/third_party/skia/tools/skhello.cpp
+++ b/src/third_party/skia/tools/skhello.cpp
@@ -5,18 +5,18 @@
* found in the LICENSE file.
*/
-#include "SkCanvas.h"
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkDocument.h"
-#include "SkGraphics.h"
-#include "SkSurface.h"
-#include "SkImage.h"
-#include "SkStream.h"
-#include "SkString.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkData.h"
+#include "include/core/SkDocument.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+#include "include/core/SkSurface.h"
+#include "tools/flags/CommandLineFlags.h"
-DEFINE_string2(outFile, o, "skhello", "The filename to write the image.");
-DEFINE_string2(text, t, "Hello", "The string to write.");
+static DEFINE_string2(outFile, o, "skhello", "The filename to write the image.");
+static DEFINE_string2(text, t, "Hello", "The string to write.");
static void doDraw(SkCanvas* canvas, const SkPaint& paint, const char text[]) {
SkRect bounds = canvas->getLocalClipBounds();
@@ -44,7 +44,7 @@
static bool do_document(int w, int h, const char path[], const char text[],
const SkPaint& paint) {
- sk_sp<SkDocument> doc(SkDocument::MakePDF(path));
+ auto doc = SkPDF::MakeDocument(path);
if (doc.get()) {
SkScalar width = SkIntToScalar(w);
SkScalar height = SkIntToScalar(h);
@@ -55,8 +55,8 @@
}
int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::SetUsage("");
+ CommandLineFlags::Parse(argc, argv);
SkAutoGraphics ag;
SkString path("skhello");
diff --git a/src/third_party/skia/tools/skiaserve/Request.cpp b/src/third_party/skia/tools/skiaserve/Request.cpp
index 12f3596..ef1934e 100644
--- a/src/third_party/skia/tools/skiaserve/Request.cpp
+++ b/src/third_party/skia/tools/skiaserve/Request.cpp
@@ -5,13 +5,11 @@
* found in the LICENSE file.
*/
-#include "Request.h"
+#include "tools/skiaserve/Request.h"
-#include "SkPictureRecorder.h"
-#include "SkPixelSerializer.h"
-#include "SkPM4fPriv.h"
-#include "picture_utils.h"
-#include "sk_tool_utils.h"
+#include "include/core/SkPictureRecorder.h"
+#include "src/utils/SkJSONWriter.h"
+#include "tools/ToolUtils.h"
using namespace sk_gpu_test;
@@ -28,50 +26,29 @@
, fOverdraw(false)
, fColorMode(0) {
// create surface
-#if SK_SUPPORT_GPU
GrContextOptions grContextOpts;
fContextFactory = new GrContextFactory(grContextOpts);
-#else
- fContextFactory = nullptr;
-#endif
}
Request::~Request() {
-#if SK_SUPPORT_GPU
if (fContextFactory) {
delete fContextFactory;
}
-#endif
-}
-
-SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) {
- SkBitmap* bmp = new SkBitmap();
- if (!bmp->tryAllocPixels(canvas->imageInfo()) || !canvas->readPixels(*bmp, 0, 0)) {
- fprintf(stderr, "Can't read pixels\n");
- delete bmp;
- return nullptr;
- }
- return bmp;
}
sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
// capture pixels
- std::unique_ptr<SkBitmap> bmp(this->getBitmapFromCanvas(canvas));
- SkASSERT(bmp);
-
- // Convert to format suitable for PNG output
- sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bmp);
- SkASSERT(encodedBitmap.get());
+ SkBitmap bmp;
+ bmp.allocPixels(canvas->imageInfo());
+ SkAssertResult(canvas->readPixels(bmp, 0, 0));
// write to an opaque png (black background)
SkDynamicMemoryWStream buffer;
- SkDrawCommand::WritePNG(encodedBitmap->bytes(), bmp->width(), bmp->height(),
- buffer, true);
+ DrawCommand::WritePNG(bmp, buffer);
return buffer.detachAsData();
}
SkCanvas* Request::getCanvas() {
-#if SK_SUPPORT_GPU
GrContextFactory* factory = fContextFactory;
GLTestContext* gl = factory->getContextInfo(GrContextFactory::kGL_ContextType,
GrContextFactory::ContextOverrides::kNone).glContext();
@@ -79,14 +56,9 @@
gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
GrContextFactory::ContextOverrides::kNone).glContext();
}
- if (!gl) {
- gl = factory->getContextInfo(GrContextFactory::kMESA_ContextType,
- GrContextFactory::ContextOverrides::kNone).glContext();
- }
if (gl) {
gl->makeCurrent();
}
-#endif
SkASSERT(fDebugCanvas);
// create the appropriate surface if necessary
@@ -97,14 +69,9 @@
return target;
}
-void Request::drawToCanvas(int n, int m) {
- SkCanvas* target = this->getCanvas();
- fDebugCanvas->drawTo(target, n, m);
-}
-
sk_sp<SkData> Request::drawToPng(int n, int m) {
//fDebugCanvas->setOverdrawViz(true);
- this->drawToCanvas(n, m);
+ fDebugCanvas->drawTo(this->getCanvas(), n, m);
//fDebugCanvas->setOverdrawViz(false);
return writeCanvasToPng(this->getCanvas());
}
@@ -118,32 +85,17 @@
fDebugCanvas->draw(canvas);
- sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
-
- SkDynamicMemoryWStream outStream;
-
- sk_sp<SkPixelSerializer> serializer = sk_tool_utils::MakePixelSerializer();
- picture->serialize(&outStream, serializer.get());
-
- return outStream.detachAsData();
+ return recorder.finishRecordingAsPicture()->serialize();
}
GrContext* Request::getContext() {
-#if SK_SUPPORT_GPU
GrContext* result = fContextFactory->get(GrContextFactory::kGL_ContextType,
GrContextFactory::ContextOverrides::kNone);
if (!result) {
result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
GrContextFactory::ContextOverrides::kNone);
}
- if (!result) {
- result = fContextFactory->get(GrContextFactory::kMESA_ContextType,
- GrContextFactory::ContextOverrides::kNone);
- }
return result;
-#else
- return nullptr;
-#endif
}
SkIRect Request::getBounds() {
@@ -151,11 +103,9 @@
if (fPicture) {
bounds = fPicture->cullRect().roundOut();
if (fGPUEnabled) {
-#if SK_SUPPORT_GPU
- int maxRTSize = this->getContext()->caps()->maxRenderTargetSize();
+ int maxRTSize = this->getContext()->maxRenderTargetSize();
bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
SkTMin(bounds.height(), maxRTSize));
-#endif
}
} else {
bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
@@ -189,8 +139,8 @@
auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
? SkColorSpace::MakeSRGBLinear()
: SkColorSpace::MakeSRGB();
- SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
- kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
+ SkImageInfo info = SkImageInfo::Make(bounds.size(), cap.fColorType, kPremul_SkAlphaType,
+ cap.fSRGB ? colorSpace : nullptr);
return SkSurface::MakeRaster(info).release();
}
@@ -201,8 +151,8 @@
auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
? SkColorSpace::MakeSRGBLinear()
: SkColorSpace::MakeSRGB();
- SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
- kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
+ SkImageInfo info = SkImageInfo::Make(bounds.size(), cap.fColorType, kPremul_SkAlphaType,
+ cap.fSRGB ? colorSpace : nullptr);
SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
return surface;
}
@@ -254,7 +204,7 @@
// pour picture into debug canvas
SkIRect bounds = this->getBounds();
- fDebugCanvas.reset(new SkDebugCanvas(bounds.width(), bounds.height()));
+ fDebugCanvas.reset(new DebugCanvas(bounds.width(), bounds.height()));
fDebugCanvas->drawPicture(fPicture);
// for some reason we need to 'flush' the debug canvas by drawing all of the ops
@@ -265,25 +215,29 @@
sk_sp<SkData> Request::getJsonOps(int n) {
SkCanvas* canvas = this->getCanvas();
- Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas);
- root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu");
- root["drawGpuOpBounds"] = Json::Value(fDebugCanvas->getDrawGpuOpBounds());
- root["colorMode"] = Json::Value(fColorMode);
SkDynamicMemoryWStream stream;
- stream.writeText(Json::FastWriter().write(root).c_str());
+ SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
+ writer.beginObject(); // root
+ writer.appendString("mode", fGPUEnabled ? "gpu" : "cpu");
+ writer.appendBool("drawGpuOpBounds", fDebugCanvas->getDrawGpuOpBounds());
+ writer.appendS32("colorMode", fColorMode);
+ fDebugCanvas->toJSON(writer, fUrlDataManager, n, canvas);
+
+ writer.endObject(); // root
+ writer.flush();
return stream.detachAsData();
}
-sk_sp<SkData> Request::getJsonOpList(int n) {
+sk_sp<SkData> Request::getJsonOpsTask(int n) {
SkCanvas* canvas = this->getCanvas();
SkASSERT(fGPUEnabled);
-
- Json::Value result = fDebugCanvas->toJSONOpList(n, canvas);
-
SkDynamicMemoryWStream stream;
- stream.writeText(Json::FastWriter().write(result).c_str());
+ SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
+ fDebugCanvas->toJSONOpsTask(writer, n, canvas);
+
+ writer.flush();
return stream.detachAsData();
}
@@ -296,29 +250,27 @@
fDebugCanvas->drawTo(canvas, n);
// make some json
+ SkDynamicMemoryWStream stream;
+ SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
+
SkMatrix vm = fDebugCanvas->getCurrentMatrix();
SkIRect clip = fDebugCanvas->getCurrentClip();
- Json::Value info(Json::objectValue);
- info["ViewMatrix"] = SkDrawCommand::MakeJsonMatrix(vm);
- info["ClipRect"] = SkDrawCommand::MakeJsonIRect(clip);
- std::string json = Json::FastWriter().write(info);
+ writer.beginObject(); // root
+ writer.appendName("ViewMatrix");
+ DrawCommand::MakeJsonMatrix(writer, vm);
+ writer.appendName("ClipRect");
+ DrawCommand::MakeJsonIRect(writer, clip);
+ writer.endObject(); // root
- // We don't want the null terminator so strlen is correct
- return SkData::MakeWithCopy(json.c_str(), strlen(json.c_str()));
+ // TODO: Old code explicitly avoided the null terminator in the returned data. Important?
+ writer.flush();
+ return stream.detachAsData();
}
SkColor Request::getPixel(int x, int y) {
- SkCanvas* canvas = this->getCanvas();
- canvas->flush();
- std::unique_ptr<SkBitmap> bitmap(this->getBitmapFromCanvas(canvas));
- SkASSERT(bitmap);
-
- // Convert to format suitable for inspection
- sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bitmap);
- SkASSERT(encodedBitmap);
-
- const uint8_t* start = encodedBitmap->bytes() + ((y * bitmap->width() + x) * 4);
- SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]);
- return result;
+ SkBitmap bmp;
+ bmp.allocPixels(this->getCanvas()->imageInfo().makeWH(1, 1));
+ SkAssertResult(this->getCanvas()->readPixels(bmp, x, y));
+ return bmp.getColor(0, 0);
}
diff --git a/src/third_party/skia/tools/skiaserve/Request.h b/src/third_party/skia/tools/skiaserve/Request.h
index 7f41748..e3dfada 100644
--- a/src/third_party/skia/tools/skiaserve/Request.h
+++ b/src/third_party/skia/tools/skiaserve/Request.h
@@ -8,18 +8,16 @@
#ifndef Request_DEFINED
#define Request_DEFINED
-#include "SkTypes.h"
+#include "include/core/SkTypes.h"
-#if SK_SUPPORT_GPU
-#include "GrContextFactory.h"
-#endif
+#include "tools/gpu/GrContextFactory.h"
-#include "SkDebugCanvas.h"
-#include "SkPicture.h"
-#include "SkStream.h"
-#include "SkSurface.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "tools/debugger/DebugCanvas.h"
-#include "UrlDataManager.h"
+#include "tools/UrlDataManager.h"
namespace sk_gpu_test {
class GrContextFactory;
@@ -41,7 +39,6 @@
sk_sp<SkData> drawToPng(int n, int m = -1);
sk_sp<SkData> writeOutSkp();
SkCanvas* getCanvas();
- SkBitmap* getBitmapFromCanvas(SkCanvas* canvas);
bool enableGPU(bool enable);
bool setOverdraw(bool enable);
bool setColorMode(int mode);
@@ -54,7 +51,7 @@
sk_sp<SkData> getJsonOps(int n);
// Returns a json list of ops as an SkData
- sk_sp<SkData> getJsonOpList(int n);
+ sk_sp<SkData> getJsonOpsTask(int n);
// Returns json with the viewMatrix and clipRect
sk_sp<SkData> getJsonInfo(int n);
@@ -63,12 +60,11 @@
SkColor getPixel(int x, int y);
UploadContext* fUploadContext;
- std::unique_ptr<SkDebugCanvas> fDebugCanvas;
+ std::unique_ptr<DebugCanvas> fDebugCanvas;
UrlDataManager fUrlDataManager;
private:
sk_sp<SkData> writeCanvasToPng(SkCanvas* canvas);
- void drawToCanvas(int n, int m = -1);
SkSurface* createCPUSurface();
SkSurface* createGPUSurface();
SkIRect getBounds();
diff --git a/src/third_party/skia/tools/skiaserve/Response.cpp b/src/third_party/skia/tools/skiaserve/Response.cpp
index 61470f1..d74963a 100644
--- a/src/third_party/skia/tools/skiaserve/Response.cpp
+++ b/src/third_party/skia/tools/skiaserve/Response.cpp
@@ -5,17 +5,17 @@
* found in the LICENSE file.
*/
-#include "Response.h"
+#include "tools/skiaserve/Response.h"
+
+#include "tools/skiaserve/Request.h"
+
+#include "include/core/SkData.h"
+#include "include/core/SkString.h"
+#include "tools/flags/CommandLineFlags.h"
#include "microhttpd.h"
-#include "Request.h"
-
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkString.h"
-
-DEFINE_string(source, "https://debugger.skia.org", "Where to load the web UI from.");
+static DEFINE_string(source, "https://debugger-assets.skia.org", "Where to load the web UI from.");
static SkString generate_template(SkString source) {
SkString debuggerTemplate;
@@ -24,18 +24,18 @@
"<html>\n"
"<head>\n"
" <title>SkDebugger</title>\n"
- " <meta charset=\"utf-8\" />\n"
- " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\n"
- " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
- " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n"
- " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n"
- " <link rel='shortcut icon' href='https://debugger.skia.org/res/img/favicon.ico' type='image/x-icon'/ >"
+ " <meta charset='utf-8' />\n"
+ " <meta http-equiv='X-UA-Compatible' content='IE=egde,chrome=1'>\n"
+ " <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n"
+ " <script src='%s/res/js/core.js' type='text/javascript' charset='utf-8'></script>\n"
+ " <link href='%s/res/vul/elements.html' rel='import' />\n"
+ " <link rel='shortcut icon' href='%s/res/img/favicon.ico' type='image/x-icon'/ >"
"</head>\n"
- "<body class=\"fullbleed layout vertical\">\n"
+ "<body class='fullbleed layout vertical'>\n"
" <debugger-app-sk>This is the app."
" </debugger-app-sk>\n"
"</body>\n"
- "</html>", source.c_str(), source.c_str());
+ "</html>", source.c_str(), source.c_str(), source.c_str());
return debuggerTemplate;
}
diff --git a/src/third_party/skia/tools/skiaserve/skiaserve.cpp b/src/third_party/skia/tools/skiaserve/skiaserve.cpp
index 29dd1b4..0a64db7 100644
--- a/src/third_party/skia/tools/skiaserve/skiaserve.cpp
+++ b/src/third_party/skia/tools/skiaserve/skiaserve.cpp
@@ -5,16 +5,16 @@
* found in the LICENSE file.
*/
-#include "Request.h"
-#include "Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
-#include "SkCommandLineFlags.h"
-#include "SkGraphics.h"
+#include "include/core/SkGraphics.h"
+#include "tools/flags/CommandLineFlags.h"
+
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "urlhandlers/UrlHandler.h"
-
#include <errno.h>
#if !defined _WIN32
@@ -24,9 +24,9 @@
using namespace Response;
-DEFINE_int32(port, 8888, "The port to listen on.");
-DEFINE_string(address, "127.0.0.1", "The address to bind to.");
-DEFINE_bool(hosted, false, "Running in hosted mode on debugger.skia.org.");
+static DEFINE_int(port, 8888, "The port to listen on.");
+static DEFINE_string(address, "127.0.0.1", "The address to bind to.");
+static DEFINE_bool(hosted, false, "Running in hosted mode on debugger.skia.org.");
class UrlManager {
public:
@@ -110,7 +110,7 @@
&answer_to_connection, &request,
MHD_OPTION_SOCK_ADDR, &address,
MHD_OPTION_END);
- if (NULL == daemon) {
+ if (nullptr == daemon) {
SkDebugf("Could not initialize daemon\n");
return 1;
}
@@ -133,7 +133,7 @@
#if !defined SK_BUILD_FOR_IOS
int main(int argc, char** argv) {
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::Parse(argc, argv);
return skiaserve_main();
}
#endif
diff --git a/src/third_party/skia/tools/skiaserve/tester/tester.py b/src/third_party/skia/tools/skiaserve/tester/tester.py
index b99529c..9bf4c51 100644
--- a/src/third_party/skia/tools/skiaserve/tester/tester.py
+++ b/src/third_party/skia/tools/skiaserve/tester/tester.py
@@ -57,7 +57,7 @@
def post(self):
with open(self.skp, 'rb') as payload:
files = {'file': payload}
-
+
# upload skp
return Check(requests.post(self.url + '/new', files=files))
@@ -73,7 +73,7 @@
def enable_gpu(self):
return Check(requests.post(self.url + '/enableGPU/1'))
-
+
def disable_gpu(self):
return Check(requests.post(self.url + '/enableGPU/0'))
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/BreakHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/BreakHandler.cpp
index f4f741f..5013c6d 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/BreakHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/BreakHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
@@ -47,15 +47,15 @@
request->fDebugCanvas->getDrawCommandAt(i)->execute(canvas);
}
SkColor target = request->getPixel(x, y);
- Json::Value response(Json::objectValue);
- Json::Value startColor(Json::arrayValue);
- startColor.append(Json::Value(SkColorGetR(target)));
- startColor.append(Json::Value(SkColorGetG(target)));
- startColor.append(Json::Value(SkColorGetB(target)));
- startColor.append(Json::Value(SkColorGetA(target)));
- response["startColor"] = startColor;
- response["endColor"] = startColor;
- response["endOp"] = Json::Value(n);
+
+ SkDynamicMemoryWStream stream;
+ SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
+ writer.beginObject(); // root
+
+ writer.appendName("startColor");
+ DrawCommand::MakeJsonColor(writer, target);
+
+ bool changed = false;
for (int i = n + 1; i < n + count; ++i) {
int index = i % count;
if (index == 0) {
@@ -67,18 +67,21 @@
request->fDebugCanvas->getDrawCommandAt(index)->execute(canvas);
SkColor current = request->getPixel(x, y);
if (current != target) {
- Json::Value endColor(Json::arrayValue);
- endColor.append(Json::Value(SkColorGetR(current)));
- endColor.append(Json::Value(SkColorGetG(current)));
- endColor.append(Json::Value(SkColorGetB(current)));
- endColor.append(Json::Value(SkColorGetA(current)));
- response["endColor"] = endColor;
- response["endOp"] = Json::Value(index);
+ writer.appendName("endColor");
+ DrawCommand::MakeJsonColor(writer, current);
+ writer.appendS32("endOp", index);
+ changed = true;
break;
}
}
+ if (!changed) {
+ writer.appendName("endColor");
+ DrawCommand::MakeJsonColor(writer, target);
+ writer.appendS32("endOp", n);
+ }
canvas->restoreToCount(saveCount);
- SkDynamicMemoryWStream stream;
- stream.writeText(Json::FastWriter().write(response).c_str());
+
+ writer.endObject(); // root
+ writer.flush();
return SendData(connection, stream.detachAsData().get(), "application/json");
}
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/ClipAlphaHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/ClipAlphaHandler.cpp
index a931f93..3032eee 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/ClipAlphaHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/ClipAlphaHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/CmdHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/CmdHandler.cpp
index c8ec82d..fa78766 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/CmdHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/CmdHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/ColorModeHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/ColorModeHandler.cpp
index 25cdf7d..a4c308d 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/ColorModeHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/ColorModeHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/DataHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/DataHandler.cpp
index 83a9be4..8df8288 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/DataHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/DataHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/DownloadHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/DownloadHandler.cpp
index 17bf867..6f344bd 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/DownloadHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/DownloadHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/EnableGPUHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/EnableGPUHandler.cpp
index 7364ef0..a458cad 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/EnableGPUHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/EnableGPUHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/ImgHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/ImgHandler.cpp
index 659c215..652b619 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/ImgHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/ImgHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/InfoHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/InfoHandler.cpp
index 9335458..d276605 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/InfoHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/InfoHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/OpBoundsHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/OpBoundsHandler.cpp
index e9a120f..94f4e6b 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/OpBoundsHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/OpBoundsHandler.cpp
@@ -5,10 +5,10 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
#include "microhttpd.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/OpsHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/OpsHandler.cpp
index 852c526..0c55419 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/OpsHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/OpsHandler.cpp
@@ -5,10 +5,10 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
#include "microhttpd.h"
using namespace Response;
@@ -31,7 +31,7 @@
if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) {
int n = request->getLastOp();
- sk_sp<SkData> data(request->getJsonOpList(n));
+ sk_sp<SkData> data(request->getJsonOpsTask(n));
return SendData(connection, data.get(), "application/json");
}
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/OverdrawHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/OverdrawHandler.cpp
index 7f8c404..e7441aa 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/OverdrawHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/OverdrawHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/PostHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/PostHandler.cpp
index 634a2e5..22b8b50 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/PostHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/PostHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/QuitHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/QuitHandler.cpp
index fa8045c..230a0f8 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/QuitHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/QuitHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/RootHandler.cpp b/src/third_party/skia/tools/skiaserve/urlhandlers/RootHandler.cpp
index 647c198..3ff04fe 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/RootHandler.cpp
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/RootHandler.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "UrlHandler.h"
+#include "tools/skiaserve/urlhandlers/UrlHandler.h"
#include "microhttpd.h"
-#include "../Request.h"
-#include "../Response.h"
+#include "tools/skiaserve/Request.h"
+#include "tools/skiaserve/Response.h"
using namespace Response;
diff --git a/src/third_party/skia/tools/skiaserve/urlhandlers/UrlHandler.h b/src/third_party/skia/tools/skiaserve/urlhandlers/UrlHandler.h
index 95fa476..eb17b5c 100644
--- a/src/third_party/skia/tools/skiaserve/urlhandlers/UrlHandler.h
+++ b/src/third_party/skia/tools/skiaserve/urlhandlers/UrlHandler.h
@@ -7,7 +7,7 @@
#ifndef UrlHandler_DEFINED
#define UrlHandler_DEFINED
-#include "SkColor.h"
+#include "include/core/SkColor.h"
struct MHD_Connection;
struct Request;
diff --git a/src/third_party/skia/tools/skottie-wasm-perf/Makefile b/src/third_party/skia/tools/skottie-wasm-perf/Makefile
new file mode 100644
index 0000000..7863cdf
--- /dev/null
+++ b/src/third_party/skia/tools/skottie-wasm-perf/Makefile
@@ -0,0 +1,2 @@
+serve:
+ python -m SimpleHTTPServer 8004
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skottie-wasm-perf/package.json b/src/third_party/skia/tools/skottie-wasm-perf/package.json
new file mode 100644
index 0000000..fbbf162
--- /dev/null
+++ b/src/third_party/skia/tools/skottie-wasm-perf/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "skottie-wasm-perf",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "dependencies": {
+ "command-line-args": "^5.0.2",
+ "command-line-usage": "^5.0.3",
+ "express": "^4.16.3",
+ "lottie-web": "5.2.1",
+ "node-fetch": "^2.2.0",
+ "puppeteer": "~1.17.0"
+ },
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC"
+}
diff --git a/src/third_party/skia/tools/skottie-wasm-perf/parse_perf_csvs.py b/src/third_party/skia/tools/skottie-wasm-perf/parse_perf_csvs.py
new file mode 100644
index 0000000..89d27cd
--- /dev/null
+++ b/src/third_party/skia/tools/skottie-wasm-perf/parse_perf_csvs.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python2
+#
+# Copyright 2019 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Helper script that takes as input 2 CSVs downloaded from perf.skia.org and
+# outputs a CSV with test_name, avg_value1 (from CSV1), avg_value2 (from CSV2),
+# perc_diff between avg_value1 and avg_value2.
+# This script also discards NUM_OUTLIERS_TO_REMOVE min values and
+# NUM_OUTLIERS_TO_REMOVE max values.
+
+
+import csv
+import optparse
+import sys
+import re
+
+
+MISSING_STR = 'N/A'
+NUM_OUTLIERS_TO_REMOVE = 2
+
+
+def read_from_csv(csv_file):
+ test_to_avg = {}
+ with open(csv_file, 'rb') as f:
+ csv_reader = csv.reader(f, delimiter=',')
+ # First row should contain headers. Validate that it does.
+ header_row = csv_reader.next()
+ if header_row[0] != 'id':
+ raise Exception('%s in unexpected format' % csv_file)
+ p = re.compile('^.*,test=(.*),$')
+ for v in csv_reader:
+ # Extract the test name.
+ result = p.search(v[0])
+ test_name = result.group(1)
+
+ vals = [float(i) for i in v[1:]]
+ vals.sort()
+ # Discard outliers.
+ vals = vals[NUM_OUTLIERS_TO_REMOVE:-NUM_OUTLIERS_TO_REMOVE]
+ # Find the avg val.
+ avg_val = reduce(lambda x, y: x+y, vals) / float(len(vals))
+ test_to_avg[test_name] = avg_val
+ return test_to_avg
+
+
+def combine_results(d1, d2):
+ test_to_result = {}
+ for test1, v1 in d1.items():
+ v2 = d2.get(test1, MISSING_STR)
+ perc_diff = MISSING_STR
+ if v2 != MISSING_STR:
+ diff = v2 - v1
+ avg = (v2 + v1)/2
+ perc_diff = 0 if avg == 0 else diff/avg * 100
+ result = {
+ 'test_name': test1,
+ 'csv1': v1,
+ 'csv2': v2,
+ 'perc_diff': perc_diff,
+ }
+ test_to_result[test1] = result
+
+ # Also add keys in d2 and not d1.
+ for test2, v2 in d2.items():
+ if test2 in test_to_result:
+ continue
+ test_to_result[test2] = {
+ 'test_name': test2,
+ 'csv1': MISSING_STR,
+ 'csv2': v2,
+ 'perc_diff': MISSING_STR,
+ }
+
+ return test_to_result
+
+
+def write_to_csv(output_dict, output_csv):
+ with open(output_csv, 'w') as f:
+ fieldnames = ['test_name', 'csv1', 'csv2', 'perc_diff']
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
+ writer.writeheader()
+ tests = output_dict.keys()
+ tests.sort()
+ for test in tests:
+ writer.writerow(output_dict[test])
+
+
+def parse_and_output(csv1, csv2, output_csv):
+ test_to_avg1 = read_from_csv(csv1)
+ test_to_avg2 = read_from_csv(csv2)
+ output_dict = combine_results(test_to_avg1, test_to_avg2)
+ write_to_csv(output_dict, output_csv)
+
+
+def main():
+ option_parser = optparse.OptionParser()
+ option_parser.add_option(
+ '', '--csv1', type=str,
+ help='The first CSV to parse.')
+ option_parser.add_option(
+ '', '--csv2', type=str,
+ help='The second CSV to parse.')
+ option_parser.add_option(
+ '', '--output_csv', type=str,
+ help='The file to write the output CSV to.')
+ options, _ = option_parser.parse_args()
+ sys.exit(parse_and_output(options.csv1, options.csv2, options.output_csv))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html b/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html
new file mode 100644
index 0000000..2d53a73
--- /dev/null
+++ b/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Skottie-WASM Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="res/canvaskit.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+ <main>
+ <canvas id=anim width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ (function() {
+ const PATH = '/res/lottie.json';
+
+ let lottieJSON = null;
+ let CK = null;
+
+ CanvasKitInit({
+ locateFile: (file) => '/res/'+file,
+ }).ready().then((CanvasKit) => {
+ CK = CanvasKit;
+ Bench(CK, lottieJSON);
+ });
+
+ fetch(PATH).then((resp) => {
+ resp.text().then((json) => {
+ lottieJSON = json;
+ Bench(CK, lottieJSON);
+ });
+ });
+ })();
+
+ const maxFrames = 25;
+ const maxLoops = 5;
+
+ function Bench(CK, json) {
+ if (!CK || !json) {
+ return;
+ }
+
+ const animation = CK.MakeManagedAnimation(json, null);
+ if (!animation) {
+ console.error('Could not process JSON');
+ return
+ }
+
+ const surface = CK.MakeCanvasSurface("anim");
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+ const canvas = surface.getCanvas();
+
+ let c = document.getElementById('anim');
+ // If CanvasKit was unable to instantiate a WebGL context, it will fallback
+ // to CPU and add a ck-replaced class to the canvas element.
+ window._gpu = CK.gpu && !c.classList.contains('ck-replaced');
+
+ const t_rate = 1.0 / (maxFrames-1);
+ let seek = 0;
+ let frame = 0;
+ let loop = 0;
+ const drawFrame = () => {
+ if (frame >= maxFrames) {
+ // Reached the end of one loop.
+ loop++;
+ if (loop == maxLoops) {
+ // These are global variables to talk with puppeteer.
+ window._skottieDone = true;
+ return;
+ }
+ // Reset frame and seek to restart the loop.
+ frame = 0;
+ seek = 0;
+ }
+
+ let damage = animation.seek(seek);
+ if (damage.fRight > damage.fLeft && damage.fBottom > damage.fTop) {
+ animation.render(canvas, {
+ fLeft: 0,
+ fTop: 0,
+ fRight: 1000,
+ fBottom: 1000
+ });
+ surface.flush();
+ }
+ console.log("Used seek: " + seek);
+ seek += t_rate;
+ frame++;
+ window.requestAnimationFrame(drawFrame);
+ };
+ window.requestAnimationFrame(drawFrame);
+ }
+ </script>
+</body>
+</html>
diff --git a/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js b/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js
new file mode 100644
index 0000000..3f25ae4
--- /dev/null
+++ b/src/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js
@@ -0,0 +1,179 @@
+/**
+ * Command line application to run Skottie-WASM perf on a Lottie file in the
+ * browser and then exporting the result.
+ *
+ */
+const puppeteer = require('puppeteer');
+const express = require('express');
+const fs = require('fs');
+const commandLineArgs = require('command-line-args');
+const commandLineUsage= require('command-line-usage');
+const fetch = require('node-fetch');
+
+const opts = [
+ {
+ name: 'canvaskit_js',
+ typeLabel: '{underline file}',
+ description: 'The path to canvaskit.js.'
+ },
+ {
+ name: 'canvaskit_wasm',
+ typeLabel: '{underline file}',
+ description: 'The path to canvaskit.wasm.'
+ },
+ {
+ name: 'input',
+ typeLabel: '{underline file}',
+ description: 'The Lottie JSON file to process.'
+ },
+ {
+ name: 'output',
+ typeLabel: '{underline file}',
+ description: 'The perf file to write. Defaults to perf.json',
+ },
+ {
+ name: 'use_gpu',
+ description: 'Whether we should run in non-headless mode with GPU.',
+ type: Boolean,
+ },
+ {
+ name: 'port',
+ description: 'The port number to use, defaults to 8081.',
+ type: Number,
+ },
+ {
+ name: 'help',
+ alias: 'h',
+ type: Boolean,
+ description: 'Print this usage guide.'
+ },
+];
+
+const usage = [
+ {
+ header: 'Skottie WASM Perf',
+ content: "Command line application to run Skottie-WASM perf."
+ },
+ {
+ header: 'Options',
+ optionList: opts,
+ },
+];
+
+// Parse and validate flags.
+const options = commandLineArgs(opts);
+
+if (!options.output) {
+ options.output = 'perf.json';
+}
+if (!options.port) {
+ options.port = 8081;
+}
+
+if (options.help) {
+ console.log(commandLineUsage(usage));
+ process.exit(0);
+}
+
+if (!options.canvaskit_js) {
+ console.error('You must supply path to canvaskit.js.');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+if (!options.canvaskit_wasm) {
+ console.error('You must supply path to canvaskit.wasm.');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+if (!options.input) {
+ console.error('You must supply a Lottie JSON filename.');
+ console.log(commandLineUsage(usage));
+ process.exit(1);
+}
+
+// Start up a web server to serve the three files we need.
+let canvasKitJS = fs.readFileSync(options.canvaskit_js, 'utf8');
+let canvasKitWASM = fs.readFileSync(options.canvaskit_wasm, 'binary');
+let driverHTML = fs.readFileSync('skottie-wasm-perf.html', 'utf8');
+let lottieJSON = fs.readFileSync(options.input, 'utf8');
+
+const app = express();
+app.get('/', (req, res) => res.send(driverHTML));
+app.get('/res/canvaskit.wasm', function(req, res) {
+ res.type('application/wasm');
+ res.send(new Buffer(canvasKitWASM, 'binary'));
+});
+app.get('/res/canvaskit.js', (req, res) => res.send(canvasKitJS));
+app.get('/res/lottie.json', (req, res) => res.send(lottieJSON));
+app.listen(options.port, () => console.log('- Local web server started.'))
+
+// Utility function.
+async function wait(ms) {
+ await new Promise(resolve => setTimeout(() => resolve(), ms));
+ return ms;
+}
+
+const targetURL = "http://localhost:" + options.port + "/";
+const viewPort = {width: 1000, height: 1000};
+
+// Drive chrome to load the web page from the server we have running.
+async function driveBrowser() {
+ console.log('- Launching chrome for ' + options.input);
+ let browser;
+ let page;
+ const headless = !options.use_gpu;
+ let browser_args = [
+ '--no-sandbox',
+ '--disable-setuid-sandbox',
+ '--window-size=' + viewPort.width + ',' + viewPort.height,
+ ];
+ if (options.use_gpu) {
+ browser_args.push('--ignore-gpu-blacklist');
+ browser_args.push('--ignore-gpu-blocklist');
+ browser_args.push('--enable-gpu-rasterization');
+ }
+ console.log("Running with headless: " + headless + " args: " + browser_args);
+ try {
+ browser = await puppeteer.launch({headless: headless, args: browser_args});
+ page = await browser.newPage();
+ await page.setViewport(viewPort);
+ } catch (e) {
+ console.log('Could not open the browser.', e);
+ process.exit(1);
+ }
+ console.log("Loading " + targetURL);
+ try {
+ // Start trace.
+ await page.tracing.start({
+ path: options.output,
+ screenshots: false,
+ categories: ["blink", "cc", "gpu"]
+ });
+
+ await page.goto(targetURL, {
+ timeout: 60000,
+ waitUntil: 'networkidle0'
+ });
+
+ console.log('Waiting 60s for run to be done');
+ await page.waitForFunction('window._skottieDone === true', {
+ timeout: 60000,
+ });
+
+ // Stop Trace.
+ await page.tracing.stop();
+ } catch(e) {
+ console.log('Timed out while loading or drawing. Either the JSON file was ' +
+ 'too big or hit a bug.', e);
+ await browser.close();
+ process.exit(1);
+ }
+
+ await browser.close();
+ // Need to call exit() because the web server is still running.
+ process.exit(0);
+}
+
+driveBrowser();
diff --git a/src/third_party/skia/tools/skottie2movie.cpp b/src/third_party/skia/tools/skottie2movie.cpp
new file mode 100644
index 0000000..e12ad3c
--- /dev/null
+++ b/src/third_party/skia/tools/skottie2movie.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "experimental/ffmpeg/SkVideoEncoder.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTime.h"
+#include "modules/skottie/include/Skottie.h"
+#include "modules/skottie/utils/SkottieUtils.h"
+#include "src/utils/SkOSPath.h"
+
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/gpu/GrContextFactory.h"
+
+#include "include/gpu/GrContextOptions.h"
+
+static DEFINE_string2(input, i, "", "skottie animation to render");
+static DEFINE_string2(output, o, "", "mp4 file to create");
+static DEFINE_string2(assetPath, a, "", "path to assets needed for json file");
+static DEFINE_int_2(fps, f, 25, "fps");
+static DEFINE_bool2(verbose, v, false, "verbose mode");
+static DEFINE_bool2(loop, l, false, "loop mode for profiling");
+static DEFINE_int(set_dst_width, 0, "set destination width (height will be computed)");
+static DEFINE_bool2(gpu, g, false, "use GPU for rendering");
+
+static void produce_frame(SkSurface* surf, skottie::Animation* anim, double frame_time) {
+ anim->seekFrameTime(frame_time);
+ surf->getCanvas()->clear(SK_ColorWHITE);
+ anim->render(surf->getCanvas());
+}
+
+struct AsyncRec {
+ SkImageInfo info;
+ SkVideoEncoder* encoder;
+};
+
+int main(int argc, char** argv) {
+ SkGraphics::Init();
+
+ CommandLineFlags::SetUsage("Converts skottie to a mp4");
+ CommandLineFlags::Parse(argc, argv);
+
+ if (FLAGS_input.count() == 0) {
+ SkDebugf("-i input_file.json argument required\n");
+ return -1;
+ }
+
+ auto contextType = sk_gpu_test::GrContextFactory::kGL_ContextType;
+ GrContextOptions grCtxOptions;
+ sk_gpu_test::GrContextFactory factory(grCtxOptions);
+
+ SkString assetPath;
+ if (FLAGS_assetPath.count() > 0) {
+ assetPath.set(FLAGS_assetPath[0]);
+ } else {
+ assetPath = SkOSPath::Dirname(FLAGS_input[0]);
+ }
+ SkDebugf("assetPath %s\n", assetPath.c_str());
+
+ auto animation = skottie::Animation::Builder()
+ .setResourceProvider(skottie_utils::FileResourceProvider::Make(assetPath))
+ .makeFromFile(FLAGS_input[0]);
+ if (!animation) {
+ SkDebugf("failed to load %s\n", FLAGS_input[0]);
+ return -1;
+ }
+
+ SkISize dim = animation->size().toRound();
+ double duration = animation->duration();
+ int fps = FLAGS_fps;
+ if (fps < 1) {
+ fps = 1;
+ } else if (fps > 240) {
+ fps = 240;
+ }
+
+ float scale = 1;
+ if (FLAGS_set_dst_width > 0) {
+ scale = FLAGS_set_dst_width / (float)dim.width();
+ dim = { FLAGS_set_dst_width, SkScalarRoundToInt(scale * dim.height()) };
+ }
+
+ const int frames = SkScalarRoundToInt(duration * fps);
+ const double frame_duration = 1.0 / fps;
+
+ if (FLAGS_verbose) {
+ SkDebugf("Size %dx%d duration %g, fps %d, frame_duration %g\n",
+ dim.width(), dim.height(), duration, fps, frame_duration);
+ }
+
+ SkVideoEncoder encoder;
+
+ GrContext* context = nullptr;
+ sk_sp<SkSurface> surf;
+ sk_sp<SkData> data;
+
+ const auto info = SkImageInfo::MakeN32Premul(dim);
+ do {
+ double loop_start = SkTime::GetSecs();
+
+ if (!encoder.beginRecording(dim, fps)) {
+ SkDEBUGF("Invalid video stream configuration.\n");
+ return -1;
+ }
+
+ // lazily allocate the surfaces
+ if (!surf) {
+ if (FLAGS_gpu) {
+ context = factory.getContextInfo(contextType).grContext();
+ surf = SkSurface::MakeRenderTarget(context,
+ SkBudgeted::kNo,
+ info,
+ 0,
+ GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+ nullptr);
+ if (!surf) {
+ context = nullptr;
+ }
+ }
+ if (!surf) {
+ surf = SkSurface::MakeRaster(info);
+ }
+ surf->getCanvas()->scale(scale, scale);
+ }
+
+ for (int i = 0; i <= frames; ++i) {
+ double ts = i * 1.0 / fps;
+ if (FLAGS_verbose) {
+ SkDebugf("rendering frame %d ts %g\n", i, ts);
+ }
+
+ double normal_time = i * 1.0 / frames;
+ double frame_time = normal_time * duration;
+
+ produce_frame(surf.get(), animation.get(), frame_time);
+
+ AsyncRec asyncRec = { info, &encoder };
+ if (context) {
+ surf->asyncRescaleAndReadPixels(info, {0, 0, info.width(), info.height()},
+ SkSurface::RescaleGamma::kSrc, kNone_SkFilterQuality,
+ [](void* ctx, const void* data, size_t rb) {
+ AsyncRec* rec = (AsyncRec*)ctx;
+ rec->encoder->addFrame({rec->info, data, rb});
+ }, &asyncRec);
+ } else {
+ SkPixmap pm;
+ SkAssertResult(surf->peekPixels(&pm));
+ encoder.addFrame(pm);
+ }
+ }
+ data = encoder.endRecording();
+
+ if (FLAGS_loop) {
+ double loop_dur = SkTime::GetSecs() - loop_start;
+ SkDebugf("recording secs %g, frames %d, recording fps %d\n",
+ loop_dur, frames, (int)(frames / loop_dur));
+ }
+ } while (FLAGS_loop);
+
+ if (FLAGS_output.count() == 0) {
+ SkDebugf("missing -o output_file.mp4 argument\n");
+ return 0;
+ }
+
+ SkFILEWStream ostream(FLAGS_output[0]);
+ if (!ostream.isValid()) {
+ SkDebugf("Can't create output file %s\n", FLAGS_output[0]);
+ return -1;
+ }
+ ostream.write(data->data(), data->size());
+ return 0;
+}
diff --git a/src/third_party/skia/tools/skp/generate_page_set.py b/src/third_party/skia/tools/skp/generate_page_set.py
new file mode 100644
index 0000000..3ca71ba
--- /dev/null
+++ b/src/third_party/skia/tools/skp/generate_page_set.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# Copyright (c) 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Script that generates a page_set for the webpages_playback.py script."""
+
+import jinja2
+import os
+
+
+PAGE_SET_TEMPLATE = 'page_set_template'
+PAGE_SET_DIR = 'page_sets'
+
+
+def main():
+ created_page_sets = []
+ while True:
+ user_agent = raw_input('user agent? (mobile/desktop/tablet): ')
+ url_name = raw_input('URL name? (eg: google): ')
+ url = raw_input('URL? (eg: http://www.google.com): ')
+ comment = raw_input('Reason for adding the URL? (eg: go/skia-skps-3-2019): ')
+
+ with open(PAGE_SET_TEMPLATE) as f:
+ t = jinja2.Template(f.read())
+ subs = {
+ 'user_agent': user_agent,
+ 'url_name': url_name,
+ 'url': url,
+ 'comment': comment,
+ }
+
+ page_set_name = 'skia_%s_%s.py' % (url_name, user_agent)
+ page_set_path = os.path.join(PAGE_SET_DIR, page_set_name)
+ with open(page_set_path, 'w') as f:
+ f.write(t.render(**subs))
+ created_page_sets.append(page_set_path)
+ print '\nPage set has been created in %s\n\n' % page_set_path
+
+ keep_going = raw_input('Do you have more page sets to create? (y/n)')
+ if keep_going != 'y':
+ break
+
+ print '\n\nSummarizing all created page sets:'
+ for page_set_path in created_page_sets:
+ print '* %s' % page_set_path
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/skp/page_set_template b/src/third_party/skia/tools/skp/page_set_template
new file mode 100644
index 0000000..d0d01cf
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_set_template
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class Skia{{ user_agent|capitalize }}Page(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(Skia{{ user_agent|capitalize }}Page, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.Shared{{ user_agent|capitalize }}PageState)
+ self.archive_data_file = 'data/skia_{{url_name}}_{{user_agent}}.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class Skia{{ url_name|capitalize }}{{ user_agent|capitalize }}PageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(Skia{{ url_name|capitalize }}{{ user_agent|capitalize }}PageSet, self).__init__(
+ archive_data_file='data/skia_{{url_name}}_{{user_agent}}.json')
+
+ urls_list = [
+ # {{comment}}
+ '{{url}}',
+ ]
+
+ for url in urls_list:
+ self.AddStory(Skia{{ user_agent|capitalize }}Page(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/__init__.py b/src/third_party/skia/tools/skp/page_sets/__init__.py
new file mode 100644
index 0000000..4a12e35
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_amazon_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_amazon_mobile.py
new file mode 100644
index 0000000..814bb8a
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_amazon_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaBuildbotMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaBuildbotMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_amazon_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaAmazonMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaAmazonMobilePageSet, self).__init__(
+ archive_data_file='data/skia_amazon_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.amazon.com/s?k=nicolas+cage&ref=is_box_',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaBuildbotMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_baidu_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_baidu_mobile.py
new file mode 100644
index 0000000..58dc713
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_baidu_mobile.py
@@ -0,0 +1,41 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_baidu_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaBaiduMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaBaiduMobilePageSet, self).__init__(
+ archive_data_file='data/skia_baidu_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ ('http://www.baidu.com/s?wd=barack+obama&rsv_bp=0&rsv_spt=3&rsv_sug3=9'
+ '&rsv_sug=0&rsv_sug4=3824&rsv_sug1=3&inputT=4920'),
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_booking_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_booking_mobile.py
new file mode 100644
index 0000000..d158bcd
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_booking_mobile.py
@@ -0,0 +1,41 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_booking_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(30)
+
+
+class SkiaBookingMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaBookingMobilePageSet, self).__init__(
+ archive_data_file='data/skia_booking_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ ('http://www.booking.com/searchresults.html?src=searchresults'
+ '&latitude=65.0500&longitude=25.4667'),
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py
new file mode 100644
index 0000000..3db39a4
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_capitalvolkswagen_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(30)
+
+
+class SkiaCapitalvolkswagenMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaCapitalvolkswagenMobilePageSet, self).__init__(
+ archive_data_file='data/skia_capitalvolkswagen_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ ('https://www.capitolvolkswagen.com/new-vehicles/'),
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_carsvg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_carsvg_desktop.py
index 8b9cc05..9e0670a 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_carsvg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_carsvg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_carsvg_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_chalkboard_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_chalkboard_desktop.py
index 5aedcda..d5ebd3d 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_chalkboard_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_chalkboard_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_chalkboard_desktop.json'
@@ -30,8 +30,8 @@
urls_list = [
# Why: from fmalita
- ('http://ie.microsoft.com/testdrive/Performance/Chalkboard/Images/'
- 'Chalkboard.svg'),
+ ('https://testdrive-archive.azurewebsites.net/performance/chalkboard/'
+ 'Images/Chalkboard.svg'),
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_cnn_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_cnn_desktop.py
new file mode 100644
index 0000000..06cd8c3
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_cnn_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_cnn_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaCnnDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaCnnDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_cnn_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://www.cnn.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_cnn_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_cnn_mobile.py
new file mode 100644
index 0000000..63d2f17
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_cnn_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_cnn_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaCnnMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaCnnMobilePageSet, self).__init__(
+ archive_data_file='data/skia_cnn_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://www.cnn.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_cnnarticle_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_cnnarticle_mobile.py
new file mode 100644
index 0000000..5cb8231
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_cnnarticle_mobile.py
@@ -0,0 +1,41 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_cnnarticle_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaCnnarticleMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaCnnarticleMobilePageSet, self).__init__(
+ archive_data_file='data/skia_cnnarticle_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ ('https://www.cnn.com/2019/05/16/entertainment/'
+ 'the-big-bang-theory-series-finale-review/index.html'),
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
index c6ddb63..594faf1 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_css3gradients_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_deviantart_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_deviantart_mobile.py
new file mode 100644
index 0000000..326822d
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_deviantart_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_deviantart_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(45)
+
+
+class SkiaDeviantartMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaDeviantartMobilePageSet, self).__init__(
+ archive_data_file='data/skia_deviantart_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.deviantart.com/whats-hot/',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_digg_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_digg_tablet.py
similarity index 69%
rename from src/third_party/skia/tools/skp/page_sets/skia_digg_nexus10.py
rename to src/third_party/skia/tools/skp/page_sets/skia_digg_tablet.py
index 2d3288f..fe64ceb 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_digg_nexus10.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_digg_tablet.py
@@ -14,22 +14,21 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.Shared10InchTabletPageState)
- self.archive_data_file = 'data/skia_digg_nexus10.json'
+ shared_page_state_class=shared_page_state.SharedTabletPageState)
+ self.archive_data_file = 'data/skia_digg_tablet.json'
def RunNavigateSteps(self, action_runner):
action_runner.Navigate(self.url)
- action_runner.Wait(5)
+ action_runner.Wait(30)
-class SkiaDiggNexus10PageSet(story.StorySet):
-
+class SkiaDiggTabletPageSet(story.StorySet):
""" Pages designed to represent the median, not highly optimized web """
def __init__(self):
- super(SkiaDiggNexus10PageSet, self).__init__(
- archive_data_file='data/skia_digg_nexus10.json')
+ super(SkiaDiggTabletPageSet, self).__init__(
+ archive_data_file='data/skia_digg_tablet.json')
urls_list = [
# Why: from Clank CY.
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_ebay_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_ebay_desktop.py
new file mode 100644
index 0000000..80f41cb
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_ebay_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_ebay_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaEbayDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaEbayDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_ebay_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://www.ebay.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_espn_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_espn_desktop.py
index a7c7e20..aae4e3c 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_espn_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_espn_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_espn_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_facebook_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_facebook_desktop.py
new file mode 100644
index 0000000..7fcb17d
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_facebook_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_facebook_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaFacebookDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaFacebookDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_facebook_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.facebook.com/barackobama',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_facebook_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_facebook_mobile.py
new file mode 100644
index 0000000..77a63ba
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_facebook_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_facebook_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(30)
+
+
+class SkiaFacebookMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaFacebookMobilePageSet, self).__init__(
+ archive_data_file='data/skia_facebook_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://facebook.com/barackobama',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_forecastio_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_forecastio_mobile.py
new file mode 100644
index 0000000..03bd4dd
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_forecastio_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_forecastio_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaForecastioMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaForecastioMobilePageSet, self).__init__(
+ archive_data_file='data/skia_forecastio_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://forecast.io',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_gamedeksiam_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_gamedeksiam_nexus10.py
deleted file mode 100644
index 1f36f1d..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_gamedeksiam_nexus10.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.Shared10InchTabletPageState)
- self.archive_data_file = 'data/skia_gamedeksiam_nexus10.json'
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(5)
-
-
-class SkiaGamedeksiamNexus10PageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaGamedeksiamNexus10PageSet, self).__init__(
- archive_data_file='data/skia_gamedeksiam_nexus10.json')
-
- urls_list = [
- # Why: from Tom W's list.
- 'http://game.deksiam.in.th/',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_gmail_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_gmail_desktop.py
new file mode 100644
index 0000000..2e97800
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_gmail_desktop.py
@@ -0,0 +1,52 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+import os
+
+from page_sets.login_helpers import google_login
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+from telemetry.util import wpr_modes
+
+
+class SkiaBuildbotDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaBuildbotDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_gmail_desktop.json'
+
+ def RunSmoothness(self, action_runner):
+ action_runner.ScrollElement()
+
+ def RunNavigateSteps(self, action_runner):
+ if self.wpr_mode != wpr_modes.WPR_REPLAY:
+ credentials_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'data/credentials.json')
+ google_login.BaseLoginGoogle(action_runner, 'google', credentials_path)
+ action_runner.Wait(10)
+ action_runner.Navigate(self.url)
+ action_runner.Wait(10)
+
+
+class SkiaGmailDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGmailDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_gmail_desktop.json')
+
+ urls_list = [
+ # Why: productivity, top google properties, long email .
+ 'https://mail.google.com/mail/?shva=1#inbox/13ba91194d0b8a2e',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_gmail_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_gmail_nexus10.py
deleted file mode 100644
index 9a3411d..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_gmail_nexus10.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.Shared10InchTabletPageState)
- self.archive_data_file = 'data/skia_gmail_nexus10.json'
- self.credentials = 'google'
-
- def RunSmoothness(self, action_runner):
- action_runner.ScrollElement()
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(10)
-
-
-class SkiaGmailNexus10PageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaGmailNexus10PageSet, self).__init__(
- archive_data_file='data/skia_gmail_nexus10.json')
-
- urls_list = [
- # Why: productivity, top google properties
- 'https://mail.google.com/mail/',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_gmailthread_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_gmailthread_desktop.py
deleted file mode 100644
index 6316b0b..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_gmailthread_desktop.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_gmailthread_desktop.json'
- self.credentials = 'google'
-
- def RunSmoothness(self, action_runner):
- action_runner.ScrollElement()
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(15)
-
-
-class SkiaGmailthreadDesktopPageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaGmailthreadDesktopPageSet, self).__init__(
- archive_data_file='data/skia_gmailthread_desktop.json')
-
- urls_list = [
- # Why: productivity, top google properties, long email thread.
- 'https://mail.google.com/mail/?shva=1#inbox/13ba91194d0b8a2e',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlecalendar_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googlecalendar_desktop.py
new file mode 100644
index 0000000..a21ab7c
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googlecalendar_desktop.py
@@ -0,0 +1,49 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+import os
+
+from page_sets.login_helpers import google_login
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+from telemetry.util import wpr_modes
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_googlecalendar_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ if self.wpr_mode != wpr_modes.WPR_REPLAY:
+ credentials_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ 'data/credentials.json')
+ google_login.BaseLoginGoogle(action_runner, 'google', credentials_path)
+ action_runner.Wait(15)
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGooglecalendarDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGooglecalendarDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_googlecalendar_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.google.com/calendar/',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googledocs_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googledocs_desktop.py
new file mode 100644
index 0000000..24f2ee2
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googledocs_desktop.py
@@ -0,0 +1,50 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+import os
+
+from page_sets.login_helpers import google_login
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+from telemetry.util import wpr_modes
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_googledocs_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ if self.wpr_mode != wpr_modes.WPR_REPLAY:
+ credentials_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ 'data/credentials.json')
+ google_login.BaseLoginGoogle(action_runner, 'google', credentials_path)
+ action_runner.Wait(15)
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGoogledocsDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGoogledocsDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_googledocs_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ ('https://docs.google.com/document/d/'
+ '1X-IKNjtEnx-WW5JIKRLsyhz5sbsat3mfTpAPUSX3_s4/view'),
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlehome_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googlehome_desktop.py
deleted file mode 100644
index 5c5779c..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_googlehome_desktop.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_googlehome_desktop.json'
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(5)
-
-
-class SkiaGooglehomeDesktopPageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaGooglehomeDesktopPageSet, self).__init__(
- archive_data_file='data/skia_googlehome_desktop.json')
-
- urls_list = [
- # Why: top google property; a google tab is often open
- 'http://www.google.com/',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googleimagesearch_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googleimagesearch_desktop.py
new file mode 100644
index 0000000..06599ee
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googleimagesearch_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_googleimagesearch_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGoogleimagesearchDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGoogleimagesearchDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_googleimagesearch_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.google.com/search?q=cats&tbm=isch',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlenews_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_googlenews_mobile.py
new file mode 100644
index 0000000..23956e6
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googlenews_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_googlenews_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGooglenewsMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGooglenewsMobilePageSet, self).__init__(
+ archive_data_file='data/skia_googlenews_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://news.google.com/',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_desktop.py
new file mode 100644
index 0000000..1c828fa
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_googlesearch_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGooglesearchDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGooglesearchDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_googlesearch_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.google.com/#hl=en&q=barack+obama',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_mobile.py
new file mode 100644
index 0000000..5ccb2aa
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googlesearch_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_googlesearch_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaGooglesearchMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaGooglesearchMobilePageSet, self).__init__(
+ archive_data_file='data/skia_googlesearch_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.google.co.uk/search?hl=en&q=barack+obama&cad=h',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_googlespreadsheet_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_googlespreadsheet_desktop.py
index ce65456..ad6bc98 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_googlespreadsheet_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_googlespreadsheet_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_googlespreadsheet_desktop.json'
@@ -31,7 +31,7 @@
urls_list = [
# Why: from Tom W's list.
('https://docs.google.com/spreadsheets/d/'
- '1YnmSPu-p-1nj-lkWd8q_GRgzjiWzg_6A-HvFYqVoVxI/edit?usp=sharing'),
+ '1YnmSPu-p-1nj-lkWd8q_GRgzjiWzg_6A-HvFYqVoVxI/edit#gid=0'),
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_jsfiddlebigcar_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_jsfiddlebigcar_desktop.py
deleted file mode 100644
index 57b14fd..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_jsfiddlebigcar_desktop.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_jsfiddlebigcar_desktop.json'
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(5)
-
-
-class SkiaJsfiddlebigcarDesktopPageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaJsfiddlebigcarDesktopPageSet, self).__init__(
- archive_data_file='data/skia_jsfiddlebigcar_desktop.json')
-
- urls_list = [
- # Why: Page from Chromium's silk test cases
- 'http://jsfiddle.net/vBQHH/3/embedded/result/',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_linkedin_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_linkedin_desktop.py
new file mode 100644
index 0000000..fa7552f
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_linkedin_desktop.py
@@ -0,0 +1,50 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+import os
+
+from page_sets.login_helpers import linkedin_login
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+from telemetry.util import wpr_modes
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_linkedin_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ if self.wpr_mode != wpr_modes.WPR_REPLAY:
+ credentials_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ 'data/credentials.json')
+ linkedin_login.LoginDesktopAccount(action_runner, 'linkedin',
+ credentials_path)
+ action_runner.Wait(15)
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaLinkedinDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaLinkedinDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_linkedin_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.linkedin.com/in/linustorvalds',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_mapsvg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_mapsvg_desktop.py
index a5f7649..e1694c4 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_mapsvg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_mapsvg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_mapsvg_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_mozilla_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_mozilla_tablet.py
similarity index 71%
rename from src/third_party/skia/tools/skp/page_sets/skia_mozilla_nexus10.py
rename to src/third_party/skia/tools/skp/page_sets/skia_mozilla_tablet.py
index be56b4c..3537deb 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_mozilla_nexus10.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_mozilla_tablet.py
@@ -14,23 +14,22 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_mozilla_nexus10.json'
+ shared_page_state_class=shared_page_state.SharedTabletPageState)
+ self.archive_data_file = 'data/skia_mozilla_tablet.json'
def RunNavigateSteps(self, action_runner):
action_runner.Navigate(self.url)
action_runner.Wait(5)
-class SkiaMozillaNexus10PageSet(story.StorySet):
-
+class SkiaMozillaTabletPageSet(story.StorySet):
""" Pages designed to represent the median, not highly optimized web """
def __init__(self):
- super(SkiaMozillaNexus10PageSet, self).__init__(
- archive_data_file='data/skia_mozilla_nexus10.json')
+ super(SkiaMozillaTabletPageSet, self).__init__(
+ archive_data_file='data/skia_mozilla_tablet.json')
urls_list = [
# Why:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_nytimes_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_nytimes_desktop.py
index 6276bdf..9124965 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_nytimes_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_nytimes_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_nytimes_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_pokemonwiki_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_pokemonwiki_desktop.py
index def33eb..3464193 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_pokemonwiki_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_pokemonwiki_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_pokemonwiki_desktop.json'
@@ -33,8 +33,8 @@
archive_data_file='data/skia_pokemonwiki_desktop.json')
urls_list = [
- # Why: http://code.google.com/p/chromium/issues/detail?id=136555
- 'http://en.wikipedia.org/wiki/List_of_Pok%C3%A9mon',
+ # go/skia-skps-3-19
+ 'https://pokemondb.net/pokedex/all',
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_pravda_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_pravda_tablet.py
similarity index 71%
rename from src/third_party/skia/tools/skp/page_sets/skia_pravda_nexus10.py
rename to src/third_party/skia/tools/skp/page_sets/skia_pravda_tablet.py
index 35d042e..944b60b 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_pravda_nexus10.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_pravda_tablet.py
@@ -14,23 +14,22 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.Shared10InchTabletPageState)
- self.archive_data_file = 'data/skia_pravda_nexus10.json'
+ shared_page_state_class=shared_page_state.SharedTabletPageState)
+ self.archive_data_file = 'data/skia_pravda_tablet.json'
def RunNavigateSteps(self, action_runner):
action_runner.Navigate(self.url)
action_runner.Wait(5)
-class SkiaPravdaNexus10PageSet(story.StorySet):
-
+class SkiaPravdaTabletPageSet(story.StorySet):
""" Pages designed to represent the median, not highly optimized web """
def __init__(self):
- super(SkiaPravdaNexus10PageSet, self).__init__(
- archive_data_file='data/skia_pravda_nexus10.json')
+ super(SkiaPravdaTabletPageSet, self).__init__(
+ archive_data_file='data/skia_pravda_tablet.json')
urls_list = [
# Why: cyrillic font test case
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_reddit_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_reddit_mobile.py
new file mode 100644
index 0000000..fe51114
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_reddit_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_reddit_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(30)
+
+
+class SkiaRedditMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaRedditMobilePageSet, self).__init__(
+ archive_data_file='data/skia_reddit_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.reddit.com/r/programming/comments/1g96ve/',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_samoasvg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_samoasvg_desktop.py
index ca2e907..6689ffd 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_samoasvg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_samoasvg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_samoasvg_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_slashdot_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_slashdot_mobile.py
new file mode 100644
index 0000000..08f1b71
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_slashdot_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_slashdot_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaSlashdotMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaSlashdotMobilePageSet, self).__init__(
+ archive_data_file='data/skia_slashdot_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://slashdot.org',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_techcrunch_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_techcrunch_mobile.py
new file mode 100644
index 0000000..16a8937
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_techcrunch_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_techcrunch_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaTechcrunchMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaTechcrunchMobilePageSet, self).__init__(
+ archive_data_file='data/skia_techcrunch_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://techcrunch.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_theverge_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_theverge_desktop.py
index 76f3a92..107e404 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_theverge_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_theverge_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_theverge_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_theverge_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_theverge_mobile.py
new file mode 100644
index 0000000..9e4159a
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_theverge_mobile.py
@@ -0,0 +1,41 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaBuildbotMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaBuildbotMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_theverge_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaThevergeMobilePageSet(story.StorySet):
+
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaThevergeMobilePageSet, self).__init__(
+ archive_data_file='data/skia_theverge_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://theverge.com/',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaBuildbotMobilePage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_tiger8svg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_tiger8svg_desktop.py
index d950a74..b7e7877 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_tiger8svg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_tiger8svg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_tiger8svg_desktop.json'
@@ -34,7 +34,8 @@
urls_list = [
# Why: from skbug.com/4713
- 'http://www.googledrive.com/host/0B5nDjttF0gt9QzJjdjRNVlNvems',
+ ('https://storage.googleapis.com/skia-infra-testdata/images-for-skps/'
+ 'tiger-8.svg'),
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_tigersvg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_tigersvg_desktop.py
index fb40acb..9d14e30 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_tigersvg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_tigersvg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_tigersvg_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_twitter_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_twitter_desktop.py
new file mode 100644
index 0000000..a6f19ae
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_twitter_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_twitter_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaTwitterDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaTwitterDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_twitter_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://twitter.com/katyperry',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_ugamsolutions_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_ugamsolutions_desktop.py
deleted file mode 100644
index 26b643e..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_ugamsolutions_desktop.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_ugamsolutions_desktop.json'
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.Wait(15)
-
-
-class SkiaUgamsolutionsDesktopPageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaUgamsolutionsDesktopPageSet, self).__init__(
- archive_data_file='data/skia_ugamsolutions_desktop.json')
-
- urls_list = [
- # Why: for crbug.com/447291
- 'http://www.ugamsolutions.com',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_unicodetable_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_unicodetable_desktop.py
deleted file mode 100644
index b4c90f0..0000000
--- a/src/third_party/skia/tools/skp/page_sets/skia_unicodetable_desktop.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaBuildbotDesktopPage(page_module.Page):
-
- def __init__(self, url, page_set):
- super(SkiaBuildbotDesktopPage, self).__init__(
- url=url,
- page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.SharedDesktopPageState)
- self.archive_data_file = 'data/skia_unicodetable_desktop.json'
-
- def RunNavigateSteps(self, action_runner):
- action_runner.Navigate(self.url)
- action_runner.ScrollPage(distance=100000)
- action_runner.Wait(20)
-
-
-class SkiaUnicodetableDesktopPageSet(story.StorySet):
-
- """ Pages designed to represent the median, not highly optimized web """
-
- def __init__(self):
- super(SkiaUnicodetableDesktopPageSet, self).__init__(
- archive_data_file='data/skia_unicodetable_desktop.json')
-
- urls_list = [
- # Why: stress tests for fonts (from skia:3574).
- 'http://unicode-table.com/en/',
- ]
-
- for url in urls_list:
- self.AddStory(SkiaBuildbotDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_weather_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_weather_desktop.py
new file mode 100644
index 0000000..5a2ffa3
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_weather_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_weather_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaWeatherDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaWeatherDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_weather_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://weather.com/weather/today/l/94043:4:US',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_desktop.py
index 10bb061..363d697 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_wikipedia_desktop.json'
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_mobile.py
new file mode 100644
index 0000000..28076d2
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_wikipedia_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_wikipedia_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaWikipediaMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaWikipediaMobilePageSet, self).__init__(
+ archive_data_file='data/skia_wikipedia_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://en.wikipedia.org/wiki/Wikipedia',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_worldjournal_nexus10.py b/src/third_party/skia/tools/skp/page_sets/skia_worldjournal_tablet.py
similarity index 67%
rename from src/third_party/skia/tools/skp/page_sets/skia_worldjournal_nexus10.py
rename to src/third_party/skia/tools/skp/page_sets/skia_worldjournal_tablet.py
index 713a4aa..b7d62b8 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_worldjournal_nexus10.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_worldjournal_tablet.py
@@ -14,19 +14,18 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
- shared_page_state_class=shared_page_state.Shared10InchTabletPageState)
- self.archive_data_file = 'data/skia_worldjournal_nexus10.json'
+ shared_page_state_class=shared_page_state.SharedTabletPageState)
+ self.archive_data_file = 'data/skia_worldjournal_tablet.json'
-class SkiaWorldjournalNexus10PageSet(story.StorySet):
-
+class SkiaWorldjournalTabletPageSet(story.StorySet):
""" Pages designed to represent the median, not highly optimized web """
def __init__(self):
- super(SkiaWorldjournalNexus10PageSet, self).__init__(
- archive_data_file='data/skia_worldjournal_nexus10.json')
+ super(SkiaWorldjournalTabletPageSet, self).__init__(
+ archive_data_file='data/skia_worldjournal_tablet.json')
urls_list = [
# Why: Chinese font test case
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_wowwiki_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_wowwiki_desktop.py
index 54e9acb..78ab738 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_wowwiki_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_wowwiki_desktop.py
@@ -14,14 +14,15 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_wowwiki_desktop.json'
def RunNavigateSteps(self, action_runner):
action_runner.Navigate(self.url)
- action_runner.Wait(25)
+ action_runner.ScrollPage(distance=6000000)
+ action_runner.Wait(60)
class SkiaWowwikiDesktopPageSet(story.StorySet):
@@ -33,8 +34,9 @@
archive_data_file='data/skia_wowwiki_desktop.json')
urls_list = [
- # Why: http://code.google.com/p/chromium/issues/detail?id=136555
- 'http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria',
+ # Why: go/skia-skps-3-2019
+ ('https://wowwiki.fandom.com/wiki/World_of_Warcraft:'
+ '_Wrath_of_the_Lich_King'),
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_yahooanswers_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_yahooanswers_desktop.py
new file mode 100644
index 0000000..3204360
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_yahooanswers_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_yahooanswers_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaYahooanswersDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaYahooanswersDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_yahooanswers_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://answers.yahoo.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_yahoosports_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_yahoosports_desktop.py
new file mode 100644
index 0000000..0a7cd79
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_yahoosports_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_yahoosports_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaYahoosportsDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaYahoosportsDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_yahoosports_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://sports.yahoo.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_ynevsvg_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_ynevsvg_desktop.py
index 04acd10..cd63195 100644
--- a/src/third_party/skia/tools/skp/page_sets/skia_ynevsvg_desktop.py
+++ b/src/third_party/skia/tools/skp/page_sets/skia_ynevsvg_desktop.py
@@ -14,8 +14,8 @@
def __init__(self, url, page_set):
super(SkiaBuildbotDesktopPage, self).__init__(
url=url,
+ name=url,
page_set=page_set,
- credentials_path='data/credentials.json',
shared_page_state_class=shared_page_state.SharedDesktopPageState)
self.archive_data_file = 'data/skia_ynevsvg_desktop.json'
@@ -34,7 +34,8 @@
urls_list = [
# Why: from skbug.com/4713
- 'http://www.googledrive.com/host/0B5nDjttF0gt9QjRKdEZ5MEVYc2c',
+ ('https://storage.googleapis.com/skia-infra-testdata/images-for-skps/'
+ 'ynev.svg'),
]
for url in urls_list:
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_youtube_desktop.py b/src/third_party/skia/tools/skp/page_sets/skia_youtube_desktop.py
new file mode 100644
index 0000000..513a067
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_youtube_desktop.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaDesktopPage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaDesktopPage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedDesktopPageState)
+ self.archive_data_file = 'data/skia_youtube_desktop.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaYoutubeDesktopPageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaYoutubeDesktopPageSet, self).__init__(
+ archive_data_file='data/skia_youtube_desktop.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'http://www.youtube.com',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaDesktopPage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/page_sets/skia_youtube_mobile.py b/src/third_party/skia/tools/skp/page_sets/skia_youtube_mobile.py
new file mode 100644
index 0000000..4e23040
--- /dev/null
+++ b/src/third_party/skia/tools/skp/page_sets/skia_youtube_mobile.py
@@ -0,0 +1,40 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=W0401,W0614
+
+
+from telemetry import story
+from telemetry.page import page as page_module
+from telemetry.page import shared_page_state
+
+
+class SkiaMobilePage(page_module.Page):
+
+ def __init__(self, url, page_set):
+ super(SkiaMobilePage, self).__init__(
+ url=url,
+ name=url,
+ page_set=page_set,
+ shared_page_state_class=shared_page_state.SharedMobilePageState)
+ self.archive_data_file = 'data/skia_youtube_mobile.json'
+
+ def RunNavigateSteps(self, action_runner):
+ action_runner.Navigate(self.url)
+ action_runner.Wait(15)
+
+
+class SkiaYoutubeMobilePageSet(story.StorySet):
+ """ Pages designed to represent the median, not highly optimized web """
+
+ def __init__(self):
+ super(SkiaYoutubeMobilePageSet, self).__init__(
+ archive_data_file='data/skia_youtube_mobile.json')
+
+ urls_list = [
+ # go/skia-skps-3-2019
+ 'https://www.youtube.com/watch?v=9hBpF_Zj4OA',
+ ]
+
+ for url in urls_list:
+ self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/src/third_party/skia/tools/skp/webpages_playback.py b/src/third_party/skia/tools/skp/webpages_playback.py
index b800d85..1b5d5f9 100644
--- a/src/third_party/skia/tools/skp/webpages_playback.py
+++ b/src/third_party/skia/tools/skp/webpages_playback.py
@@ -33,11 +33,10 @@
to capture archives and/or capture SKP files. Majority of the time it should be
a newly built chrome binary.
-The --data_store flag controls where the needed artifacts, such as
-credential files, are downloaded from. It also controls where the
-generated artifacts, such as recorded webpages and resulting skp renderings,
-are uploaded to. URLs with scheme 'gs://' use Google Storage. Otherwise
-use local filesystem.
+The --data_store flag controls where the needed artifacts are downloaded from.
+It also controls where the generated artifacts, such as recorded webpages and
+resulting skp renderings, are uploaded to. URLs with scheme 'gs://' use Google
+Storage. Otherwise use local filesystem.
The --upload=True flag means generated artifacts will be
uploaded or copied to the location specified by --data_store. (default value is
@@ -52,6 +51,7 @@
they can be added to the buildbots with no breakages.
"""
+import datetime
import glob
import optparse
import os
@@ -92,14 +92,14 @@
# Dictionary of device to platform prefixes for SKP files.
DEVICE_TO_PLATFORM_PREFIX = {
'desktop': 'desk',
- 'galaxynexus': 'mobi',
- 'nexus10': 'tabl'
+ 'mobile': 'mobi',
+ 'tablet': 'tabl'
}
# How many times the record_wpr binary should be retried.
RETRY_RECORD_WPR_COUNT = 5
# How many times the run_benchmark binary should be retried.
-RETRY_RUN_MEASUREMENT_COUNT = 5
+RETRY_RUN_MEASUREMENT_COUNT = 3
# Location of the credentials.json file in Google Storage.
CREDENTIALS_GS_PATH = 'playback/credentials/credentials.json'
@@ -111,10 +111,20 @@
# Dictionary of supported Chromium page sets to their file prefixes.
CHROMIUM_PAGE_SETS_TO_PREFIX = {
- 'key_mobile_sites_smooth.py': 'keymobi',
- 'top_25_smooth.py': 'top25desk',
}
+PAGE_SETS_TO_EXCLUSIONS = {
+ # See skbug.com/7348
+ 'key_mobile_sites_smooth.py': '"(digg|worldjournal|twitter|espn)"',
+ # See skbug.com/7421
+ 'top_25_smooth.py': '"(mail\.google\.com)"',
+}
+
+
+class InvalidSKPException(Exception):
+ """Raised when the created SKP is invalid."""
+ pass
+
def remove_prefix(s, prefix):
if s.startswith(prefix):
@@ -200,19 +210,14 @@
self.gs.download_file(CREDENTIALS_GS_PATH, CREDENTIALS_FILE_PATH)
if not os.path.isfile(CREDENTIALS_FILE_PATH):
- print """\n\nCould not locate credentials file in the storage.
- Please create a %s file that contains:
+ raise Exception("""Could not locate credentials file in the storage.
+ Please create a credentials file in gs://%s that contains:
{
"google": {
"username": "google_testing_account_username",
"password": "google_testing_account_password"
- },
- "facebook": {
- "username": "facebook_testing_account_username",
- "password": "facebook_testing_account_password"
}
- }\n\n""" % CREDENTIALS_FILE_PATH
- raw_input("Please press a key when you are ready to proceed...")
+ }\n\n""" % CREDENTIALS_GS_PATH)
# Delete any left over data files in the data directory.
for archive_file in glob.glob(
@@ -227,10 +232,12 @@
# Loop through all page_sets.
for page_set in self._page_sets:
-
+ if os.path.basename(page_set) == '__init__.py':
+ continue
page_set_basename = os.path.basename(page_set).split('.')[0]
page_set_json_name = page_set_basename + '.json'
- wpr_data_file = page_set.split(os.path.sep)[-1].split('.')[0] + '_000.wpr'
+ wpr_data_file_glob = (
+ page_set.split(os.path.sep)[-1].split('.')[0] + '_*.wprgo')
page_set_dir = os.path.dirname(page_set)
if self._IsChromiumPageSet(page_set):
@@ -254,9 +261,11 @@
# Copy over the created archive into the local webpages archive
# directory.
- shutil.copy(
- os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file),
- self._local_record_webpages_archive_dir)
+ for wpr_data_file in glob.glob(os.path.join(
+ LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file_glob)):
+ shutil.copy(
+ os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file),
+ self._local_record_webpages_archive_dir)
shutil.copy(
os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
page_set_json_name),
@@ -274,9 +283,9 @@
else:
# Get the webpages archive so that it can be replayed.
- self._DownloadWebpagesArchive(wpr_data_file, page_set_json_name)
+ self._DownloadWebpagesArchive(wpr_data_file_glob, page_set_json_name)
- run_benchmark_cmd = (
+ run_benchmark_cmd = [
'PYTHONPATH=%s:%s:$PYTHONPATH' % (page_set_dir, self._catapult_dir),
'DISPLAY=%s' % X11_DISPLAY,
'timeout', '1800',
@@ -288,28 +297,36 @@
'--page-set-name=%s' % page_set_basename,
'--page-set-base-dir=%s' % page_set_dir,
'--skp-outdir=%s' % TMP_SKP_DIR,
- '--also-run-disabled-tests'
- )
+ '--also-run-disabled-tests',
+ ]
+
+ exclusions = PAGE_SETS_TO_EXCLUSIONS.get(os.path.basename(page_set))
+ if exclusions:
+ run_benchmark_cmd.append('--story-filter-exclude=' + exclusions)
for _ in range(RETRY_RUN_MEASUREMENT_COUNT):
try:
print '\n\n=======Capturing SKP of %s=======\n\n' % page_set
subprocess.check_call(' '.join(run_benchmark_cmd), shell=True)
except subprocess.CalledProcessError:
- # skpicture_printer sometimes fails with AssertionError but the
- # captured SKP is still valid. This is a known issue.
- pass
-
- # Rename generated SKP files into more descriptive names.
- try:
- self._RenameSkpFiles(page_set)
- # Break out of the retry loop since there were no errors.
- break
- except Exception:
# There was a failure continue with the loop.
traceback.print_exc()
print '\n\n=======Retrying %s=======\n\n' % page_set
time.sleep(10)
+ continue
+
+ try:
+ # Rename generated SKP files into more descriptive names.
+ self._RenameSkpFiles(page_set)
+ except InvalidSKPException:
+ # There was a failure continue with the loop.
+ traceback.print_exc()
+ print '\n\n=======Retrying %s=======\n\n' % page_set
+ time.sleep(10)
+ continue
+
+ # Break out of the retry loop since there were no errors.
+ break
else:
# If we get here then run_benchmark did not succeed and thus did not
# break out of the loop.
@@ -362,11 +379,16 @@
print '\n\n=======Uploading to Partner bucket %s =======\n\n' % (
PARTNERS_GS_BUCKET)
partner_gs = GoogleStorageDataStore(PARTNERS_GS_BUCKET)
- partner_gs.delete_path(SKPICTURES_DIR_NAME)
- print 'Uploading %s to %s' % (self._local_skp_dir, SKPICTURES_DIR_NAME)
- partner_gs.upload_dir_contents(self._local_skp_dir, SKPICTURES_DIR_NAME)
+ timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%d')
+ upload_dir = posixpath.join(SKPICTURES_DIR_NAME, timestamp)
+ try:
+ partner_gs.delete_path(upload_dir)
+ except subprocess.CalledProcessError:
+ print 'Cannot delete %s because it does not exist yet.' % upload_dir
+ print 'Uploading %s to %s' % (self._local_skp_dir, upload_dir)
+ partner_gs.upload_dir_contents(self._local_skp_dir, upload_dir)
print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % (
- posixpath.join(partner_gs.target_name(), SKPICTURES_DIR_NAME))
+ posixpath.join(partner_gs.target_name(), upload_dir))
return 0
@@ -400,6 +422,10 @@
Look into the subdirectory of TMP_SKP_DIR and find the most interesting
.skp in there to be this page_set's representative .skp.
+
+ Throws InvalidSKPException if the chosen .skp is less than 1KB. This
+ typically happens when there is a 404 or a redirect loop. Anything greater
+ than 1KB seems to have captured at least some useful information.
"""
subdirs = glob.glob(os.path.join(TMP_SKP_DIR, '*'))
for site in subdirs:
@@ -420,6 +446,11 @@
shutil.move(largest_skp, dest)
self._skp_files.append(filename)
shutil.rmtree(site)
+ skp_size = os.path.getsize(dest)
+ if skp_size < 1024:
+ raise InvalidSKPException(
+ 'Size of %s is only %d. Something is wrong.' % (dest, skp_size))
+
def _CreateLocalStorageDirs(self):
"""Creates required local storage directories for this script."""
@@ -439,9 +470,7 @@
gs = self.gs
if (gs.does_storage_object_exist(wpr_source) and
gs.does_storage_object_exist(page_set_source)):
- gs.download_file(wpr_source,
- os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
- wpr_data_file))
+ gs.download_file(wpr_source, LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR)
gs.download_file(page_set_source,
os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
page_set_json_name))
diff --git a/src/third_party/skia/tools/skp_parser.cpp b/src/third_party/skia/tools/skp_parser.cpp
index 887c50d..595209f 100644
--- a/src/third_party/skia/tools/skp_parser.cpp
+++ b/src/third_party/skia/tools/skp_parser.cpp
@@ -5,17 +5,36 @@
* found in the LICENSE file.
*/
-#include <iostream>
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "include/utils/SkNullCanvas.h"
+#include "tools/debugger/DebugCanvas.h"
-#include "SkDebugCanvas.h"
-#include "SkNullCanvas.h"
-#include "SkStream.h"
+#include <iostream>
#ifdef SK_BUILD_FOR_WIN
#include <fcntl.h>
#include <io.h>
#endif
+/*
+If you execute skp_parser with one argument, it spits out a json representation
+of the skp, but that's incomplete since it's missing many binary blobs (these
+could represent images or typefaces or just anything that doesn't currently
+have a json representation). Each unique blob is labeled with a string in the
+form "data/%d". So for example:
+
+ tools/git-sync-deps
+ bin/gn gen out/debug
+ ninja -C out/debug dm skp_parser
+ out/debug/dm -m grayscale -w /tmp/dm --config skp
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | less
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | grep data
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 | file -
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 > /tmp/data0.png
+
+"data/0" is an image that the SKP serializer has encoded as PNG.
+*/
int main(int argc, char** argv) {
if (argc < 2) {
SkDebugf("Usage:\n %s SKP_FILE [DATA_URL]\n", argv[0]);
@@ -32,12 +51,16 @@
return 3;
}
SkISize size = pic->cullRect().roundOut().size();
- SkDebugCanvas debugCanvas(size.width(), size.height());
+ DebugCanvas debugCanvas(size.width(), size.height());
pic->playback(&debugCanvas);
std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
UrlDataManager dataManager(SkString("data"));
- Json::Value json = debugCanvas.toJSON(
- dataManager, debugCanvas.getSize(), nullCanvas.get());
+ SkDynamicMemoryWStream stream;
+ SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
+ writer.beginObject(); // root
+ debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
+ writer.endObject(); // root
+ writer.flush();
if (argc > 2) {
if (UrlDataManager::UrlData* data =
dataManager.getDataFromUrl(SkString(argv[2]))) {
@@ -53,7 +76,8 @@
return 4;
}
} else {
- Json::StyledStreamWriter(" ").write(std::cout, json);
+ sk_sp<SkData> data = stream.detachAsData();
+ fwrite(data->data(), data->size(), 1, stdout);
}
return 0;
}
diff --git a/src/third_party/skia/tools/skpbench/_adb.py b/src/third_party/skia/tools/skpbench/_adb.py
index 66ef623..9601dcb 100644
--- a/src/third_party/skia/tools/skpbench/_adb.py
+++ b/src/third_party/skia/tools/skpbench/_adb.py
@@ -5,16 +5,18 @@
from __future__ import print_function
import re
+import time
import subprocess
import sys
class Adb:
- def __init__(self, device_serial=None, echo=False):
- self.__invocation = ['adb']
+ def __init__(self, device_serial=None, adb_binary=None, echo=False):
+ self.__invocation = [adb_binary]
if device_serial:
self.__invocation.extend(['-s', device_serial])
self.__echo = echo
self.__is_root = None
+ self.__has_established_connection = False
def shell(self, cmd):
if self.__echo:
@@ -24,6 +26,7 @@
def check(self, cmd):
if self.__echo:
self.__echo_shell_cmd(cmd)
+ self.__establish_connection()
result = subprocess.check_output(self.__invocation + ['shell', cmd])
if self.__echo:
print(result, file=sys.stderr)
@@ -32,7 +35,7 @@
def root(self):
if not self.is_root():
self.__invoke('root')
- self.__invoke('wait-for-device')
+ self.__has_established_connection = False
self.__is_root = None
return self.is_root()
@@ -44,6 +47,11 @@
def remount(self):
self.__invoke('remount')
+ def reboot(self):
+ self.__is_root = None
+ self.shell('reboot')
+ self.__has_established_connection = False
+
def __echo_shell_cmd(self, cmd):
escaped = [re.sub(r'([^a-zA-Z0-9])', r'\\\1', x)
for x in cmd.strip().splitlines()]
@@ -51,4 +59,15 @@
" '\n>' ".join(escaped))
def __invoke(self, *args):
+ self.__establish_connection()
subprocess.call(self.__invocation + list(args), stdout=sys.stderr)
+
+ def __establish_connection(self):
+ if self.__has_established_connection:
+ return
+ self.__has_established_connection = True
+ self.__invoke('wait-for-device')
+ while True:
+ time.sleep(1)
+ if '1' == self.check('getprop sys.boot_completed').strip():
+ break
diff --git a/src/third_party/skia/tools/skpbench/_adb_path.py b/src/third_party/skia/tools/skpbench/_adb_path.py
index 4d8bce4..966ab44 100644
--- a/src/third_party/skia/tools/skpbench/_adb_path.py
+++ b/src/third_party/skia/tools/skpbench/_adb_path.py
@@ -9,9 +9,9 @@
__ADB = None
-def init(device_serial):
+def init(device_serial, adb_binary):
global __ADB
- __ADB = Adb(device_serial)
+ __ADB = Adb(device_serial, adb_binary)
def join(*pathnames):
return '/'.join(pathnames)
@@ -20,12 +20,14 @@
return pathname.rsplit('/', maxsplit=1)[-1]
def find_skps(skps):
+ # root first, in case skps reside in a protected directory
+ __ADB.root()
escapedskps = [re.sub(r'([^a-zA-Z0-9_/\.\*\?\[\!\]])', r'\\\1', x)
for x in skps]
return __ADB.check('''\
for PATHNAME in %s; do
if [ -d "$PATHNAME" ]; then
- find "$PATHNAME" -maxdepth 1 -name *.skp
+ find "$PATHNAME" -maxdepth 1 -name '*.skp' -o -name '*.mskp'
else
echo "$PATHNAME"
fi
diff --git a/src/third_party/skia/tools/skpbench/_hardware.py b/src/third_party/skia/tools/skpbench/_hardware.py
index de8848d..9283243 100644
--- a/src/third_party/skia/tools/skpbench/_hardware.py
+++ b/src/third_party/skia/tools/skpbench/_hardware.py
@@ -41,10 +41,6 @@
"""Prints any info that may help improve or debug hardware monitoring."""
pass
- def sleep(self, sleeptime):
- """Puts the hardware into a resting state for a fixed amount of time."""
- time.sleep(sleeptime)
-
class HardwareException(Exception):
"""Gets thrown when certain hardware state is not what we expect.
diff --git a/src/third_party/skia/tools/skpbench/_hardware_android.py b/src/third_party/skia/tools/skpbench/_hardware_android.py
index ebaba0a..499247b 100644
--- a/src/third_party/skia/tools/skpbench/_hardware_android.py
+++ b/src/third_party/skia/tools/skpbench/_hardware_android.py
@@ -16,10 +16,12 @@
if self._adb.root():
self._adb.remount()
- self._initial_ASLR = \
- self._adb.check('cat /proc/sys/kernel/randomize_va_space')
def __enter__(self):
+ Hardware.__enter__(self)
+ if not self._adb.is_root() and self._adb.root():
+ self._adb.remount()
+
self._adb.shell('\n'.join([
# turn on airplane mode.
'''
@@ -27,9 +29,9 @@
# disable GPS.
'''
- for MODE in gps wifi network; do
- settings put secure location_providers_allowed -$MODE
- done''']))
+ settings put secure location_providers_allowed -gps
+ settings put secure location_providers_allowed -wifi
+ settings put secure location_providers_allowed -network''']))
if self._adb.is_root():
self._adb.shell('\n'.join([
@@ -53,23 +55,11 @@
print("WARNING: no adb root access; results may be unreliable.",
file=sys.stderr)
- return Hardware.__enter__(self)
+ return self
def __exit__(self, exception_type, exception_value, traceback):
Hardware.__exit__(self, exception_type, exception_value, traceback)
-
- if self._adb.is_root():
- self._adb.shell('\n'.join([
- # restore ASLR.
- '''
- echo %s > /proc/sys/kernel/randomize_va_space''' % self._initial_ASLR,
-
- # revive the gui.
- '''
- setprop ctl.start drm
- setprop ctl.start surfaceflinger
- setprop ctl.start zygote
- setprop ctl.start media''']))
+ self._adb.reboot() # some devices struggle waking up; just hard reboot.
def sanity_check(self):
Hardware.sanity_check(self)
@@ -102,6 +92,3 @@
done''')
Hardware.print_debug_diagnostics(self)
-
- def sleep(self, sleeptime):
- Hardware.sleep(self, sleeptime)
diff --git a/src/third_party/skia/tools/skpbench/_hardware_nexus_6p.py b/src/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
index 077933b..e640835 100644
--- a/src/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
+++ b/src/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
@@ -14,23 +14,9 @@
HardwareAndroid.__init__(self, adb)
def __enter__(self):
- self._lock_clocks()
- return HardwareAndroid.__enter__(self)
-
- def __exit__(self, exception_type, exception_value, exception_traceback):
- HardwareAndroid.__exit__(self, exception_type,
- exception_value, exception_traceback)
- self._unlock_clocks()
-
- def _lock_clocks(self):
+ HardwareAndroid.__enter__(self)
if not self._adb.is_root():
- return
-
- self._adb.shell('''\
- stop thermal-engine
- stop thermald
- stop perfd
- stop mpdecision''')
+ return self
# enable and lock 3 of 4 big cores.
self._adb.shell('''\
@@ -72,51 +58,7 @@
echo 9887 > /sys/class/devfreq/qcom,gpubw.70/max_freq
echo 9887 > /sys/class/devfreq/qcom,gpubw.70/min_freq''')
- def _unlock_clocks(self):
- if not self._adb.is_root():
- return
-
- # restore ddr settings to default.
- self._adb.shell('''\
- echo 1525 > /sys/class/devfreq/qcom,cpubw.32/min_freq
- echo 9887 > /sys/class/devfreq/qcom,cpubw.32/max_freq
- echo bw_hwmon > /sys/class/devfreq/qcom,cpubw.32/governor
- echo 1525 > /sys/class/devfreq/qcom,gpubw.70/min_freq
- echo 9887 > /sys/class/devfreq/qcom,gpubw.70/max_freq
- echo bw_hwmon > /sys/class/devfreq/qcom,gpubw.70/governor''')
-
- # restore gpu settings to default.
- self._adb.shell('''\
- echo 180000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
- echo 600000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
- echo 180000000 > /sys/class/kgsl/kgsl-3d0/gpuclk
- echo msm-adreno-tz > /sys/class/kgsl/kgsl-3d0/devfreq/governor
- echo 0 > /sys/class/kgsl/kgsl-3d0/idle_timer
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_clk_on
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_rail_on
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_bus_on
- echo 1 > /sys/class/kgsl/kgsl-3d0/bus_split''')
-
- # turn the disabled cores back on.
- self._adb.shell('''\
- for N in 7 3 2 1 0; do
- echo 1 > /sys/devices/system/cpu/cpu$N/online
- done''')
-
- # unlock the 3 enabled big cores.
- self._adb.shell('''\
- for N in 6 5 4; do
- echo 633600 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
- echo 1958400 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
- echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
- echo interactive > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
- done''')
-
- self._adb.shell('''\
- start mpdecision
- start perfd
- start thermald
- start thermal-engine''')
+ return self
def sanity_check(self):
HardwareAndroid.sanity_check(self)
@@ -148,8 +90,3 @@
for i in range(4, 7)]
Expectation.check_all(expectations, result.splitlines())
-
- def sleep(self, sleeptime):
- self._unlock_clocks()
- HardwareAndroid.sleep(self, sleeptime)
- self._lock_clocks()
diff --git a/src/third_party/skia/tools/skpbench/_hardware_pixel.py b/src/third_party/skia/tools/skpbench/_hardware_pixel.py
new file mode 100644
index 0000000..7c254ac
--- /dev/null
+++ b/src/third_party/skia/tools/skpbench/_hardware_pixel.py
@@ -0,0 +1,90 @@
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from _hardware import Expectation
+from _hardware_android import HardwareAndroid
+
+CPU_CLOCK_RATE = 1670400
+GPU_CLOCK_RATE = 315000000
+
+class HardwarePixel(HardwareAndroid):
+ def __init__(self, adb):
+ HardwareAndroid.__init__(self, adb)
+
+ def __enter__(self):
+ HardwareAndroid.__enter__(self)
+ if not self._adb.is_root():
+ return self
+
+ self._adb.shell('\n'.join([
+ # enable and lock the two fast cores.
+ '''
+ stop thermal-engine
+ stop perfd
+
+ for N in 3 2; do
+ echo 1 > /sys/devices/system/cpu/cpu$N/online
+ echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
+ done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
+
+ # turn off the two slow cores
+ '''
+ for N in 1 0; do
+ echo 0 > /sys/devices/system/cpu/cpu$N/online
+ done''',
+
+ # pylint: disable=line-too-long
+
+ # Set GPU bus and idle timer
+ # Set DDR frequency to max
+ # Set GPU to performance mode, 315 MHZ
+ # See https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/tests/scripts/prep_marlfish.sh
+ '''
+ echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
+ echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
+ echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer
+
+ echo 13763 > /sys/class/devfreq/soc:qcom,gpubw/min_freq
+
+ echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
+
+ echo 4 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
+ echo 4 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel''' %
+ tuple(GPU_CLOCK_RATE for _ in range(2))]))
+
+ return self
+
+ def sanity_check(self):
+ HardwareAndroid.sanity_check(self)
+
+ if not self._adb.is_root():
+ return
+
+ result = self._adb.check(' '.join(
+ ['cat',
+ '/sys/class/power_supply/battery/capacity',
+ '/sys/devices/system/cpu/online'] + \
+ ['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i
+ for i in range(2, 4)] + \
+ ['/sys/kernel/debug/clk/bimc_clk/measure',
+ '/sys/class/thermal/thermal_zone22/temp',
+ '/sys/class/thermal/thermal_zone23/temp']))
+
+ expectations = \
+ [Expectation(int, min_value=30, name='battery', sleeptime=30*60),
+ Expectation(str, exact_value='2-3', name='online cpus')] + \
+ [Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i)
+ for i in range(2, 4)] + \
+ [Expectation(long, min_value=902390000, max_value=902409999,
+ name='measured ddr clock', sleeptime=10),
+ Expectation(int, max_value=41000, name='pm8994_tz temperature'),
+ Expectation(int, max_value=40, name='msm_therm temperature')]
+
+ Expectation.check_all(expectations, result.splitlines())
diff --git a/src/third_party/skia/tools/skpbench/_hardware_pixel2.py b/src/third_party/skia/tools/skpbench/_hardware_pixel2.py
new file mode 100644
index 0000000..a42cafa
--- /dev/null
+++ b/src/third_party/skia/tools/skpbench/_hardware_pixel2.py
@@ -0,0 +1,119 @@
+# Copyright 2018 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from _hardware import Expectation
+from _hardware_android import HardwareAndroid
+
+CPU_CLOCK_RATE = 2035200
+MEM_CLOCK_RATE = 13763
+GPU_CLOCK_RATE = 670000000
+GPU_POWER_LEVEL = 1 # lower is faster, minimum is 0
+
+class HardwarePixel2(HardwareAndroid):
+ def __init__(self, adb):
+ HardwareAndroid.__init__(self, adb)
+
+ def __enter__(self):
+ HardwareAndroid.__enter__(self)
+ if not self._adb.is_root():
+ return self
+
+ self._adb.shell('\n'.join([
+ '''
+ stop thermal-engine
+ stop perfd''',
+
+ # turn off the slow cores and one fast core
+ '''
+ for N in 0 1 2 3 7; do
+ echo 0 > /sys/devices/system/cpu/cpu$N/online
+ done''',
+
+ # lock 3 fast cores: two for Skia and one for the OS
+ '''
+ for N in 4 5 6; do
+ echo 1 > /sys/devices/system/cpu/cpu$N/online
+ echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
+ done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
+
+ # Set GPU bus and idle timer
+ '''
+ echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split''',
+ # csmartdalton, 4-26-2018: this line hangs my device
+ # echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
+ '''
+ echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer''',
+
+ # Set mem frequency to max
+ '''
+ echo %i > /sys/class/devfreq/soc\:qcom,gpubw/min_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,gpubw/max_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,cpubw/min_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,cpubw/max_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,mincpubw/min_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,mincpubw/max_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,memlat-cpu0/min_freq
+ echo %i > /sys/class/devfreq/soc\:qcom,memlat-cpu0/max_freq''' %
+ tuple(MEM_CLOCK_RATE for _ in range(8)),
+
+ # Set GPU to performance mode
+ '''
+ echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq''' %
+ tuple(GPU_CLOCK_RATE for _ in range(2)),
+
+ # Set GPU power level
+ '''
+ echo %i > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
+ echo %i > /sys/class/kgsl/kgsl-3d0/min_pwrlevel''' %
+ tuple(GPU_POWER_LEVEL for _ in range(2))]))
+
+ assert('msm_therm' == self._adb.check(\
+ 'cat /sys/class/thermal/thermal_zone10/type').strip())
+ assert('pm8998_tz' == self._adb.check(\
+ 'cat /sys/class/thermal/thermal_zone7/type').strip())
+
+ return self
+
+ def sanity_check(self):
+ HardwareAndroid.sanity_check(self)
+
+ if not self._adb.is_root():
+ return
+
+ result = self._adb.check(' '.join(
+ ['cat',
+ '/sys/class/power_supply/battery/capacity',
+ '/sys/devices/system/cpu/online'] + \
+ ['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i
+ for i in range(4, 7)] + \
+ # Unfortunately we can't monitor the gpu clock:
+ #
+ # /sys/class/kgsl/kgsl-3d0/devfreq/cur_freq
+ #
+ # It doesn't respect the min_freq/max_freq values when not under load.
+ ['/sys/kernel/debug/clk/bimc_clk/measure',
+ '/sys/class/kgsl/kgsl-3d0/temp',
+ '/sys/class/kgsl/kgsl-3d0/throttling',
+ '/sys/class/thermal/thermal_zone10/temp',
+ '/sys/class/thermal/thermal_zone7/temp']))
+
+ expectations = \
+ [Expectation(int, min_value=30, name='battery', sleeptime=30*60),
+ Expectation(str, exact_value='4-6', name='online cpus')] + \
+ [Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i)
+ for i in range(4, 7)] + \
+ [Expectation(long, min_value=902390000, max_value=902409999,
+ name='measured ddr clock', sleeptime=10),
+ Expectation(int, max_value=750, name='gpu temperature'),
+ Expectation(int, exact_value=1, name='gpu throttling'),
+ Expectation(int, max_value=75, name='msm_therm temperature'),
+ Expectation(int, max_value=75000, name='pm8998_tz temperature')]
+
+ Expectation.check_all(expectations, result.splitlines())
diff --git a/src/third_party/skia/tools/skpbench/_hardware_pixel_c.py b/src/third_party/skia/tools/skpbench/_hardware_pixel_c.py
index a1cd17a..5d0b9f1 100644
--- a/src/third_party/skia/tools/skpbench/_hardware_pixel_c.py
+++ b/src/third_party/skia/tools/skpbench/_hardware_pixel_c.py
@@ -6,44 +6,37 @@
from _hardware import HardwareException, Expectation
from _hardware_android import HardwareAndroid
-CPU_CLOCK_RATE = 1836000
-GPU_EMC_PROFILE = '0c: core 921 MHz emc 1600 MHz a A d D *'
-GPU_EMC_PROFILE_ID = '0c'
+CPU_CLOCK_RATE = 1326000
+# If you run adb cat /sys/devices/57000000.gpu/pstate it shows all
+# possible configurations, with a * next to the current one.
+GPU_EMC_PROFILE = '04: core 307 MHz emc 1065 MHz a A d D *'
+GPU_EMC_PROFILE_ID = '04'
class HardwarePixelC(HardwareAndroid):
def __init__(self, adb):
HardwareAndroid.__init__(self, adb)
def __enter__(self):
- self._lock_clocks()
- return HardwareAndroid.__enter__(self)
-
- def __exit__(self, exception_type, exception_value, exception_traceback):
- HardwareAndroid.__exit__(self, exception_type,
- exception_value, exception_traceback)
- self._unlock_clocks()
-
- def filter_line(self, line):
- JUNK = ['NvRmPrivGetChipPlatform: Could not read platform information',
- 'Expected on kernels without fuse support, using silicon']
- return False if line in JUNK else HardwareAndroid.filter_line(self, line)
-
- def _lock_clocks(self):
+ HardwareAndroid.__enter__(self)
if not self._adb.is_root():
- return
+ return self
self._adb.shell('\n'.join([
- # turn on and lock the first 3 cores.
+ # pylint: disable=line-too-long
+ # Based on https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/tests/scripts/prep_ryu.sh
+ # All CPUs have the same scaling settings, so we only need to set it once
'''
- for N in 0 1 2; do
- echo 1 > /sys/devices/system/cpu/cpu$N/online
- echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
- echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
- echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
- echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
- done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
+ stop thermal-engine
+ stop perfd
- # turn off the fourth core.
+ echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
+ echo %i > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
+ echo %i > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
+ echo %i > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
+ ''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
+ # turn off the fourth core. This will hopefully produce less heat, allowing
+ # for more consistent results. 3 cores should be enough to run Ganesh,
+ # the graphics driver, and the OS.
'''
echo 0 > /sys/devices/system/cpu/cpu3/online''',
@@ -52,28 +45,12 @@
chown root:root /sys/devices/57000000.gpu/pstate
echo %s > /sys/devices/57000000.gpu/pstate''' % GPU_EMC_PROFILE_ID]))
- def _unlock_clocks(self):
- if not self._adb.is_root():
- return
+ return self
- self._adb.shell('\n'.join([
- # unlock gpu/emc clocks.
- '''
- echo auto > /sys/devices/57000000.gpu/pstate
- chown system:system /sys/devices/57000000.gpu/pstate''',
-
- # turn the fourth core back on.
- '''
- echo 1 > /sys/devices/system/cpu/cpu3/online''',
-
- # unlock the first 3 cores.
- '''
- for N in 2 1 0; do
- echo 1912500 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
- echo 51000 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
- echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
- echo interactive >/sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
- done''']))
+ def filter_line(self, line):
+ JUNK = ['NvRmPrivGetChipPlatform: Could not read platform information',
+ 'Expected on kernels without fuse support, using silicon']
+ return False if line in JUNK else HardwareAndroid.filter_line(self, line)
def sanity_check(self):
HardwareAndroid.sanity_check(self)
@@ -109,8 +86,3 @@
[Expectation(str, exact_value=GPU_EMC_PROFILE, name='gpu/emc profile')]
Expectation.check_all(expectations, result.splitlines())
-
- def sleep(self, sleeptime):
- self._unlock_clocks()
- HardwareAndroid.sleep(self, sleeptime)
- self._lock_clocks()
diff --git a/src/third_party/skia/tools/skpbench/_os_path.py b/src/third_party/skia/tools/skpbench/_os_path.py
index 42b1c42..2c10265 100644
--- a/src/third_party/skia/tools/skpbench/_os_path.py
+++ b/src/third_party/skia/tools/skpbench/_os_path.py
@@ -17,6 +17,7 @@
for skp in skps:
if (path.isdir(skp)):
pathnames.extend(glob.iglob(path.join(skp, '*.skp')))
+ pathnames.extend(glob.iglob(path.join(skp, '*.mskp')))
else:
pathnames.append(skp)
return pathnames
diff --git a/src/third_party/skia/tools/skpbench/skpbench.cpp b/src/third_party/skia/tools/skpbench/skpbench.cpp
index c0ead46..b1d0cc0 100644
--- a/src/third_party/skia/tools/skpbench/skpbench.cpp
+++ b/src/third_party/skia/tools/skpbench/skpbench.cpp
@@ -5,24 +5,37 @@
* found in the LICENSE file.
*/
-#include "GpuTimer.h"
-#include "GrContextFactory.h"
-#include "SkGr.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkPictureRecorder.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkSurfaceProps.h"
+#include "include/effects/SkPerlinNoiseShader.h"
+#include "include/private/SkDeferredDisplayList.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkTaskGroup.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/SkGr.h"
+#include "src/utils/SkMultiPictureDocument.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/DDLPromiseImageHelper.h"
+#include "tools/DDLTileHelper.h"
+#include "tools/SkSharingProc.h"
+#include "tools/ToolUtils.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/flags/CommonFlags.h"
+#include "tools/flags/CommonFlagsConfig.h"
+#include "tools/gpu/GpuTimer.h"
+#include "tools/gpu/GrContextFactory.h"
-#include "SkCanvas.h"
-#include "SkCommonFlagsPathRenderer.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkPerlinNoiseShader.h"
-#include "SkPicture.h"
-#include "SkPictureRecorder.h"
-#include "SkStream.h"
-#include "SkSurface.h"
-#include "SkSurfaceProps.h"
-#include "picture_utils.h"
-#include "sk_tool_utils.h"
-#include "flags/SkCommandLineFlags.h"
-#include "flags/SkCommonFlagsConfig.h"
+#ifdef SK_XML
+#include "experimental/svg/model/SkSVGDOM.h"
+#include "src/xml/SkDOM.h"
+#endif
+
#include <stdlib.h>
#include <algorithm>
#include <array>
@@ -31,25 +44,35 @@
#include <vector>
/**
- * This is a minimalist program whose sole purpose is to open an skp file, benchmark it on a single
- * config, and exit. It is intended to be used through skpbench.py rather than invoked directly.
- * Limiting the entire process to a single config/skp pair helps to keep the results repeatable.
+ * This is a minimalist program whose sole purpose is to open a .skp or .svg file, benchmark it on a
+ * single config, and exit. It is intended to be used through skpbench.py rather than invoked
+ * directly. Limiting the entire process to a single config/skp pair helps to keep the results
+ * repeatable.
*
* No tiling, looping, or other fanciness is used; it just draws the skp whole into a size-matched
* render target and syncs the GPU after each draw.
*
+ * Well, maybe a little fanciness, MSKP's can be loaded and played. The animation is played as many
+ * times as necessary to reach the target sample duration and FPS is reported.
+ *
* Currently, only GPU configs are supported.
*/
-DEFINE_int32(duration, 5000, "number of milliseconds to run the benchmark");
-DEFINE_int32(sampleMs, 50, "minimum duration of a sample");
-DEFINE_bool(gpuClock, false, "time on the gpu clock (gpu work only)");
-DEFINE_bool(fps, false, "use fps instead of ms");
-DEFINE_string(skp, "", "path to a single .skp file, or 'warmup' for a builtin warmup run");
-DEFINE_string(png, "", "if set, save a .png proof to disk at this file location");
-DEFINE_int32(verbosity, 4, "level of verbosity (0=none to 5=debug)");
-DEFINE_bool(suppressHeader, false, "don't print a header row before the results");
-DEFINE_pathrenderer_flag;
+static DEFINE_bool(ddl, false, "record the skp into DDLs before rendering");
+static DEFINE_int(ddlNumAdditionalThreads, 0,
+ "number of DDL recording threads in addition to main one");
+static DEFINE_int(ddlTilingWidthHeight, 0, "number of tiles along one edge when in DDL mode");
+static DEFINE_bool(ddlRecordTime, false, "report just the cpu time spent recording DDLs");
+
+static DEFINE_int(duration, 5000, "number of milliseconds to run the benchmark");
+static DEFINE_int(sampleMs, 50, "minimum duration of a sample");
+static DEFINE_bool(gpuClock, false, "time on the gpu clock (gpu work only)");
+static DEFINE_bool(fps, false, "use fps instead of ms");
+static DEFINE_string(src, "",
+ "path to a single .skp or .svg file, or 'warmup' for a builtin warmup run");
+static DEFINE_string(png, "", "if set, save a .png proof to disk at this file location");
+static DEFINE_int(verbosity, 4, "level of verbosity (0=none to 5=debug)");
+static DEFINE_bool(suppressHeader, false, "don't print a header row before the results");
static const char* header =
" accum median max min stddev samples sample_ms clock metric config bench";
@@ -57,6 +80,8 @@
static const char* resultFormat =
"%8.4g %8.4g %8.4g %8.4g %6.3g%% %7li %9i %-5s %-6s %-9s %s";
+static constexpr int kNumFlushesToPrimeCache = 3;
+
struct Sample {
using duration = std::chrono::nanoseconds;
@@ -93,23 +118,169 @@
kSoftware = 70
};
-static void draw_skp_and_flush(SkCanvas*, const SkPicture*);
+static void draw_skp_and_flush(SkSurface*, const SkPicture*);
static sk_sp<SkPicture> create_warmup_skp();
+static sk_sp<SkPicture> create_skp_from_svg(SkStream*, const char* filename);
static bool mkdir_p(const SkString& name);
-static SkString join(const SkCommandLineFlags::StringArray&);
+static SkString join(const CommandLineFlags::StringArray&);
static void exitf(ExitErr, const char* format, ...);
-static void run_benchmark(const sk_gpu_test::FenceSync* fenceSync, SkCanvas* canvas,
- const SkPicture* skp, std::vector<Sample>* samples) {
+// An interface used by both static SKPs and animated SKPs
+class SkpProducer {
+ public:
+ virtual ~SkpProducer() {}
+ // Draw an SkPicture to the provided surface, flush the surface, and sync the GPU.
+ // You may use the static draw_skp_and_flush declared above.
+ // returned int tells how many draw/flush/sync were done.
+ virtual int drawAndFlushAndSync(SkSurface* surface, GpuSync& gpuSync) = 0;
+};
+
+class StaticSkp : public SkpProducer {
+ public:
+ StaticSkp(sk_sp<SkPicture> skp) : fSkp(skp) {}
+
+ int drawAndFlushAndSync(SkSurface* surface, GpuSync& gpuSync) override {
+ draw_skp_and_flush(surface, fSkp.get());
+ gpuSync.syncToPreviousFrame();
+ return 1;
+ }
+ private:
+ sk_sp<SkPicture> fSkp;
+};
+
+// A class for playing/benchmarking a multi frame SKP file.
+// the recorded frames are looped over repeatedly.
+// This type of benchmark may have a much higher std dev in frame times.
+class MultiFrameSkp : public SkpProducer {
+public:
+ MultiFrameSkp(const std::vector<SkDocumentPage>& frames) : fFrames(frames){}
+
+ static std::unique_ptr<MultiFrameSkp> MakeFromFile(const SkString& path) {
+ // Load the multi frame skp at the given filename.
+ std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path.c_str());
+ if (!stream) { return nullptr; }
+
+ // Attempt to deserialize with an image sharing serial proc.
+ auto deserialContext = std::make_unique<SkSharingDeserialContext>();
+ SkDeserialProcs procs;
+ procs.fImageProc = SkSharingDeserialContext::deserializeImage;
+ procs.fImageCtx = deserialContext.get();
+
+ // The outer format of multi-frame skps is the multi-picture document, which is a
+ // skp file containing subpictures separated by annotations.
+ int page_count = SkMultiPictureDocumentReadPageCount(stream.get());
+ if (!page_count) {
+ return nullptr;
+ }
+ std::vector<SkDocumentPage> frames(page_count); // can't call reserve, why?
+ if (!SkMultiPictureDocumentRead(stream.get(), frames.data(), page_count, &procs)) {
+ return nullptr;
+ }
+
+ return std::make_unique<MultiFrameSkp>(frames);
+ }
+
+ // Draw the whole animation once.
+ int drawAndFlushAndSync(SkSurface* surface, GpuSync& gpuSync) override {
+ for (int i=0; i<this->count(); i++){
+ draw_skp_and_flush(surface, this->frame(i).get());
+ gpuSync.syncToPreviousFrame();
+ }
+ return this->count();
+ }
+ // Return the requested frame.
+ sk_sp<SkPicture> frame(int n) const { return fFrames[n].fPicture; }
+ // Return the number of frames in the recording.
+ int count() const { return fFrames.size(); }
+private:
+ std::vector<SkDocumentPage> fFrames;
+};
+
+static void ddl_sample(GrContext* context, DDLTileHelper* tiles, GpuSync* gpuSync, Sample* sample,
+ std::chrono::high_resolution_clock::time_point* startStopTime) {
+ using clock = std::chrono::high_resolution_clock;
+
+ clock::time_point start = *startStopTime;
+
+ tiles->createDDLsInParallel();
+
+ if (!FLAGS_ddlRecordTime) {
+ tiles->drawAllTilesAndFlush(context, true);
+ if (gpuSync) {
+ gpuSync->syncToPreviousFrame();
+ }
+ }
+
+ *startStopTime = clock::now();
+
+ tiles->resetAllTiles();
+
+ if (sample) {
+ SkASSERT(gpuSync);
+ sample->fDuration += *startStopTime - start;
+ sample->fFrames++;
+ }
+}
+
+static void run_ddl_benchmark(const sk_gpu_test::FenceSync* fenceSync,
+ GrContext* context, SkCanvas* finalCanvas,
+ SkPicture* inputPicture, std::vector<Sample>* samples) {
using clock = std::chrono::high_resolution_clock;
const Sample::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs);
const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration);
- draw_skp_and_flush(canvas, skp);
- GpuSync gpuSync(fenceSync);
+ SkIRect viewport = finalCanvas->imageInfo().bounds();
- draw_skp_and_flush(canvas, skp);
- gpuSync.syncToPreviousFrame();
+ DDLPromiseImageHelper promiseImageHelper;
+ sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture);
+ if (!compressedPictureData) {
+ exitf(ExitErr::kUnavailable, "DDL: conversion of skp failed");
+ }
+
+ promiseImageHelper.uploadAllToGPU(context);
+
+ DDLTileHelper tiles(finalCanvas, viewport, FLAGS_ddlTilingWidthHeight);
+
+ tiles.createSKPPerTile(compressedPictureData.get(), promiseImageHelper);
+
+ SkTaskGroup::Enabler enabled(FLAGS_ddlNumAdditionalThreads);
+
+ clock::time_point startStopTime = clock::now();
+
+ ddl_sample(context, &tiles, nullptr, nullptr, &startStopTime);
+ GpuSync gpuSync(fenceSync);
+ ddl_sample(context, &tiles, &gpuSync, nullptr, &startStopTime);
+
+ clock::duration cumulativeDuration = std::chrono::milliseconds(0);
+
+ do {
+ samples->emplace_back();
+ Sample& sample = samples->back();
+
+ do {
+ ddl_sample(context, &tiles, &gpuSync, &sample, &startStopTime);
+ } while (sample.fDuration < sampleDuration);
+
+ cumulativeDuration += sample.fDuration;
+ } while (cumulativeDuration < benchDuration || 0 == samples->size() % 2);
+
+ if (!FLAGS_png.isEmpty()) {
+ // The user wants to see the final result
+ tiles.composeAllTiles(finalCanvas);
+ }
+}
+
+static void run_benchmark(const sk_gpu_test::FenceSync* fenceSync, SkSurface* surface,
+ SkpProducer* skpp, std::vector<Sample>* samples) {
+ using clock = std::chrono::high_resolution_clock;
+ const Sample::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs);
+ const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration);
+
+ GpuSync gpuSync(fenceSync);
+ int i = 0;
+ do {
+ i += skpp->drawAndFlushAndSync(surface, gpuSync);
+ } while(i < kNumFlushesToPrimeCache);
clock::time_point now = clock::now();
const clock::time_point endTime = now + benchDuration;
@@ -120,18 +291,15 @@
Sample& sample = samples->back();
do {
- draw_skp_and_flush(canvas, skp);
- gpuSync.syncToPreviousFrame();
-
- now = clock::now();
- sample.fDuration = now - sampleStart;
- ++sample.fFrames;
+ sample.fFrames += skpp->drawAndFlushAndSync(surface, gpuSync);
+ now = clock::now();
+ sample.fDuration = now - sampleStart;
} while (sample.fDuration < sampleDuration);
} while (now < endTime || 0 == samples->size() % 2);
}
static void run_gpu_time_benchmark(sk_gpu_test::GpuTimer* gpuTimer,
- const sk_gpu_test::FenceSync* fenceSync, SkCanvas* canvas,
+ const sk_gpu_test::FenceSync* fenceSync, SkSurface* surface,
const SkPicture* skp, std::vector<Sample>* samples) {
using sk_gpu_test::PlatformTimerQuery;
using clock = std::chrono::steady_clock;
@@ -143,13 +311,16 @@
"results may be unreliable\n");
}
- draw_skp_and_flush(canvas, skp);
+ draw_skp_and_flush(surface, skp);
GpuSync gpuSync(fenceSync);
- gpuTimer->queueStart();
- draw_skp_and_flush(canvas, skp);
- PlatformTimerQuery previousTime = gpuTimer->queueStop();
- gpuSync.syncToPreviousFrame();
+ PlatformTimerQuery previousTime = 0;
+ for (int i = 1; i < kNumFlushesToPrimeCache; ++i) {
+ gpuTimer->queueStart();
+ draw_skp_and_flush(surface, skp);
+ previousTime = gpuTimer->queueStop();
+ gpuSync.syncToPreviousFrame();
+ }
clock::time_point now = clock::now();
const clock::time_point endTime = now + benchDuration;
@@ -161,7 +332,7 @@
do {
gpuTimer->queueStart();
- draw_skp_and_flush(canvas, skp);
+ draw_skp_and_flush(surface, skp);
PlatformTimerQuery time = gpuTimer->queueStop();
gpuSync.syncToPreviousFrame();
@@ -223,9 +394,10 @@
}
int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Use skpbench.py instead. "
- "You usually don't want to use this program directly.");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::SetUsage(
+ "Use skpbench.py instead. "
+ "You usually don't want to use this program directly.");
+ CommandLineFlags::Parse(argc, argv);
if (!FLAGS_suppressHeader) {
printf("%s\n", header);
@@ -244,39 +416,57 @@
}
// Parse the skp.
- if (FLAGS_skp.count() != 1) {
- exitf(ExitErr::kUsage, "invalid skp '%s': must specify a single skp file, or 'warmup'",
- join(FLAGS_skp).c_str());
+ if (FLAGS_src.count() != 1) {
+ exitf(ExitErr::kUsage,
+ "invalid input '%s': must specify a single .skp or .svg file, or 'warmup'",
+ join(FLAGS_src).c_str());
}
+
+ SkGraphics::Init();
+
sk_sp<SkPicture> skp;
- SkString skpname;
- if (0 == strcmp(FLAGS_skp[0], "warmup")) {
+ std::unique_ptr<MultiFrameSkp> mskp; // populated if the file is multi frame.
+ SkString srcname;
+ if (0 == strcmp(FLAGS_src[0], "warmup")) {
skp = create_warmup_skp();
- skpname = "warmup";
+ srcname = "warmup";
} else {
- const char* skpfile = FLAGS_skp[0];
- std::unique_ptr<SkStream> skpstream(SkStream::MakeFromFile(skpfile));
- if (!skpstream) {
- exitf(ExitErr::kIO, "failed to open skp file %s", skpfile);
+ SkString srcfile(FLAGS_src[0]);
+ std::unique_ptr<SkStream> srcstream(SkStream::MakeFromFile(srcfile.c_str()));
+ if (!srcstream) {
+ exitf(ExitErr::kIO, "failed to open file %s", srcfile.c_str());
}
- skp = SkPicture::MakeFromStream(skpstream.get());
+ if (srcfile.endsWith(".svg")) {
+ skp = create_skp_from_svg(srcstream.get(), srcfile.c_str());
+ } else if (srcfile.endsWith(".mskp")) {
+ mskp = MultiFrameSkp::MakeFromFile(srcfile);
+ // populate skp with it's first frame, for width height determination.
+ skp = mskp->frame(0);
+ } else {
+ skp = SkPicture::MakeFromStream(srcstream.get());
+ }
if (!skp) {
- exitf(ExitErr::kData, "failed to parse skp file %s", skpfile);
+ exitf(ExitErr::kData, "failed to parse file %s", srcfile.c_str());
}
- skpname = SkOSPath::Basename(skpfile);
+ srcname = SkOSPath::Basename(srcfile.c_str());
}
int width = SkTMin(SkScalarCeilToInt(skp->cullRect().width()), 2048),
height = SkTMin(SkScalarCeilToInt(skp->cullRect().height()), 2048);
if (FLAGS_verbosity >= 3 &&
(width != skp->cullRect().width() || height != skp->cullRect().height())) {
fprintf(stderr, "%s is too large (%ix%i), cropping to %ix%i.\n",
- skpname.c_str(), SkScalarCeilToInt(skp->cullRect().width()),
+ srcname.c_str(), SkScalarCeilToInt(skp->cullRect().width()),
SkScalarCeilToInt(skp->cullRect().height()), width, height);
}
+ if (config->getSurfType() != SkCommandLineConfigGpu::SurfType::kDefault) {
+ exitf(ExitErr::kUnavailable, "This tool only supports the default surface type. (%s)",
+ config->getTag().c_str());
+ }
+
// Create a context.
GrContextOptions ctxOptions;
- ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+ SetCtxOptionsFromCommonFlags(&ctxOptions);
sk_gpu_test::GrContextFactory factory(ctxOptions);
sk_gpu_test::ContextInfo ctxInfo =
factory.getContextInfo(config->getContextType(), config->getContextOverrides());
@@ -285,14 +475,17 @@
exitf(ExitErr::kUnavailable, "failed to create context for config %s",
config->getTag().c_str());
}
- if (ctx->caps()->maxRenderTargetSize() < SkTMax(width, height)) {
+ if (ctx->maxRenderTargetSize() < SkTMax(width, height)) {
exitf(ExitErr::kUnavailable, "render target size %ix%i not supported by platform (max: %i)",
- width, height, ctx->caps()->maxRenderTargetSize());
+ width, height, ctx->maxRenderTargetSize());
}
- GrPixelConfig grPixConfig = SkImageInfo2GrPixelConfig(config->getColorType(),
- config->getColorSpace(),
- *ctx->caps());
- int supportedSampleCount = ctx->caps()->getSampleCount(config->getSamples(), grPixConfig);
+ GrBackendFormat format = ctx->defaultBackendFormat(config->getColorType(), GrRenderable::kYes);
+ if (!format.isValid()) {
+ exitf(ExitErr::kUnavailable, "failed to get GrBackendFormat from SkColorType: %d",
+ config->getColorType());
+ }
+ int supportedSampleCount = ctx->priv().caps()->getRenderTargetSampleCount(
+ config->getSamples(), format);
if (supportedSampleCount != config->getSamples()) {
exitf(ExitErr::kUnavailable, "sample count %i not supported by platform",
config->getSamples());
@@ -329,15 +522,25 @@
SkCanvas* canvas = surface->getCanvas();
canvas->translate(-skp->cullRect().x(), -skp->cullRect().y());
if (!FLAGS_gpuClock) {
- run_benchmark(testCtx->fenceSync(), canvas, skp.get(), &samples);
+ if (FLAGS_ddl) {
+ run_ddl_benchmark(testCtx->fenceSync(), ctx, canvas, skp.get(), &samples);
+ } else if (!mskp) {
+ auto s = std::make_unique<StaticSkp>(skp);
+ run_benchmark(testCtx->fenceSync(), surface.get(), s.get(), &samples);
+ } else {
+ run_benchmark(testCtx->fenceSync(), surface.get(), mskp.get(), &samples);
+ }
} else {
+ if (FLAGS_ddl) {
+ exitf(ExitErr::kUnavailable, "DDL: GPU-only timing not supported");
+ }
if (!testCtx->gpuTimingSupport()) {
exitf(ExitErr::kUnavailable, "GPU does not support timing");
}
- run_gpu_time_benchmark(testCtx->gpuTimer(), testCtx->fenceSync(), canvas, skp.get(),
- &samples);
+ run_gpu_time_benchmark(testCtx->gpuTimer(), testCtx->fenceSync(), surface.get(),
+ skp.get(), &samples);
}
- print_result(samples, config->getTag().c_str(), skpname.c_str());
+ print_result(samples, config->getTag().c_str(), srcname.c_str());
// Save a proof (if one was requested).
if (!FLAGS_png.isEmpty()) {
@@ -346,12 +549,10 @@
if (!surface->getCanvas()->readPixels(bmp, 0, 0)) {
exitf(ExitErr::kUnavailable, "failed to read canvas pixels for png");
}
- const SkString &dirname = SkOSPath::Dirname(FLAGS_png[0]),
- &basename = SkOSPath::Basename(FLAGS_png[0]);
- if (!mkdir_p(dirname)) {
- exitf(ExitErr::kIO, "failed to create directory \"%s\" for png", dirname.c_str());
+ if (!mkdir_p(SkOSPath::Dirname(FLAGS_png[0]))) {
+ exitf(ExitErr::kIO, "failed to create directory for png \"%s\"", FLAGS_png[0]);
}
- if (!sk_tools::write_bitmap_to_disk(bmp, dirname, nullptr, basename)) {
+ if (!ToolUtils::EncodeImageToFile(FLAGS_png[0], bmp, SkEncodedImageFormat::kPNG, 100)) {
exitf(ExitErr::kIO, "failed to save png to \"%s\"", FLAGS_png[0]);
}
}
@@ -359,9 +560,10 @@
exit(0);
}
-static void draw_skp_and_flush(SkCanvas* canvas, const SkPicture* skp) {
+static void draw_skp_and_flush(SkSurface* surface, const SkPicture* skp) {
+ auto canvas = surface->getCanvas();
canvas->drawPicture(skp);
- canvas->flush();
+ surface->flush();
}
static sk_sp<SkPicture> create_warmup_skp() {
@@ -377,7 +579,7 @@
// Use a big path to (theoretically) warmup the CPU.
SkPath bigPath;
- sk_tool_utils::make_big_path(bigPath);
+ ToolUtils::make_big_path(bigPath);
recording->drawPath(bigPath, stroke);
// Use a perlin shader to warmup the GPU.
@@ -388,14 +590,38 @@
return recorder.finishRecordingAsPicture();
}
+static sk_sp<SkPicture> create_skp_from_svg(SkStream* stream, const char* filename) {
+#ifdef SK_XML
+ SkDOM xml;
+ if (!xml.build(*stream)) {
+ exitf(ExitErr::kData, "failed to parse xml in file %s", filename);
+ }
+ sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromDOM(xml);
+ if (!svg) {
+ exitf(ExitErr::kData, "failed to build svg dom from file %s", filename);
+ }
+
+ static constexpr SkRect bounds{0, 0, 1200, 1200};
+ SkPictureRecorder recorder;
+ SkCanvas* recording = recorder.beginRecording(bounds);
+
+ svg->setContainerSize(SkSize::Make(recording->getBaseLayerSize()));
+ svg->render(recording);
+
+ return recorder.finishRecordingAsPicture();
+#endif
+ exitf(ExitErr::kData, "SK_XML is disabled; cannot open svg file %s", filename);
+ return nullptr;
+}
+
bool mkdir_p(const SkString& dirname) {
- if (dirname.isEmpty()) {
+ if (dirname.isEmpty() || dirname == SkString("/")) {
return true;
}
return mkdir_p(SkOSPath::Dirname(dirname.c_str())) && sk_mkdir(dirname.c_str());
}
-static SkString join(const SkCommandLineFlags::StringArray& stringArray) {
+static SkString join(const CommandLineFlags::StringArray& stringArray) {
SkString joined;
for (int i = 0; i < stringArray.count(); ++i) {
joined.appendf(i ? " %s" : "%s", stringArray[i]);
diff --git a/src/third_party/skia/tools/skpbench/skpbench.py b/src/third_party/skia/tools/skpbench/skpbench.py
index ef44577..7e40df4 100755
--- a/src/third_party/skia/tools/skpbench/skpbench.py
+++ b/src/third_party/skia/tools/skpbench/skpbench.py
@@ -33,6 +33,8 @@
help="path to the skpbench binary")
__argparse.add_argument('--adb',
action='store_true', help="execute skpbench over adb")
+__argparse.add_argument('--adb_binary', default='adb',
+ help="The name of the adb binary to use.")
__argparse.add_argument('-s', '--device-serial',
help="if using adb, ID of the specific device to target "
"(only required if more than 1 device is attached)")
@@ -54,18 +56,39 @@
help="perform timing on the gpu clock instead of cpu (gpu work only)")
__argparse.add_argument('--fps',
action='store_true', help="use fps instead of ms")
+__argparse.add_argument('--pr',
+ help="comma- or space-separated list of GPU path renderers, including: "
+ "[[~]all [~]default [~]dashline [~]nvpr [~]msaa [~]aaconvex "
+ "[~]aalinearizing [~]small [~]tess]")
+__argparse.add_argument('--cc',
+ action='store_true', help="allow coverage counting shortcuts to render paths")
+__argparse.add_argument('--nocache',
+ action='store_true', help="disable caching of path mask textures")
__argparse.add_argument('-c', '--config',
default='gl', help="comma- or space-separated list of GPU configs")
__argparse.add_argument('-a', '--resultsfile',
help="optional file to append results into")
-__argparse.add_argument('skps',
+__argparse.add_argument('--ddl',
+ action='store_true', help="record the skp into DDLs before rendering")
+__argparse.add_argument('--ddlNumAdditionalThreads',
+ type=int, default=0,
+ help="number of DDL recording threads in addition to main one")
+__argparse.add_argument('--ddlTilingWidthHeight',
+ type=int, default=0, help="number of tiles along one edge when in DDL mode")
+__argparse.add_argument('--ddlRecordTime',
+ action='store_true', help="report just the cpu time spent recording DDLs")
+__argparse.add_argument('--gpuThreads',
+ type=int, default=-1,
+ help="Create this many extra threads to assist with GPU work, including"
+ " software path rendering. Defaults to two.")
+__argparse.add_argument('srcs',
nargs='+',
- help=".skp files or directories to expand for .skp files")
+ help=".skp files or directories to expand for .skp files, and/or .svg files")
FLAGS = __argparse.parse_args()
if FLAGS.adb:
import _adb_path as _path
- _path.init(FLAGS.device_serial)
+ _path.init(FLAGS.device_serial, FLAGS.adb_binary)
else:
import _os_path as _path
@@ -108,11 +131,31 @@
ARGV.extend(['--gpuClock', 'true'])
if FLAGS.fps:
ARGV.extend(['--fps', 'true'])
+ if FLAGS.pr:
+ ARGV.extend(['--pr'] + re.split(r'[ ,]', FLAGS.pr))
+ if FLAGS.cc:
+ ARGV.extend(['--cc', 'true'])
+ if FLAGS.nocache:
+ ARGV.extend(['--cachePathMasks', 'false'])
+ if FLAGS.gpuThreads != -1:
+ ARGV.extend(['--gpuThreads', str(FLAGS.gpuThreads)])
+
+ # DDL parameters
+ if FLAGS.ddl:
+ ARGV.extend(['--ddl', 'true'])
+ if FLAGS.ddlNumAdditionalThreads:
+ ARGV.extend(['--ddlNumAdditionalThreads',
+ str(FLAGS.ddlNumAdditionalThreads)])
+ if FLAGS.ddlTilingWidthHeight:
+ ARGV.extend(['--ddlTilingWidthHeight', str(FLAGS.ddlTilingWidthHeight)])
+ if FLAGS.ddlRecordTime:
+ ARGV.extend(['--ddlRecordTime', 'true'])
+
if FLAGS.adb:
if FLAGS.device_serial is None:
- ARGV[:0] = ['adb', 'shell']
+ ARGV[:0] = [FLAGS.adb_binary, 'shell']
else:
- ARGV[:0] = ['adb', '-s', FLAGS.device_serial, 'shell']
+ ARGV[:0] = [FLAGS.adb_binary, '-s', FLAGS.device_serial, 'shell']
@classmethod
def get_header(cls, outfile=sys.stdout):
@@ -128,7 +171,7 @@
print('running %i second warmup...' % warmup_time, file=sys.stderr)
commandline = cls.ARGV + ['--duration', str(warmup_time * 1000),
'--config', config,
- '--skp', 'warmup']
+ '--src', 'warmup']
dump_commandline_if_verbose(commandline)
output = subprocess.check_output(commandline, stderr=subprocess.STDOUT)
@@ -139,8 +182,8 @@
return
raise Exception('Invalid warmup output:\n%s' % output)
- def __init__(self, skp, config, max_stddev, best_result=None):
- self.skp = skp
+ def __init__(self, src, config, max_stddev, best_result=None):
+ self.src = src
self.config = config
self.max_stddev = max_stddev
self.best_result = best_result
@@ -163,11 +206,11 @@
self._schedule_hardware_poll()
commandline = self.ARGV + ['--config', self.config,
- '--skp', self.skp,
+ '--src', self.src,
'--suppressHeader', 'true']
if FLAGS.write_path:
pngfile = _path.join(FLAGS.write_path, self.config,
- _path.basename(self.skp) + '.png')
+ _path.basename(self.src) + '.png')
commandline.extend(['--png', pngfile])
dump_commandline_if_verbose(commandline)
self._proc = subprocess.Popen(commandline, stdout=subprocess.PIPE,
@@ -230,59 +273,75 @@
print(line, file=resultsfile)
resultsfile.flush()
-def run_benchmarks(configs, skps, hardware, resultsfile=None):
- emit_result(SKPBench.get_header(), resultsfile)
- benches = collections.deque([(skp, config, FLAGS.max_stddev)
- for skp in skps
+def run_benchmarks(configs, srcs, hardware, resultsfile=None):
+ hasheader = False
+ benches = collections.deque([(src, config, FLAGS.max_stddev)
+ for src in srcs
for config in configs])
while benches:
- benchargs = benches.popleft()
- with SKPBench(*benchargs) as skpbench:
- try:
- skpbench.execute(hardware)
- if skpbench.best_result:
- emit_result(skpbench.best_result.format(FLAGS.suffix), resultsfile)
- else:
- print("WARNING: no result for %s with config %s" %
- (skpbench.skp, skpbench.config), file=sys.stderr)
-
- except StddevException:
- retry_max_stddev = skpbench.max_stddev * math.sqrt(2)
- if FLAGS.verbosity >= 1:
- print("stddev is too high for %s/%s (%s%%, max=%.2f%%), "
- "re-queuing with max=%.2f%%." %
- (skpbench.best_result.config, skpbench.best_result.bench,
- skpbench.best_result.stddev, skpbench.max_stddev,
- retry_max_stddev),
- file=sys.stderr)
- benches.append((skpbench.skp, skpbench.config, retry_max_stddev,
- skpbench.best_result))
-
- except HardwareException as exception:
- skpbench.terminate()
- if FLAGS.verbosity >= 4:
- hardware.print_debug_diagnostics()
- if FLAGS.verbosity >= 1:
- print("%s; taking a %i second nap..." %
- (exception.message, exception.sleeptime), file=sys.stderr)
- benches.appendleft(benchargs) # retry the same bench next time.
- hardware.sleep(exception.sleeptime)
- if FLAGS.verbosity >= 4:
- hardware.print_debug_diagnostics()
+ try:
+ with hardware:
SKPBench.run_warmup(hardware.warmup_time, configs[0])
+ if not hasheader:
+ emit_result(SKPBench.get_header(), resultsfile)
+ hasheader = True
+ while benches:
+ benchargs = benches.popleft()
+ with SKPBench(*benchargs) as skpbench:
+ try:
+ skpbench.execute(hardware)
+ if skpbench.best_result:
+ emit_result(skpbench.best_result.format(FLAGS.suffix),
+ resultsfile)
+ else:
+ print("WARNING: no result for %s with config %s" %
+ (skpbench.src, skpbench.config), file=sys.stderr)
+
+ except StddevException:
+ retry_max_stddev = skpbench.max_stddev * math.sqrt(2)
+ if FLAGS.verbosity >= 1:
+ print("stddev is too high for %s/%s (%s%%, max=%.2f%%), "
+ "re-queuing with max=%.2f%%." %
+ (skpbench.best_result.config, skpbench.best_result.bench,
+ skpbench.best_result.stddev, skpbench.max_stddev,
+ retry_max_stddev),
+ file=sys.stderr)
+ benches.append((skpbench.src, skpbench.config, retry_max_stddev,
+ skpbench.best_result))
+
+ except HardwareException as exception:
+ skpbench.terminate()
+ if FLAGS.verbosity >= 4:
+ hardware.print_debug_diagnostics()
+ if FLAGS.verbosity >= 1:
+ print("%s; rebooting and taking a %i second nap..." %
+ (exception.message, exception.sleeptime), file=sys.stderr)
+ benches.appendleft(benchargs) # retry the same bench next time.
+ raise # wake hw up from benchmarking mode before the nap.
+
+ except HardwareException as exception:
+ time.sleep(exception.sleeptime)
def main():
# Delimiter is ',' or ' ', skip if nested inside parens (e.g. gpu(a=b,c=d)).
DELIMITER = r'[, ](?!(?:[^(]*\([^)]*\))*[^()]*\))'
configs = re.split(DELIMITER, FLAGS.config)
- skps = _path.find_skps(FLAGS.skps)
+ srcs = _path.find_skps(FLAGS.srcs)
+ assert srcs
if FLAGS.adb:
- adb = Adb(FLAGS.device_serial, echo=(FLAGS.verbosity >= 5))
+ adb = Adb(FLAGS.device_serial, FLAGS.adb_binary,
+ echo=(FLAGS.verbosity >= 5))
model = adb.check('getprop ro.product.model').strip()
if model == 'Pixel C':
from _hardware_pixel_c import HardwarePixelC
hardware = HardwarePixelC(adb)
+ elif model == 'Pixel':
+ from _hardware_pixel import HardwarePixel
+ hardware = HardwarePixel(adb)
+ elif model == 'Pixel 2':
+ from _hardware_pixel2 import HardwarePixel2
+ hardware = HardwarePixel2(adb)
elif model == 'Nexus 6P':
from _hardware_nexus_6p import HardwareNexus6P
hardware = HardwareNexus6P(adb)
@@ -294,13 +353,11 @@
else:
hardware = Hardware()
- with hardware:
- SKPBench.run_warmup(hardware.warmup_time, configs[0])
- if FLAGS.resultsfile:
- with open(FLAGS.resultsfile, mode='a+') as resultsfile:
- run_benchmarks(configs, skps, hardware, resultsfile=resultsfile)
- else:
- run_benchmarks(configs, skps, hardware)
+ if FLAGS.resultsfile:
+ with open(FLAGS.resultsfile, mode='a+') as resultsfile:
+ run_benchmarks(configs, srcs, hardware, resultsfile=resultsfile)
+ else:
+ run_benchmarks(configs, srcs, hardware)
if __name__ == '__main__':
diff --git a/src/third_party/skia/tools/skpinfo.cpp b/src/third_party/skia/tools/skpinfo.cpp
index 104322f..2fa2831 100644
--- a/src/third_party/skia/tools/skpinfo.cpp
+++ b/src/third_party/skia/tools/skpinfo.cpp
@@ -5,18 +5,20 @@
* found in the LICENSE file.
*/
-#include "SkCommandLineFlags.h"
-#include "SkPicture.h"
-#include "SkPictureData.h"
-#include "SkStream.h"
-#include "SkFontDescriptor.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkFontDescriptor.h"
+#include "src/core/SkPictureCommon.h"
+#include "src/core/SkPictureData.h"
+#include "tools/flags/CommandLineFlags.h"
-DEFINE_string2(input, i, "", "skp on which to report");
-DEFINE_bool2(version, v, true, "version");
-DEFINE_bool2(cullRect, c, true, "cullRect");
-DEFINE_bool2(flags, f, true, "flags");
-DEFINE_bool2(tags, t, true, "tags");
-DEFINE_bool2(quiet, q, false, "quiet");
+static DEFINE_string2(input, i, "", "skp on which to report");
+static DEFINE_bool2(version, v, true, "version");
+static DEFINE_bool2(cullRect, c, true, "cullRect");
+static DEFINE_bool2(flags, f, true, "flags");
+static DEFINE_bool2(tags, t, true, "tags");
+static DEFINE_bool2(quiet, q, false, "quiet");
// This tool can print simple information about an SKP but its main use
// is just to check if an SKP has been truncated during the recording
@@ -30,8 +32,8 @@
static const int kIOError = 5;
int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Prints information about an skp file");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::SetUsage("Prints information about an skp file");
+ CommandLineFlags::Parse(argc, argv);
if (FLAGS_input.count() != 1) {
if (!FLAGS_quiet) {
@@ -51,7 +53,7 @@
size_t totStreamSize = stream.getLength();
SkPictInfo info;
- if (!SkPicture::InternalOnly_StreamIsSKP(&stream, &info)) {
+ if (!SkPicture_StreamIsSKP(&stream, &info)) {
return kNotAnSKP;
}
@@ -63,30 +65,10 @@
info.fCullRect.fLeft, info.fCullRect.fTop,
info.fCullRect.fRight, info.fCullRect.fBottom);
}
- if (FLAGS_flags && !FLAGS_quiet) {
- SkDebugf("Flags: ");
- bool needsSeparator = false;
- if (info.fFlags & SkPictInfo::kCrossProcess_Flag) {
- SkDebugf("kCrossProcess");
- needsSeparator = true;
- }
- if (info.fFlags & SkPictInfo::kScalarIsFloat_Flag) {
- if (needsSeparator) {
- SkDebugf("|");
- }
- SkDebugf("kScalarIsFloat");
- needsSeparator = true;
- }
- if (info.fFlags & SkPictInfo::kPtrIs64Bit_Flag) {
- if (needsSeparator) {
- SkDebugf("|");
- }
- SkDebugf("kPtrIs64Bit");
- }
- SkDebugf("\n");
- }
- if (!stream.readBool()) {
+ bool hasData;
+ if (!stream.readBool(&hasData)) { return kTruncatedFile; }
+ if (!hasData) {
// If we read true there's a picture playback object flattened
// in the file; if false, there isn't a playback, so we're done
// reading the file.
@@ -94,12 +76,14 @@
}
for (;;) {
- uint32_t tag = stream.readU32();
+ uint32_t tag;
+ if (!stream.readU32(&tag)) { return kTruncatedFile; }
if (SK_PICT_EOF_TAG == tag) {
break;
}
- uint32_t chunkSize = stream.readU32();
+ uint32_t chunkSize;
+ if (!stream.readU32(&chunkSize)) { return kTruncatedFile; }
size_t curPos = stream.getPosition();
// "move" doesn't error out when seeking beyond the end of file
diff --git a/src/third_party/skia/tools/skpmaker.cpp b/src/third_party/skia/tools/skpmaker.cpp
deleted file mode 100644
index a3ccd61..0000000
--- a/src/third_party/skia/tools/skpmaker.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Simple tool to generate SKP files for testing.
- */
-
-#include "SkCanvas.h"
-#include "SkColor.h"
-#include "SkCommandLineFlags.h"
-#include "SkPaint.h"
-#include "SkPicture.h"
-#include "SkPictureRecorder.h"
-#include "SkScalar.h"
-#include "SkStream.h"
-
-#include <stdlib.h>
-
-// Flags used by this file, alphabetically:
-DEFINE_int32(blue, 128, "Value of blue color channel in image, 0-255.");
-DEFINE_int32(border, 4, "Width of the black border around the image.");
-DEFINE_int32(green, 128, "Value of green color channel in image, 0-255.");
-DEFINE_int32(height, 200, "Height of canvas to create.");
-DEFINE_int32(red, 128, "Value of red color channel in image, 0-255.");
-DEFINE_int32(width, 300, "Width of canvas to create.");
-DEFINE_string(writePath, "", "Filepath to write the SKP into.");
-
-// Create a 'width' by 'height' skp with a 'border'-wide black border around
-// a 'color' rectangle.
-static void make_skp(SkScalar width, SkScalar height, SkScalar border, SkColor color,
- const char *writePath) {
- SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(SK_ColorBLACK);
- SkRect r = SkRect::MakeWH(width, height);
- canvas->drawRect(r, paint);
- paint.setColor(color);
- r.inset(border, border);
- canvas->drawRect(r, paint);
- SkFILEWStream stream(writePath);
- recorder.finishRecordingAsPicture()->serialize(&stream);
-}
-
-int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Creates a simple .skp file for testing.");
- SkCommandLineFlags::Parse(argc, argv);
-
- // Validate flags.
- if ((FLAGS_blue < 0) || (FLAGS_blue > 255)) {
- SkDebugf("--blue must be within range [0,255]\n");
- exit(-1);
- }
- if ((FLAGS_green < 0) || (FLAGS_green > 255)) {
- SkDebugf("--green must be within range [0,255]\n");
- exit(-1);
- }
- if (FLAGS_height <= 0) {
- SkDebugf("--height must be >0\n");
- exit(-1);
- }
- if ((FLAGS_red < 0) || (FLAGS_red > 255)) {
- SkDebugf("--red must be within range [0,255]\n");
- exit(-1);
- }
- if (FLAGS_width <= 0) {
- SkDebugf("--width must be >0\n");
- exit(-1);
- }
- if (FLAGS_writePath.isEmpty()) {
- SkDebugf("--writePath must be nonempty\n");
- exit(-1);
- }
-
- SkColor color = SkColorSetRGB(FLAGS_red, FLAGS_green, FLAGS_blue);
- make_skp(SkIntToScalar(FLAGS_width),
- SkIntToScalar(FLAGS_height),
- SkIntToScalar(FLAGS_border),
- color, FLAGS_writePath[0]);
- return 0;
-}
diff --git a/src/third_party/skia/tools/skqp/README.md b/src/third_party/skia/tools/skqp/README.md
new file mode 100644
index 0000000..e652795
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/README.md
@@ -0,0 +1,92 @@
+SkQP
+====
+
+SkQP (Skia Quality Program) is a component of the Android CTS (Compatablity
+Test Suite) that tests an Android device's GPU and OpenGLES & Vulkan drivers
+using Skia's existing unit & rendering tests.
+
+See https://skia.org/dev/testing/skqp for pre-build APKs.
+
+How to build and run the SkQP tests
+-----------------------------------
+
+1. Get the dependencies:
+
+ - You will need Java JDK 8, `git`, and `python`.
+
+ - Install Chromium's [depot\_tools](http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html). Add it to your `PATH`.
+
+ git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'
+ export PATH="${PWD}/depot_tools:${PATH}"
+
+ - Install the [Android NDK](https://developer.android.com/ndk/downloads/).
+
+ ( cd ~; unzip ~/Downloads/android-ndk-*.zip )
+ ANDROID_NDK=$(ls -d ~/android-ndk-*) # Or wherever you installed the Android NDK.
+
+ - Install the [Android SDK](https://developer.android.com/studio/#command-tools).
+ Set the `ANDROID_HOME` environment variable.
+
+ mkdir ~/android-sdk
+ ( cd ~/android-sdk; unzip ~/Downloads/sdk-tools-*.zip )
+ yes | ~/android-sdk/tools/bin/sdkmanager --licenses
+ export ANDROID_HOME=~/android-sdk # Or wherever you installed the Android SDK.
+
+ Put `adb` in your `PATH`.
+
+ export PATH="${PATH}:${ANDROID_HOME}/platform-tools"
+
+2. Get the right version of Skia:
+
+ git clone https://skia.googlesource.com/skia.git
+ cd skia
+ git checkout origin/skqp/dev # or whatever release tag you need
+
+3. Build the APK:
+
+ tools/git-sync-deps
+ tools/skqp/make_universal_apk
+
+4. Build, install, and run.
+
+ adb install -r out/skqp/skqp-universal-debug.apk
+ adb logcat -c
+ adb shell am instrument -w org.skia.skqp
+
+5. Monitor the output with:
+
+ adb logcat TestRunner org.skia.skqp skia "*:S"
+
+ Note the test's output path on the device. It will look something like this:
+
+ 01-23 15:22:12.688 27158 27173 I org.skia.skqp:
+ output written to "/storage/emulated/0/Android/data/org.skia.skqp/files/output"
+
+6. Retrieve and view the report with:
+
+ OUTPUT_LOCATION="/storage/emulated/0/Android/data/org.skia.skqp/files/output"
+ adb pull $OUTPUT_LOCATION /tmp/
+ bin/sysopen /tmp/output/skqp_report/report.html
+
+Running a single test
+---------------------
+
+To run a single test, for example `gles_aarectmodes`:
+
+ adb shell am instrument -e class 'org.skia.skqp.SkQPRunner#gles_aarectmodes' -w org.skia.skqp
+
+Unit tests can be run with the `unitTest_` prefix:
+
+ adb shell am instrument -e class 'org.skia.skqp.SkQPRunner#unitTest_GrSurface -w org.skia.skqp
+
+Run as a non-APK executable
+---------------------------
+
+1. Follow steps 1-3 as above.
+
+2. Build the SkQP program, load files on the device, and run skqp:
+
+ gn gen out/skqp-arm
+ ninja -C out/skqp-arm skqp
+ python tools/skqp/run_skqp_exe out/skqp-arm
+
diff --git a/src/third_party/skia/tools/skqp/README_ALGORITHM.md b/src/third_party/skia/tools/skqp/README_ALGORITHM.md
new file mode 100644
index 0000000..c1eb23b
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/README_ALGORITHM.md
@@ -0,0 +1,96 @@
+SkQP Render Test Algorithm
+==========================
+
+The following is a description of the render test validation algorithm that
+will be used by the version of SkQP that will be released for Android Q-release.
+
+There is a global macro constant: `SK_SKQP_GLOBAL_ERROR_TOLERANCE`, which
+reflects the `gn` variable `skia_skqp_global_error_tolerance`. This is usually
+set to 8.
+
+First, look for a file named `skqp/rendertests.txt` in the
+`platform_tools/android/apps/skqp/src/main/assets` directory. The format of
+this file is: each line contains one render test name, followed by a comma,
+followed by an integer. The integer is the `passing_threshold` for that test.
+
+For each test, we have a `max_image` and a `min_image`. These are PNG-encoded
+images stored in SkQP's APK's asset directory (in the paths `gmkb/${TEST}/min.png`
+and `gmkb/${TEST}/max.png`).
+
+The test input is a rendered image. This will be produced by running one of
+the render tests against the either the `vk` (Vulkan) or `gles` (OpenGL ES)
+Skia backend.
+
+Here is psuedocode for the error calculation:
+
+ function calculate_pixel_error(pixel_value, pixel_max, pixel_min):
+ pixel_error = 0
+
+ for color_channel in { red, green, blue, alpha }:
+ value = get_color(pixel_value, color_channel)
+ v_max = get_color(pixel_max, color_channel)
+ v_min = get_color(pixel_min, color_channel)
+
+ if value > v_max:
+ channel_error = value - v_max
+ elif value < v_min:
+ channel_error = v_min - value
+ else:
+ channel_error = 0
+ pixel_error = max(pixel_error, channel_error)
+
+ return max(0, pixel_error - SK_SKQP_GLOBAL_ERROR_TOLERANCE);
+
+ function get_error(rendered_image, max_image, min_image):
+ assert(dimensions(rendered_image) == dimensions(max_image))
+ assert(dimensions(rendered_image) == dimensions(min_image))
+
+ max_error = 0
+ bad_pixels = 0
+ total_error = 0
+
+ error_image = allocate_bitmap(dimensions(rendered_image))
+
+ for xy in list_all_pixel_coordinates(rendered_image):
+ pixel_error = calculate_pixel_error(rendered_image(xy),
+ max_image(xy),
+ min_image(xy))
+ if pixel_error > 0:
+ for neighboring_xy in find_neighbors(xy):
+ if not inside(neighboring_xy, dimensions(rendered_image)):
+ continue
+ pixel_error = min(pixel_error,
+ calculate_pixel_error(rendered_image(xy),
+ max_image(neighboring_xy),
+ min_image(neighboring_xy)))
+
+ if pixel_error > 0:
+ max_error = max(max_error, pixel_error)
+ bad_pixels += 1
+ total_error += pixel_error
+
+ error_image(xy) = linear_interpolation(black, red, pixel_error)
+ else:
+ error_image(xy) = white
+
+ return ((total_error, max_error, bad_pixels), error_image)
+
+For each render test, there is a threshold value for `total_error`, :
+`passing_threshold`.
+
+If `passing_threshold >= 0 && total_error > passing_threshold`, then the test
+is a failure and is included in the report. if `passing_threshold == -1`, then
+the test always passes, but we do execute the test to verify that the driver
+does not crash.
+
+We generate a report with the following information for each test:
+
+ backend_name,render_test_name,max_error,bad_pixels,total_error
+
+in CSV format in the file `out.csv`. A HTML report of just the failing tests
+is written to the file `report.html`. This version includes four images for
+each test: `rendered_image`, `max_image`, `min_image`, and `error_image`, as
+well as the three metrics: `max_error`, `bad_pixels`, and `total_error`.
+
+
+
diff --git a/src/third_party/skia/tools/skqp/README_GENERATING_MODELS.md b/src/third_party/skia/tools/skqp/README_GENERATING_MODELS.md
new file mode 100644
index 0000000..b852564
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/README_GENERATING_MODELS.md
@@ -0,0 +1,84 @@
+How SkQP Generates Render Test Models
+=====================================
+
+We will, at regular intervals, generate new models from the [master branch of
+Skia][1]. Here is how that process works:
+
+0. Choose a commit to make the branch from
+
+ COMMIT=origin/master
+
+ Or use the script to find the best one:
+
+ cd SKIA_SOURCE_DIRECTORY
+ git fetch origin
+ COMMIT=$(python tools/skqp/find_commit_with_best_gold_results.py \
+ origin/master ^origin/skqp/dev)
+
+1. Get the positively triaged results from Gold and generate models:
+
+ cd SKIA_SOURCE_DIRECTORY
+ git fetch origin
+ git checkout "$COMMIT"
+ python tools/skqp/cut_release.py HEAD~10 HEAD
+
+ This will create the following files:
+
+ platform_tools/android/apps/skqp/src/main/assets/files.checksum
+ platform_tools/android/apps/skqp/src/main/assets/skqp/rendertests.txt
+ platform_tools/android/apps/skqp/src/main/assets/skqp/unittests.txt
+
+ These three files can be commited to Skia to create a new commit. Make
+ `origin/skqp/dev` a parent of this commit (without merging it in), and
+ push this new commit to `origin/skqp/dev`, using this script:
+
+ sh tools/skqp/branch_skqp_dev.sh
+
+ Review and submit the change:
+
+ git push origin HEAD:refs/for/skqp/dev
+ bin/sysopen https://review.skia.org/$(bin/gerrit-number HEAD)
+
+ (Optional) Make a SkQP APK.
+
+ tools/skqp/docker_build_universal_apk.sh
+
+ (Optional) Test the SkQP APK:
+
+ tools/skqp/test_apk.sh (LOCATION)/skqp-universal-debug.apk
+
+ (Once changes land) Upload the SkQP APK.
+
+ tools/skqp/upload_apk HEAD (LOCATION)/skqp-universal-debug.apk
+
+
+`tools/skqp/cut_release.py`
+---------------------------
+
+This tool will call `make_skqp_model` to generate the `m{ax,in}.png` files for
+each render test.
+
+Then it calls `jitter_gms` to see which render tests pass the jitter test.
+`jitter_gms` respects the `bad_gms.txt` file by ignoring the render tests
+enumerated in that file. Tests which pass the jitter test are enumerated in
+the file `good.txt`, those that fail in the `bad.txt` file.
+
+Next, the `skqp/rendertests.txt` file is created. This file lists the render
+tests that will be executed by SkQP. These are the union of the tests
+enumerated in the `good.txt` and `bad.txt` files. If the render test is found
+in the `good.txt` file and the model exists, its per-test threshold is set
+to 0 (a later CL can manually change this, if needed). Otherwise, the
+threshold is set to -1; this indicated that the rendertest will be executed (to
+verify that the driver will not crash), but the output will not be compared
+against the model. Unnecessary models will be removed.
+
+Next, all of the files that represent the models are uploaded to cloud storage.
+A single checksum hash is kept in the `files.checksum` file. This is enough
+to re-download those files later, but we don't have to fill the git repository
+with a lot of binary data.
+
+Finally, a list of the current gpu unit tests is created and stored in
+`skqp/unittests.txt`.
+
+[1]: https://skia.googlesource.com/skia/+log/master "Skia Master Branch"
+[2]: https://gold.skia.org/search "Skia Gold Search"
diff --git a/src/third_party/skia/tools/skqp/bad_gms.txt b/src/third_party/skia/tools/skqp/bad_gms.txt
new file mode 100644
index 0000000..7e7bf51
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/bad_gms.txt
@@ -0,0 +1,11 @@
+arcs_as_paths
+drawbitmaprect
+drawbitmaprect-imagerect
+etc1
+ovals_as_paths
+p3
+perlinnoise
+radial_gradient_precision
+readpixels
+skbug1719
+zero_length_paths_aa
diff --git a/src/third_party/skia/tools/skqp/branch_skqp_dev.sh b/src/third_party/skia/tools/skqp/branch_skqp_dev.sh
new file mode 100755
index 0000000..2662c1e
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/branch_skqp_dev.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+set -xe
+set -- platform_tools/android/apps/skqp/src/main/assets/files.checksum \
+ platform_tools/android/apps/skqp/src/main/assets/skqp/rendertests.txt \
+ platform_tools/android/apps/skqp/src/main/assets/skqp/unittests.txt
+for arg; do [ -f "$arg" ] || exit 1; done
+MSG="$(printf 'Cut SkQP %s\n\nNo-Try: true' "$(date +%Y-%m-%d)")"
+git merge -s ours origin/skqp/dev -m "$MSG"
+git add "$@"
+git commit --amend --reuse-message=HEAD
diff --git a/src/third_party/skia/tools/skqp/clean_app.sh b/src/third_party/skia/tools/skqp/clean_app.sh
new file mode 100755
index 0000000..d6b5284
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/clean_app.sh
@@ -0,0 +1,17 @@
+#! /bin/sh
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+set -e
+
+# Change to the root and remove previously added build assets from the source
+# tree of the SKQP app.
+cd "$(dirname "$0")/../.."
+cd platform_tools/android/apps
+git clean -fxd skqp/build \
+ skqp/src/main/assets/gmkb \
+ skqp/src/main/assets/resources \
+ skqp/src/main/libs \
+ .gradle build viewer/build
diff --git a/src/third_party/skia/tools/skqp/create_apk.py b/src/third_party/skia/tools/skqp/create_apk.py
new file mode 100755
index 0000000..2f6d94e
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/create_apk.py
@@ -0,0 +1,235 @@
+#! /usr/bin/env python
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''
+This script can be run with no arguments, in which case it will produce an
+APK with native libraries for all four architectures: arm, arm64, x86, and
+x64. You can instead list the architectures you want as arguments to this
+script. For example:
+
+ python create_apk.py arm x86
+
+The environment variables ANDROID_NDK and ANDROID_HOME must be set to the
+locations of the Android NDK and SDK.
+
+Additionally, `ninja` should be in your path.
+
+It assumes that the source tree is in the desired state, e.g. by having
+run 'python tools/git-sync-deps' in the root of the skia checkout.
+
+We also assume that the 'resources' directory has been copied to
+'platform_tools/android/apps/skqp/src/main/assets', and the
+'tools/skqp/download_model' script has been run.
+
+Also:
+ * If the environment variable SKQP_BUILD_DIR is set, many of the
+ intermediate build objects will be placed here.
+ * If the environment variable SKQP_OUTPUT_DIR is set, the final APK
+ will be placed in this directory.
+ * If the environment variable SKQP_DEBUG is set, Skia will be compiled
+ in debug mode.
+'''
+
+import os
+import re
+import subprocess
+import sys
+import shutil
+import time
+
+import skqp_gn_args
+
+def print_cmd(cmd, o):
+ m = re.compile('[^A-Za-z0-9_./-]')
+ o.write('+ ')
+ for c in cmd:
+ if m.search(c) is not None:
+ o.write(repr(c) + ' ')
+ else:
+ o.write(c + ' ')
+ o.write('\n')
+ o.flush()
+
+def check_call(cmd, **kwargs):
+ print_cmd(cmd, sys.stdout)
+ return subprocess.check_call(cmd, **kwargs)
+
+def find_name(searchpath, filename):
+ for dirpath, _, filenames in os.walk(searchpath):
+ if filename in filenames:
+ yield os.path.join(dirpath, filename)
+
+def check_ninja():
+ with open(os.devnull, 'w') as devnull:
+ return subprocess.call(['ninja', '--version'],
+ stdout=devnull, stderr=devnull) == 0
+
+def remove(p):
+ if not os.path.islink(p) and os.path.isdir(p):
+ shutil.rmtree(p)
+ elif os.path.lexists(p):
+ os.remove(p)
+ assert not os.path.exists(p)
+
+def makedirs(dst):
+ if not os.path.exists(dst):
+ os.makedirs(dst)
+
+class RemoveFiles(object):
+ def __init__(self, *args):
+ self.args = args
+ def __enter__(self):
+ pass
+ def __exit__(self, a, b, c):
+ for arg in self.args:
+ remove(arg)
+
+class ChDir(object):
+ def __init__(self, d):
+ self.orig = os.getcwd()
+ os.chdir(d)
+ def __enter__(self):
+ pass
+ def __exit__(self, a, b, c):
+ os.chdir(self.orig)
+
+def make_symlinked_subdir(target, working_dir):
+ newdir = os.path.join(working_dir, os.path.basename(target))
+ makedirs(newdir)
+ os.symlink(os.path.relpath(newdir, os.path.dirname(target)), target)
+
+def accept_android_license(android_home):
+ proc = subprocess.Popen(
+ [android_home + '/tools/bin/sdkmanager', '--licenses'],
+ stdin=subprocess.PIPE)
+ while proc.poll() is None:
+ proc.stdin.write('y\n')
+ time.sleep(1)
+
+# pylint: disable=bad-whitespace
+skia_to_android_arch_name_map = {'arm' : 'armeabi-v7a',
+ 'arm64': 'arm64-v8a' ,
+ 'x86' : 'x86' ,
+ 'x64' : 'x86_64' }
+
+def create_apk_impl(opts):
+ build_dir, final_output_dir = opts.build_dir, opts.final_output_dir
+
+ assert os.path.exists('bin/gn') # Did you `tools/git-syc-deps`?
+
+ for d in [build_dir, final_output_dir]:
+ makedirs(d)
+
+ apps_dir = 'platform_tools/android/apps'
+ app = 'skqp'
+ lib = 'lib%s_app.so' % app
+
+ # These are the locations in the tree where the gradle needs or will create
+ # not-checked-in files. Treat them specially to keep the tree clean.
+ remove(build_dir + '/libs')
+ build_paths = [apps_dir + '/.gradle',
+ apps_dir + '/' + app + '/build',
+ apps_dir + '/' + app + '/src/main/libs']
+ for path in build_paths:
+ remove(path)
+ try:
+ make_symlinked_subdir(path, build_dir)
+ except OSError:
+ sys.stderr.write('failed to create symlink "%s"\n' % path)
+
+ lib_dir = '%s/%s/src/main/libs' % (apps_dir, app)
+ apk_build_dir = '%s/%s/build/outputs/apk' % (apps_dir, app)
+ for d in [lib_dir, apk_build_dir]:
+ shutil.rmtree(d, True) # force rebuild
+
+ with RemoveFiles(*build_paths):
+ for arch in opts.architectures:
+ build = os.path.join(build_dir, arch)
+ gn_args = opts.gn_args(arch)
+ args = ' '.join('%s=%s' % (k, v) for k, v in gn_args.items())
+ check_call(['bin/gn', 'gen', build, '--args=' + args])
+ check_call(['ninja', '-C', build, lib])
+ dst = '%s/%s' % (lib_dir, skia_to_android_arch_name_map[arch])
+ makedirs(dst)
+ shutil.copy(os.path.join(build, lib), dst)
+
+ accept_android_license(opts.android_home)
+ env_copy = os.environ.copy()
+ env_copy['ANDROID_HOME'] = opts.android_home
+ env_copy['ANDROID_NDK_HOME'] = opts.android_ndk
+ # Why does gradlew need to be called from this directory?
+ check_call(['apps/gradlew', '-p' 'apps/' + app,
+ '-P', 'suppressNativeBuild',
+ ':%s:assembleUniversalDebug' % app],
+ env=env_copy, cwd='platform_tools/android')
+
+ apk_name = app + "-universal-debug.apk"
+
+ apk_list = list(find_name(apk_build_dir, apk_name))
+ assert len(apk_list) == 1
+
+ out = os.path.join(final_output_dir, apk_name)
+ shutil.move(apk_list[0], out)
+ sys.stdout.write(out + '\n')
+
+ arches = '_'.join(sorted(opts.architectures))
+ copy = os.path.join(final_output_dir, "%s-%s-debug.apk" % (app, arches))
+ shutil.copyfile(out, copy)
+ sys.stdout.write(copy + '\n')
+
+ sys.stdout.write('* * * COMPLETE * * *\n\n')
+
+
+def create_apk(opts):
+ skia_dir = os.path.abspath(os.path.dirname(__file__) + '/../..')
+ assert os.path.exists(skia_dir)
+ with ChDir(skia_dir):
+ create_apk_impl(opts)
+
+class SkQP_Build_Options(object):
+ def __init__(self):
+ assert '/' in [os.sep, os.altsep] # 'a/b' over os.path.join('a', 'b')
+ self.error = ''
+ if not check_ninja():
+ self.error += '`ninja` is not in the path.\n'
+ for var in ['ANDROID_NDK', 'ANDROID_HOME']:
+ if not os.path.exists(os.environ.get(var, '')):
+ self.error += 'Environment variable `%s` is not set.\n' % var
+ self.android_ndk = os.path.abspath(os.environ['ANDROID_NDK'])
+ self.android_home = os.path.abspath(os.environ['ANDROID_HOME'])
+ args = sys.argv[1:]
+ for arg in args:
+ if arg not in skia_to_android_arch_name_map:
+ self.error += ('Argument %r is not in %r\n' %
+ (arg, skia_to_android_arch_name_map.keys()))
+ self.architectures = args if args else skia_to_android_arch_name_map.keys()
+ default_build = os.path.dirname(__file__) + '/../../out/skqp'
+ self.build_dir = os.path.abspath(os.environ.get('SKQP_BUILD_DIR', default_build))
+ self.final_output_dir = os.path.abspath(os.environ.get('SKQP_OUTPUT_DIR', default_build))
+ self.debug = bool(os.environ.get('SKQP_DEBUG', ''))
+
+ def gn_args(self, arch):
+ return skqp_gn_args.GetGNArgs(arch, self.android_ndk, self.debug, 26)
+
+ def write(self, o):
+ for k, v in [('ANDROID_NDK', self.android_ndk),
+ ('ANDROID_HOME', self.android_home),
+ ('SKQP_OUTPUT_DIR', self.final_output_dir),
+ ('SKQP_BUILD_DIR', self.build_dir),
+ ('SKQP_DEBUG', self.debug),
+ ('Architectures', self.architectures)]:
+ o.write('%s = %r\n' % (k, v))
+ o.flush()
+
+def main():
+ options = SkQP_Build_Options()
+ if options.error:
+ sys.stderr.write(options.error + __doc__)
+ sys.exit(1)
+ options.write(sys.stdout)
+ create_apk(options)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/skqp/cut_release.py b/src/third_party/skia/tools/skqp/cut_release.py
new file mode 100755
index 0000000..fba4f6c
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/cut_release.py
@@ -0,0 +1,168 @@
+#! /usr/bin/env python
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+import json
+import md5
+import multiprocessing
+import os
+import shutil
+import sys
+import tempfile
+import urllib
+import urllib2
+
+from subprocess import check_call, check_output
+
+assert '/' in [os.sep, os.altsep] and os.pardir == '..'
+
+ASSETS = 'platform_tools/android/apps/skqp/src/main/assets'
+BUCKET = 'skia-skqp-assets'
+
+def make_skqp_model(arg):
+ name, urls, exe = arg
+ tmp = tempfile.mkdtemp()
+ for url in urls:
+ urllib.urlretrieve(url, tmp + '/' + url[url.rindex('/') + 1:])
+ check_call([exe, tmp, ASSETS + '/gmkb/' + name])
+ shutil.rmtree(tmp)
+ sys.stdout.write(name + ' ')
+ sys.stdout.flush()
+
+def goldgetter(meta, exe):
+ assert os.path.exists(exe)
+ jobs = []
+ for rec in meta:
+ urls = [d['URL'] for d in rec['digests']
+ if d['status'] == 'positive' and
+ (set(d['paramset']['config']) & set(['vk', 'gles']))]
+ if urls:
+ jobs.append((rec['testName'], urls, exe))
+ pool = multiprocessing.Pool(processes=20)
+ pool.map(make_skqp_model, jobs)
+ sys.stdout.write('\n')
+ return set((n for n, _, _ in jobs))
+
+def gold(first_commit, last_commit):
+ c1, c2 = (check_output(['git', 'rev-parse', c]).strip()
+ for c in (first_commit, last_commit))
+ f = urllib2.urlopen('https://public-gold.skia.org/json/export?' + urllib.urlencode([
+ ('fbegin', c1),
+ ('fend', c2),
+ ('query', 'config=gles&config=vk&source_type=gm'),
+ ('pos', 'true'),
+ ('neg', 'false'),
+ ('unt', 'false')
+ ]))
+ j = json.load(f)
+ f.close()
+ return j
+
+def gset(path):
+ s = set()
+ if os.path.isfile(path):
+ with open(path, 'r') as f:
+ for line in f:
+ s.add(line.strip())
+ return s
+
+def make_rendertest_list(models, good, bad):
+ assert good.isdisjoint(bad)
+ do_score = good & models
+ no_score = bad | (good - models)
+ to_delete = models & bad
+ for d in to_delete:
+ path = ASSETS + '/gmkb/' + d
+ if os.path.isdir(path):
+ shutil.rmtree(path)
+ results = dict()
+ for n in do_score:
+ results[n] = 0
+ for n in no_score:
+ results[n] = -1
+ return ''.join('%s,%d\n' % (n, results[n]) for n in sorted(results))
+
+def get_digest(path):
+ m = md5.new()
+ with open(path, 'r') as f:
+ m.update(f.read())
+ return m.hexdigest()
+
+def upload_cmd(path, digest):
+ return ['gsutil', 'cp', path, 'gs://%s/%s' % (BUCKET, digest)]
+
+def upload_model():
+ bucket_url = 'gs://%s/' % BUCKET
+ extant = set((u.replace(bucket_url, '', 1)
+ for u in check_output(['gsutil', 'ls', bucket_url]).splitlines() if u))
+ cmds = []
+ filelist = []
+ for dirpath, _, filenames in os.walk(ASSETS + '/gmkb'):
+ for filename in filenames:
+ path = os.path.join(dirpath, filename)
+ digest = get_digest(path)
+ if digest not in extant:
+ cmds.append(upload_cmd(path, digest))
+ filelist.append('%s;%s\n' % (digest, os.path.relpath(path, ASSETS)))
+ tmp = tempfile.mkdtemp()
+ filelist_path = tmp + '/x'
+ with open(filelist_path, 'w') as o:
+ for l in filelist:
+ o.write(l)
+ filelist_digest = get_digest(filelist_path)
+ if filelist_digest not in extant:
+ cmds.append(upload_cmd(filelist_path, filelist_digest))
+
+ pool = multiprocessing.Pool(processes=20)
+ pool.map(check_call, cmds)
+ shutil.rmtree(tmp)
+ return filelist_digest
+
+def remove(x):
+ if os.path.isdir(x) and not os.path.islink(x):
+ shutil.rmtree(x)
+ if os.path.exists(x):
+ os.remove(x)
+
+def main(first_commit, last_commit):
+ check_call(upload_cmd('/dev/null', get_digest('/dev/null')))
+
+ os.chdir(os.path.dirname(__file__) + '/../..')
+ remove(ASSETS + '/files.checksum')
+ for d in [ASSETS + '/gmkb', ASSETS + '/skqp', ]:
+ remove(d)
+ os.mkdir(d)
+
+ check_call([sys.executable, 'tools/git-sync-deps'],
+ env=dict(os.environ, GIT_SYNC_DEPS_QUIET='T'))
+ build = 'out/ndebug'
+ check_call(['bin/gn', 'gen', build,
+ '--args=cc="clang" cxx="clang++" is_debug=false'])
+ check_call(['ninja', '-C', build,
+ 'jitter_gms', 'list_gpu_unit_tests', 'make_skqp_model'])
+
+ models = goldgetter(gold(first_commit, last_commit), build + '/make_skqp_model')
+
+ check_call([build + '/jitter_gms', 'tools/skqp/bad_gms.txt'])
+
+ with open(ASSETS + '/skqp/rendertests.txt', 'w') as o:
+ o.write(make_rendertest_list(models, gset('good.txt'), gset('bad.txt')))
+
+ remove('good.txt')
+ remove('bad.txt')
+
+ with open(ASSETS + '/skqp/unittests.txt', 'w') as o:
+ o.write(check_output([build + '/list_gpu_unit_tests']))
+
+ with open(ASSETS + '/files.checksum', 'w') as o:
+ o.write(upload_model() + '\n')
+
+ sys.stdout.write(ASSETS + '/files.checksum\n')
+ sys.stdout.write(ASSETS + '/skqp/rendertests.txt\n')
+ sys.stdout.write(ASSETS + '/skqp/unittests.txt\n')
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ sys.stderr.write('Usage:\n %s C1 C2\n\n' % sys.argv[0])
+ sys.exit(1)
+ main(sys.argv[1], sys.argv[2])
diff --git a/src/third_party/skia/tools/skqp/docker_build_universal_apk.sh b/src/third_party/skia/tools/skqp/docker_build_universal_apk.sh
new file mode 100755
index 0000000..963a37b
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/docker_build_universal_apk.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# You may need to run as root for docker permissions.
+#
+# You *must* run `tools/git-sync-deps` first.
+
+if [ "$SKQP_OUTPUT_DIR" ]; then
+ mkdir -p "$SKQP_OUTPUT_DIR" || exit 1
+ OUT="$(cd "$SKQP_OUTPUT_DIR"; pwd)"
+else
+ OUT="$(mktemp -d "${TMPDIR:-/tmp}/skqp_apk.XXXXXXXXXX")"
+fi
+SKIA_ROOT="$(cd "$(dirname "$0")/../.."; pwd)"
+
+cd "${SKIA_ROOT}/infra/skqp/docker"
+
+docker build -t android-skqp ./android-skqp/
+
+NAME=$(date +android_em_%Y%m%d_%H%M%S)
+
+docker run --rm -d --name "$NAME" \
+ --env=DEVICE="Samsung Galaxy S6" \
+ --volume="$SKIA_ROOT":/SRC \
+ --volume="$OUT":/OUT \
+ android-skqp
+
+BUILD="$(docker exec "$NAME" mktemp -d)"
+
+docker exec \
+ --env=SKQP_OUTPUT_DIR=/OUT \
+ --env=SKQP_BUILD_DIR="$BUILD" \
+ "$NAME" /SRC/tools/skqp/make_universal_apk.py
+
+if [ -f "$OUT"/skqp-universal-debug.apk ]; then
+ docker exec "$NAME" find /OUT -type f -exec chmod 0666 '{}' '+'
+fi
+
+docker kill "$NAME"
+
+ls -l "$OUT"/*.apk 2> /dev/null
diff --git a/src/third_party/skia/tools/skqp/docker_run_apk.sh b/src/third_party/skia/tools/skqp/docker_run_apk.sh
new file mode 100755
index 0000000..5c54bf4
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/docker_run_apk.sh
@@ -0,0 +1,43 @@
+#! /bin/sh
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# You may need to run as root for docker permissions.
+#
+# The SKQP_ARGS environment variable affects this script.
+
+if ! [ -f "$1" ] ; then
+ echo "Usage: $0 SKQP_APK_FILE_PATH" >&2
+ exit 1
+fi
+
+APK_DIR="$(cd "$(dirname "$1")"; pwd)"
+APK_FILE="$(basename "$1")"
+DST="$(mktemp -d "${TMPDIR:-/tmp}/skqp_emulated_test.XXXXXXXXXX")"
+SED_CMD='s/^.* org.skia.skqp: output written to "\([^"]*\)".*$/\1/p'
+SKQP="$(cd $(dirname "$0"); pwd)"
+
+set -x
+
+cd "${SKQP}/../../infra/skqp/docker"
+
+docker build -t android-skqp ./android-skqp/ > "$DST"/docker-build || exit 2
+
+docker run --privileged --rm -d \
+ --name android_em \
+ --env=DEVICE="Samsung Galaxy S6" \
+ --env=SKQP_SLEEP="30" \
+ --env=SKQP_ARGS="$SKQP_ARGS" \
+ --volume="$DST":/DST \
+ --volume="$APK_DIR":/APK:ro \
+ --volume="$SKQP":/SKQP:ro \
+ android-skqp > "$DST"/docker-run || exit 3
+
+docker exec android_em sh "/SKQP/run_apk.sh" "/APK/$APK_FILE" "/DST"
+
+docker kill android_em
+
+"${SKQP}/../../bin/sysopen" "$DST"/skqp_report_*/report.html
diff --git a/src/third_party/skia/tools/skqp/download_model b/src/third_party/skia/tools/skqp/download_model
new file mode 100755
index 0000000..68ef50d
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/download_model
@@ -0,0 +1,6 @@
+#! /usr/bin/env python
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import download_model
+download_model.main()
diff --git a/src/third_party/skia/tools/skqp/download_model.py b/src/third_party/skia/tools/skqp/download_model.py
new file mode 100755
index 0000000..fb0020e
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/download_model.py
@@ -0,0 +1,69 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import hashlib
+import multiprocessing
+import os
+import shutil
+import sys
+import tempfile
+import urllib2
+
+def checksum(path):
+ if not os.path.exists(path):
+ return None
+ m = hashlib.md5()
+ with open(path, 'rb') as f:
+ while True:
+ buf = f.read(4096)
+ if not buf:
+ return m.hexdigest()
+ m.update(buf)
+
+def download(md5, path):
+ if not md5 == checksum(path):
+ dirname = os.path.dirname(path)
+ if dirname and not os.path.exists(dirname):
+ try:
+ os.makedirs(dirname)
+ except OSError:
+ pass # ignore race condition
+ url = 'https://storage.googleapis.com/skia-skqp-assets/' + md5
+ with open(path, 'wb') as o:
+ shutil.copyfileobj(urllib2.urlopen(url), o)
+
+def tmp(prefix):
+ fd, path = tempfile.mkstemp(prefix=prefix)
+ os.close(fd)
+ return path
+
+def main():
+ target_dir = os.path.join('platform_tools', 'android', 'apps', 'skqp', 'src', 'main', 'assets')
+ os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, target_dir))
+ checksum_path = 'files.checksum'
+ if not os.path.isfile(checksum_path):
+ sys.stderr.write('Error: "%s" is missing.\n' % os.path.join(target_dir, checksum_path))
+ sys.exit(1)
+ file_list_file = tmp('files_')
+ with open(checksum_path, 'r') as f:
+ md5 = f.read().strip()
+ assert(len(md5) == 32)
+ download(md5, file_list_file)
+ with open(file_list_file, 'r') as f:
+ records = []
+ for line in f:
+ md5, path = line.strip().split(';', 1)
+ records.append((md5, path))
+ sys.stderr.write('Downloading %d files.\n' % len(records))
+ pool = multiprocessing.Pool(processes=multiprocessing.cpu_count() * 2)
+ for record in records:
+ pool.apply_async(download, record, callback=lambda x: sys.stderr.write('.'))
+ pool.close()
+ pool.join()
+ sys.stderr.write('\n')
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/skqp/find_commit_with_best_gold_results.py b/src/third_party/skia/tools/skqp/find_commit_with_best_gold_results.py
new file mode 100755
index 0000000..49d2a4a
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/find_commit_with_best_gold_results.py
@@ -0,0 +1,122 @@
+#! /usr/bin/env python
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import re
+import subprocess
+import sys
+import threading
+import urllib
+import urllib2
+
+
+assert '/' in [os.sep, os.altsep]
+
+
+skia_directory = os.path.abspath(os.path.dirname(__file__) + '/../..')
+
+
+def get_jobs():
+ path = skia_directory + '/infra/bots/jobs.json'
+ reg = re.compile('Test-(?P<os>[A-Za-z0-9_]+)-'
+ '(?P<compiler>[A-Za-z0-9_]+)-'
+ '(?P<model>[A-Za-z0-9_]+)-GPU-'
+ '(?P<cpu_or_gpu_value>[A-Za-z0-9_]+)-'
+ '(?P<arch>[A-Za-z0-9_]+)-'
+ '(?P<configuration>[A-Za-z0-9_]+)-'
+ 'All(-(?P<extra_config>[A-Za-z0-9_]+)|)')
+ keys = ['os', 'compiler', 'model', 'cpu_or_gpu_value', 'arch',
+ 'configuration', 'extra_config']
+ def fmt(s):
+ return s.encode('utf-8') if s is not None else ''
+ with open(path) as f:
+ jobs = json.load(f)
+ for job in jobs:
+ m = reg.match(job)
+ if m is not None:
+ yield [(k, fmt(m.group(k))) for k in keys]
+
+
+def gold_export_url(job, config, first_commit, last_commit):
+ qq = [('source_type', 'gm'), ('config', config)] + job
+ query = [
+ ('fbegin', first_commit),
+ ('fend', last_commit),
+ ('query', urllib.urlencode(qq)),
+ ('pos', 'true'),
+ ('neg', 'false'),
+ ('unt', 'false'),
+ ('head', 'true')
+ ]
+ return 'https://public-gold.skia.org/json/export?' + urllib.urlencode(query)
+
+
+def get_results_for_commit(commit, jobs):
+ sys.stderr.write('%s\n' % commit)
+ sys.stderr.flush()
+ CONFIGS = ['gles', 'vk']
+ passing_tests_for_all_jobs = []
+ def process(url):
+ testResults = json.load(urllib2.urlopen(url))
+ sys.stderr.write('.')
+ sys.stderr.flush()
+ passing_tests = 0
+ for t in testResults:
+ assert t['digests']
+ passing_tests += 1
+ passing_tests_for_all_jobs.append(passing_tests)
+ all_urls = [gold_export_url(job, config, commit, commit)
+ for job in jobs for config in CONFIGS]
+ threads = [threading.Thread(target=process, args=(url,)) for url in all_urls]
+ for t in threads:
+ t.start()
+ for t in threads:
+ t.join()
+ result = sum(passing_tests_for_all_jobs)
+ sys.stderr.write('\n%d\n' % result)
+ sys.stderr.flush()
+ return result
+
+
+def find_best_commit(commits):
+ jobs = [j for j in get_jobs()]
+ results = []
+ for commit_name in commits:
+ commit_hash = subprocess.check_output(['git', 'rev-parse', commit_name]).strip()
+ results.append((commit_hash, get_results_for_commit(commit_hash, jobs)))
+
+ best_result = max(r for h, r in results)
+ for h, r in results:
+ if r == best_result:
+ return h
+ return None
+
+
+def generate_commit_list(args):
+ return subprocess.check_output(['git', 'log', '--format=%H'] + args).splitlines()
+
+
+def main(args):
+ os.chdir(skia_directory)
+ subprocess.check_call(['git', 'fetch', 'origin'])
+ sys.stderr.write('%s\n' % ' '.join(args))
+ commits = generate_commit_list(args)
+ sys.stderr.write('%d\n' % len(commits))
+ best = find_best_commit(commits)
+ sys.stderr.write('DONE:\n')
+ sys.stderr.flush()
+ sys.stdout.write('%s\n' % best)
+
+
+usage = '''Example usage:
+ python %s origin/master ^origin/skqp/dev < /dev/null > LOG 2>&1 & disown
+'''
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ sys.stderr.write(usage % sys.argv[0])
+ sys.exit(1)
+ main(sys.argv[1:])
diff --git a/src/third_party/skia/tools/skqp/generate_gn_args b/src/third_party/skia/tools/skqp/generate_gn_args
new file mode 100755
index 0000000..ad1db01
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/generate_gn_args
@@ -0,0 +1,46 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+import skqp_gn_args
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='Generate args.gn file.')
+ parser.add_argument('target_build_dir')
+ parser.add_argument('android_ndk_dir' )
+ parser.add_argument('--arch', metavar='architecture', default='arm',
+ help='defaults to "arm", valid values: "arm" "arm64" "x86" "x64"')
+ parser.add_argument('--api_level', type=int, metavar='api_level',
+ default=26, help='android API level, defaults to 26')
+ parser.add_argument('--debug', default=False, action='store_true',
+ help='compile native code in debug mode, defaults to false')
+ args = parser.parse_args()
+ result = skqp_gn_args.GetGNArgs(args.arch,
+ os.path.abspath(args.android_ndk_dir),
+ args.debug,
+ args.api_level)
+ return args.target_build_dir, result)
+
+def write_gn(o, args):
+ l = max(len(k) for k in args)
+ for k, v in sorted(args.items()):
+ o.write('%-*s = %s\n' % (l, k, v))
+
+def make_args_gn(out_dir, args):
+ if out_dir == '-':
+ write_gn(sys.stdout, args)
+ return
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir)
+ with open(os.path.join(out_dir, 'args.gn'), 'w') as o:
+ write_gn(o, args)
+
+if __name__ == '__main__':
+ build_dir, args = parse_args()
+ make_args_gn(build_dir, args)
diff --git a/src/third_party/skia/tools/skqp/gn_to_bp.py b/src/third_party/skia/tools/skqp/gn_to_bp.py
new file mode 100755
index 0000000..8fd614a
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/gn_to_bp.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generate Android.bp for Skia from GN configuration.
+
+import argparse
+import json
+import os
+import pprint
+import string
+import subprocess
+import sys
+import tempfile
+
+root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ os.pardir, os.pardir)
+skia_gn_dir = os.path.join(root_dir, 'gn')
+sys.path.insert(0, skia_gn_dir)
+
+import gn_to_bp_utils
+
+from skqp_gn_args import SkqpGnArgs
+
+# First we start off with a template for Android.bp,
+# with holes for source lists and include directories.
+bp = string.Template('''// This file is autogenerated by tools/skqp/gn_to_bp.py.
+
+cc_library_shared {
+ name: "libskqp_app",
+ sdk_version: "26",
+ stl: "libc++_static",
+ compile_multilib: "both",
+
+ cflags: [
+ $cflags
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+
+ cppflags:[
+ $cflags_cc
+ ],
+
+ local_include_dirs: [
+ $local_includes
+ ],
+
+ srcs: [
+ "third_party/vulkanmemoryallocator/GrVulkanMemoryAllocator.cpp",
+ $srcs
+ ],
+
+ arch: {
+ arm: {
+ srcs: [
+ $arm_srcs
+ ],
+
+ neon: {
+ srcs: [
+ $arm_neon_srcs
+ ],
+ },
+ },
+
+ arm64: {
+ srcs: [
+ $arm64_srcs
+ ],
+ },
+
+ mips: {
+ srcs: [
+ $none_srcs
+ ],
+ },
+
+ mips64: {
+ srcs: [
+ $none_srcs
+ ],
+ },
+
+ x86: {
+ srcs: [
+ $x86_srcs
+ ],
+ },
+
+ x86_64: {
+ srcs: [
+ $x86_srcs
+ ],
+ },
+ },
+
+ shared_libs: [
+ "libandroid",
+ "libEGL",
+ "libGLESv2",
+ "liblog",
+ "libvulkan",
+ "libz",
+ ],
+ static_libs: [
+ "libexpat",
+ "libjpeg_static_ndk",
+ "libpng_ndk",
+ "libwebp-decode",
+ "libwebp-encode",
+ ]
+}''')
+
+# We'll run GN to get the main source lists and include directories for Skia.
+gn_args = {
+ 'target_cpu': '"none"',
+ 'target_os': '"android"',
+
+ # setup skqp
+ 'is_debug': 'false',
+ 'ndk_api': '26',
+
+ # specify that the Android.bp will supply the necessary components
+ 'skia_use_system_expat': 'true', # removed this when gn is fixed
+ 'skia_use_system_libpng': 'true',
+ 'skia_use_system_libwebp': 'true',
+ 'skia_use_system_libjpeg_turbo': 'true',
+ 'skia_use_system_zlib': 'true',
+}
+
+for k, v in SkqpGnArgs.iteritems():
+ gn_args[k] = v
+
+js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
+
+def strip_slashes(lst):
+ return {str(p.lstrip('/')) for p in lst}
+
+srcs = strip_slashes(js['targets']['//:libskqp_app']['sources'])
+cflags = strip_slashes(js['targets']['//:libskqp_app']['cflags'])
+cflags_cc = strip_slashes(js['targets']['//:libskqp_app']['cflags_cc'])
+local_includes = strip_slashes(js['targets']['//:libskqp_app']['include_dirs'])
+defines = {str(d) for d in js['targets']['//:libskqp_app']['defines']}
+
+defines.update(["SK_ENABLE_DUMP_GPU", "SK_BUILD_FOR_SKQP"])
+cflags_cc.update(['-Wno-extra-semi-stmt'])
+
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'sources', srcs, None)
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'include_dirs',
+ local_includes, 'freetype')
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'defines',
+ defines, None)
+
+# No need to list headers or other extra flags.
+srcs = {s for s in srcs if not s.endswith('.h')}
+cflags = gn_to_bp_utils.CleanupCFlags(cflags)
+cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
+
+# We need to add the include path to the vulkan defines and header file set in
+# then skia_vulkan_header gn arg that is used for framework builds.
+local_includes.add("platform_tools/android/vulkan")
+
+# Get architecture specific source files
+defs = gn_to_bp_utils.GetArchSources(os.path.join(skia_gn_dir, 'opts.gni'))
+
+# Add source file until fix lands in
+# https://skia-review.googlesource.com/c/skia/+/101820
+srcs.add("src/ports/SkFontMgr_empty_factory.cpp")
+
+# Turn a list of strings into the style bpfmt outputs.
+def bpfmt(indent, lst, sort=True):
+ if sort:
+ lst = sorted(lst)
+ return ('\n' + ' '*indent).join('"%s",' % v for v in lst)
+
+# Most defines go into SkUserConfig.h, where they're seen by Skia and its users.
+gn_to_bp_utils.WriteUserConfig('include/config/SkUserConfig.h', defines)
+
+# OK! We have everything to fill in Android.bp...
+with open('Android.bp', 'w') as f:
+ print >>f, bp.substitute({
+ 'local_includes': bpfmt(8, local_includes),
+ 'srcs': bpfmt(8, srcs),
+ 'cflags': bpfmt(8, cflags, False),
+ 'cflags_cc': bpfmt(8, cflags_cc),
+
+ 'arm_srcs': bpfmt(16, defs['armv7']),
+ 'arm_neon_srcs': bpfmt(20, defs['neon']),
+ 'arm64_srcs': bpfmt(16, defs['arm64'] +
+ defs['crc32']),
+ 'none_srcs': bpfmt(16, defs['none']),
+ 'x86_srcs': bpfmt(16, defs['sse2'] +
+ defs['ssse3'] +
+ defs['sse41'] +
+ defs['sse42'] +
+ defs['avx'] +
+ defs['hsw']),
+ })
+
diff --git a/src/third_party/skia/tools/skqp/jitter_gms.cpp b/src/third_party/skia/tools/skqp/jitter_gms.cpp
new file mode 100644
index 0000000..be26eef
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/jitter_gms.cpp
@@ -0,0 +1,153 @@
+// Copyright 2018 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+// Jitter GMs
+//
+// Re-execute rendering tests with slight translational changes and see if
+// there is a significant change. Print `1` if the named test has no
+// significant change, `0` otherwise
+
+#include "gm/gm.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkExecutor.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkSemaphore.h"
+#include "tools/Registry.h"
+#include "tools/skqp/src/skqp.h"
+#include "tools/skqp/src/skqp_model.h"
+
+#include <math.h>
+#include <algorithm>
+#include <cstdio>
+#include <fstream>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+// Error tolerance distance in 8888 color space with Manhattan metric on color channel.
+static constexpr uint8_t kSkiaSkqpGlobalErrorTolerance = 8;
+
+// Number of times to jitter the canvas.
+static constexpr int kNumberOfJitters = 7;
+
+// Distance to translate the canvas in each jitter (direction will be different each time).
+static constexpr float kJitterMagnitude = 0.03125f;
+
+// The `kNumberOfJitters` different runs will each go in a different direction.
+// this is the angle (in radians) for the first one.
+static constexpr float kPhase = 0.3f;
+
+static void do_gm(SkBitmap* bm, skiagm::GM* gm, SkPoint jitter) {
+ SkASSERT(bm);
+ SkASSERT(gm);
+ SkASSERT(bm->dimensions() == gm->getISize());
+ SkCanvas canvas(*bm);
+ SkAutoCanvasRestore autoCanvasRestore(&canvas, true);
+ canvas.clear(SK_ColorWHITE);
+ canvas.translate(jitter.x(), jitter.y());
+ gm->draw(&canvas);
+ canvas.flush();
+}
+
+// Return true if passes jitter test.
+static bool test_jitter(skiagm::GM* gm) {
+ SkASSERT(gm);
+ SkISize size = gm->getISize();
+ SkBitmap control, experimental;
+ control.allocN32Pixels(size.width(), size.height());
+ experimental.allocN32Pixels(size.width(), size.height());
+ do_gm(&control, gm, {0, 0});
+ for (int i = 0; i < kNumberOfJitters; ++i) {
+ float angle = i * (6.2831853f / kNumberOfJitters) + kPhase;
+ do_gm(&experimental, gm, SkPoint{kJitterMagnitude * cosf(angle),
+ kJitterMagnitude * sinf(angle)});
+ SkQP::RenderOutcome result = skqp::Check(
+ control.pixmap(), control.pixmap(), experimental.pixmap(),
+ kSkiaSkqpGlobalErrorTolerance, nullptr);
+ if (result.fTotalError > 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool do_this_test(const char* name,
+ const std::vector<std::string>& doNotRun,
+ const std::vector<std::string>& testOnlyThese) {
+ for (const std::string& bad : doNotRun) {
+ if (bad == name) {
+ return false;
+ }
+ }
+ for (const std::string& good : testOnlyThese) {
+ if (good == name) {
+ return true;
+ }
+ }
+ return testOnlyThese.empty();
+}
+
+
+int main(int argc, char** argv) {
+ std::vector<std::string> doNotRun;
+ std::vector<std::string> testOnlyThese;
+ if (argc > 1) {
+ std::ifstream ifs(argv[1]);
+ if (ifs.is_open()) {
+ std::string str;
+ while (std::getline(ifs, str)) {
+ doNotRun.push_back(str);
+ }
+ }
+ }
+ if (argc > 2) {
+ for (int i = 2; i < argc; ++i) {
+ testOnlyThese.emplace_back(argv[i]);
+ }
+ }
+ SkGraphics::Init();
+ std::mutex mutex;
+ std::vector<std::string> goodResults;
+ std::vector<std::string> badResults;
+
+ int total = 0;
+ SkSemaphore semaphore;
+ auto executor = SkExecutor::MakeFIFOThreadPool();
+ for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
+ ++total;
+ executor->add([factory, &mutex, &goodResults, &badResults,
+ &semaphore, &doNotRun, &testOnlyThese](){
+ std::unique_ptr<skiagm::GM> gm(factory());
+ const char* name = gm->getName();
+ if (do_this_test(name, doNotRun, testOnlyThese)) {
+ bool success = test_jitter(gm.get());
+ std::lock_guard<std::mutex> lock(mutex);
+ if (success) {
+ goodResults.emplace_back(name);
+ } else {
+ badResults.emplace_back(name);
+ }
+ fputc('.', stderr);
+ fflush(stderr);
+ }
+ semaphore.signal();
+ });
+ }
+ while (total-- > 0) { semaphore.wait(); }
+ fputc('\n', stderr);
+ fflush(stderr);
+ std::sort(goodResults.begin(), goodResults.end());
+ std::sort(badResults.begin(), badResults.end());
+ std::ofstream good("good.txt");
+ std::ofstream bad("bad.txt");
+ for (const std::string& s : goodResults) { good << s << '\n'; }
+ for (const std::string& s : badResults) { bad << s << '\n'; }
+ fprintf(stderr, "good = %u\nbad = %u\n\n",
+ (unsigned)goodResults.size(), (unsigned)badResults.size());
+}
diff --git a/src/third_party/skia/tools/skqp/make_apk.sh b/src/third_party/skia/tools/skqp/make_apk.sh
new file mode 100755
index 0000000..cd1bb7b
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/make_apk.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+# Copyright 2019 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+exec python "$(dirname "$0")"/make_universal_apk.py "$@"
diff --git a/src/third_party/skia/tools/skqp/make_apk_list.py b/src/third_party/skia/tools/skqp/make_apk_list.py
new file mode 100755
index 0000000..dacbc24
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/make_apk_list.py
@@ -0,0 +1,132 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from subprocess import call, check_output, CalledProcessError
+import os
+import re
+import sys
+import tempfile
+
+HEADER = '''<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<title>SkQP Pre-built APKs</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<style>
+body {
+font-family:sans-serif;
+max-width:50em;
+margin:8px auto;
+padding:0 8px;
+}
+table { max-width:100%; border-collapse: collapse; }
+td { padding:12px 8px; vertical-align:top; }
+tr:nth-child(even) {background: #F2F2F2; color:#000;}
+tr:nth-child(odd) {background: #FFFFFF; color:#000;}
+</style>
+</head>
+<body>
+<h1>SkQP Pre-built APKs</h1>
+'''
+FOOTER = '</body>\n</html>\n'
+
+BUCKET = 'skia-skqp'
+
+NAME_FMT = 'skqp-universal-%s.apk'
+
+def get_existing_files():
+ cmd = ['gsutil', 'ls', 'gs://' + BUCKET]
+ try:
+ output = check_output(cmd)
+ except (OSError, CalledProcessError):
+ sys.stderr.write('command: "%s" failed.\n' % ' '.join(cmd))
+ sys.exit(1)
+ result = set()
+ regex = re.compile('gs://%s/%s' % (BUCKET, NAME_FMT % '([0-9a-f]+)'))
+ for line in output.split('\n'):
+ m = regex.match(line.strip())
+ if m is not None:
+ result.add(m.group(1))
+ return result
+
+def find(v, extant):
+ l = min(16, len(v))
+ while l > 8:
+ if v[:l] in extant:
+ return v[:l]
+ l -= 1
+ return None
+
+def nowrap(s):
+ return (s.replace(' ', u'\u00A0'.encode('utf-8'))
+ .replace('-', u'\u2011'.encode('utf-8')))
+
+def rev_parse(arg):
+ if isinstance(arg, tuple):
+ remote_url, branch = arg
+ for remote in check_output(['git', 'remote']).strip().split('\n'):
+ remote = remote.strip()
+ url = check_output(['git', 'remote', 'get-url', remote]).strip()
+ if url == remote_url:
+ arg = remote + '/' + branch
+ break
+ return check_output(['git', 'rev-parse', arg]).strip()
+
+
+def table(o, remote, branch, excludes):
+ env_copy = os.environ.copy()
+ env_copy['TZ'] = ''
+ extant = get_existing_files()
+
+ commits = [rev_parse((remote, branch))]
+ for exclude in excludes:
+ commits.append('^' + rev_parse(exclude))
+
+ o.write('<h2>Remote: %s<br>Branch: %s</h2>\n' % (remote, branch))
+ o.write('<table>\n<tr><th>APK</th><th>Date</th><th>Commit</th></tr>\n')
+ git_cmd = ['git', 'log', '--format=%H;%cd;%<(100,trunc)%s',
+ '--date=format-local:%Y-%m-%d %H:%M:%S %Z'] + commits
+ commits = check_output(git_cmd, env=env_copy)
+ for line in commits.split('\n'):
+ line = line.strip()
+ if not line:
+ continue
+ commit, date, subj = line.split(';', 2)
+ short = find(commit, extant)
+ if short is not None:
+ apk_name = NAME_FMT % short
+ url = 'https://storage.googleapis.com/%s/%s' % (BUCKET, apk_name)
+ else:
+ apk_name, url = '', ''
+ commit_url = '%s/+/%s' % (remote, commit)
+ o.write('<tr>\n<td><a href="%s">%s</a></td>\n'
+ '<td>%s</td>\n<td><a href="%s">%s</a></td>\n</tr>\n' %
+ (url, nowrap(apk_name), nowrap(date), commit_url, subj))
+ o.write('</table>\n')
+
+def main():
+ origin = 'https://skia.googlesource.com/skia'
+ aosp_skqp = 'https://android.googlesource.com/platform/external/skqp'
+
+ assert '/' in [os.sep, os.altsep] and '..' == os.pardir
+ os.chdir(os.path.join(os.path.dirname(__file__), '../..'))
+ d = tempfile.mkdtemp()
+ path = os.path.join(d, 'apklist.html')
+ with open(path, 'w') as o:
+ o.write(HEADER)
+ table(o, origin, 'skqp/dev', [(origin, 'master'), '3e34285f2a0'])
+ table(o, origin, 'skqp/release', [(origin, 'master'), '09ab171c5c0'])
+ table(o, aosp_skqp, 'pie-cts-dev', ['f084c17322'])
+ o.write(FOOTER)
+ print path
+ call([sys.executable, 'bin/sysopen', path])
+ gscmd = 'gsutil -h "Content-Type:text/html" cp "%s" gs://skia-skqp/apklist'
+ print gscmd % path
+
+if __name__ == '__main__':
+ main()
+
diff --git a/src/third_party/skia/tools/skqp/make_skqp_model.cpp b/src/third_party/skia/tools/skqp/make_skqp_model.cpp
new file mode 100644
index 0000000..62ae5d0
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/make_skqp_model.cpp
@@ -0,0 +1,82 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/encode/SkPngEncoder.h"
+#include "src/core/SkOSFile.h"
+
+static void update(SkBitmap* maxBitmap, SkBitmap* minBitmap, const SkBitmap& bm) {
+ SkASSERT(!bm.drawsNothing());
+ SkASSERT(4 == bm.bytesPerPixel());
+ if (maxBitmap->drawsNothing()) {
+ maxBitmap->allocPixels(bm.info());
+ maxBitmap->eraseColor(0x00000000);
+ minBitmap->allocPixels(bm.info());
+ minBitmap->eraseColor(0xFFFFFFFF);
+ }
+ SkASSERT_RELEASE(maxBitmap->info() == bm.info());
+ const SkPixmap& pmin = minBitmap->pixmap();
+ const SkPixmap& pmax = maxBitmap->pixmap();
+ const SkPixmap& pm = bm.pixmap();
+ for (int y = 0; y < pm.height(); ++y) {
+ for (int x = 0; x < pm.width(); ++x) {
+ uint32_t* minPtr = pmin.writable_addr32(x, y);
+ uint32_t* maxPtr = pmax.writable_addr32(x, y);
+ uint8_t minColor[4], maxColor[4], color[4];
+ memcpy(minColor, minPtr, 4);
+ memcpy(maxColor, maxPtr, 4);
+ memcpy(color, pm.addr32(x, y), 4);
+ for (unsigned i = 0; i < 4; ++i) {
+ minColor[i] = std::min(minColor[i], color[i]);
+ maxColor[i] = std::max(maxColor[i], color[i]);
+ }
+ memcpy(minPtr, minColor, 4);
+ memcpy(maxPtr, maxColor, 4);
+ }
+ }
+}
+
+static SkBitmap decode_to_srgb_8888_unpremul(const char* path) {
+ SkBitmap dst;
+ if (auto codec = SkCodec::MakeFromData(SkData::MakeFromFileName(path))) {
+ SkISize size = codec->getInfo().dimensions();
+ SkASSERT(!size.isEmpty());
+ dst.allocPixels(SkImageInfo::Make(
+ size.width(), size.height(), kRGBA_8888_SkColorType,
+ kUnpremul_SkAlphaType, SkColorSpace::MakeSRGB()));
+ if (SkCodec::kSuccess != codec->getPixels(dst.pixmap())) {
+ dst.reset();
+ }
+ }
+ return dst;
+}
+
+bool encode_png(const char* path, const SkPixmap& pixmap) {
+ if (!pixmap.addr()) {
+ return false;
+ }
+ SkPngEncoder::Options encOpts;
+ encOpts.fZLibLevel = 9; // slow encode;
+ SkFILEWStream o(path);
+ return o.isValid() && SkPngEncoder::Encode(&o, pixmap, encOpts);
+}
+
+int main(int argc, char** argv) {
+ SkASSERT_RELEASE(argc > 2);
+ const char* src_dir = argv[1];
+ const char* dst_dir = argv[2];
+ SkBitmap maxBitmap, minBitmap;
+ SkOSFile::Iter iter(src_dir);
+ SkString name;
+ while (iter.next(&name)) {
+ name.prependf("%s/", src_dir);
+ SkBitmap bm = decode_to_srgb_8888_unpremul(name.c_str());
+ if (!bm.drawsNothing()) {
+ update(&maxBitmap, &minBitmap, bm);
+ }
+ }
+ SkASSERT_RELEASE(sk_mkdir(dst_dir));
+ encode_png(SkStringPrintf("%s/min.png", dst_dir).c_str(), minBitmap.pixmap());
+ encode_png(SkStringPrintf("%s/max.png", dst_dir).c_str(), maxBitmap.pixmap());
+}
diff --git a/src/third_party/skia/tools/skqp/make_universal_apk b/src/third_party/skia/tools/skqp/make_universal_apk
new file mode 100755
index 0000000..e90a92d
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/make_universal_apk
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+exec python "$(dirname "$0")"/make_universal_apk.py "$@"
diff --git a/src/third_party/skia/tools/skqp/make_universal_apk.py b/src/third_party/skia/tools/skqp/make_universal_apk.py
new file mode 100755
index 0000000..bbddeb1
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/make_universal_apk.py
@@ -0,0 +1,69 @@
+#! /usr/bin/env python
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''
+This script can be run with no arguments, in which case it will produce an
+APK with native libraries for all four architectures: arm, arm64, x86, and
+x64. You can instead list the architectures you want as arguments to this
+script. For example:
+
+ python make_universal_apk.py arm x86
+
+The environment variables ANDROID_NDK and ANDROID_HOME must be set to the
+locations of the Android NDK and SDK.
+
+Additionally, `ninja` should be in your path.
+
+It assumes that the source tree is in the desired state, e.g. by having
+run 'python tools/git-sync-deps' in the root of the skia checkout.
+
+Also:
+ * If the environment variable SKQP_BUILD_DIR is set, many of the
+ intermediate build objects will be placed here.
+ * If the environment variable SKQP_OUTPUT_DIR is set, the final APK
+ will be placed in this directory.
+ * If the environment variable SKQP_DEBUG is set, Skia will be compiled
+ in debug mode.
+'''
+
+import os
+import sys
+
+import create_apk
+import download_model
+
+def make_apk(opts):
+ assert '/' in [os.sep, os.altsep] # 'a/b' over os.path.join('a', 'b')
+
+ skia_dir = os.path.dirname(__file__) + '/../..'
+ create_apk.makedirs(opts.build_dir)
+ assets_dir = skia_dir + '/platform_tools/android/apps/skqp/src/main/assets'
+ gmkb = assets_dir + '/gmkb'
+ resources_path = assets_dir + '/resources'
+
+ with create_apk.RemoveFiles(resources_path, gmkb): # always clean up
+ create_apk.remove(gmkb)
+ create_apk.make_symlinked_subdir(gmkb, opts.build_dir)
+
+ create_apk.remove(resources_path)
+ os.symlink('../../../../../../../resources', resources_path)
+
+ if os.path.exists(assets_dir + '/files.checksum'):
+ download_model.main()
+ else:
+ sys.stderr.write(
+ '\n* * * Note: SkQP models are missing! * * *\n\n')
+ create_apk.create_apk(opts)
+
+def main():
+ options = create_apk.SkQP_Build_Options()
+ if options.error:
+ sys.stderr.write(options.error + __doc__)
+ sys.exit(1)
+ options.write(sys.stdout)
+ make_apk(options)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/skia/tools/skqp/release.sh b/src/third_party/skia/tools/skqp/release.sh
new file mode 100755
index 0000000..ac898de
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/release.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+cd "$(dirname "$0")/../.."
+
+set -e -x
+
+[ -f platform_tools/android/apps/skqp/src/main/assets/files.checksum ] || exit 1
+[ -f platform_tools/android/apps/skqp/src/main/assets/skqp/rendertests.txt ] || exit 1
+[ -f platform_tools/android/apps/skqp/src/main/assets/skqp/unittests.txt ] || exit 1
+
+python tools/skqp/gn_to_bp.py
+python tools/skqp/download_model
+python tools/skqp/setup_resources
+
+touch MODULE_LICENSE_BSD
+
+cat > platform_tools/android/apps/skqp/src/main/Android.mk <<- "EOM"
+ # Copyright 2019 Google LLC.
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
+ LOCAL_PATH:= $(call my-dir)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE_TAGS := tests optional
+ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+ LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+ LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+ LOCAL_JNI_SHARED_LIBRARIES := libskqp_app
+ LOCAL_MULTILIB := both
+ LOCAL_USE_AAPT2 := true
+ LOCAL_STATIC_ANDROID_LIBRARIES := android-support-design
+ LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt
+ LOCAL_SRC_FILES := $(call all-java-files-under, java)
+ LOCAL_PACKAGE_NAME := CtsSkQPTestCases
+ LOCAL_SDK_VERSION := test_current
+ include $(BUILD_CTS_PACKAGE)
+EOM
+
+cat > include/config/SkUserConfigManual.h <<- "EOM"
+ // Copyright 2019 Google LLC.
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ #ifndef SkUserConfigManual_DEFINED
+ #define SkUserConfigManual_DEFINED
+ // DON'T DEFINE THINGS HERE AS IT WILL RESULT IN DIFFERENCES WITH
+ // THE VERSION OF SKQP PUBLISHED ON SKIA.ORG
+ #endif // SkUserConfigManual_DEFINED
+EOM
+
+cat > platform_tools/android/apps/skqp/src/main/AndroidTest.xml <<- "EOM"
+ <?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Copyright 2019 Google LLC.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+ <configuration description="Config for CTS SkQP test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="not-shardable" value="true" />
+ <option name="config-descriptor:metadata" key="component" value="uitoolkit" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSkQPTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="org.skia.skqp" />
+ <option name="runtime-hint" value="7m" />
+ </test>
+ </configuration>
+EOM
+
+[ -f platform_tools/android/apps/skqp/src/main/assets/.gitignore ] && \
+ git rm platform_tools/android/apps/skqp/src/main/assets/.gitignore
+
+git add \
+ Android.bp \
+ MODULE_LICENSE_BSD \
+ include/config/SkUserConfig.h \
+ include/config/SkUserConfigManual.h \
+ platform_tools/android/apps/skqp/src/main/Android.mk \
+ platform_tools/android/apps/skqp/src/main/AndroidTest.xml \
+ platform_tools/android/apps/skqp/src/main/assets
diff --git a/src/third_party/skia/tools/skqp/run_apk.sh b/src/third_party/skia/tools/skqp/run_apk.sh
new file mode 100644
index 0000000..b35933e
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/run_apk.sh
@@ -0,0 +1,39 @@
+#! /bin/sh
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Note:
+# The ANDROID_SERIAL, SKQP_ARGS, and SKQP_SLEEP environment variables affect
+# this script.
+
+if ! [ -f "$1" ] || ! [ -d "$2" ] ; then
+ echo "Usage: $0 SKQP_APK_FILE_PATH RESULTS_DIRECTORY" >&2
+ exit 1
+fi
+
+SED_CMD='s/^.* org.skia.skqp: output written to "\([^"]*\)".*$/\1/p'
+APK="$1"
+DST="$2"
+
+printf '\n\nAPK = "%s"\nDST = "%s"\n\n' "$APK" "$DST"
+
+set -x
+
+timeout 60 adb wait-for-device || exit 1
+
+sleep ${SKQP_SLEEP:-0}
+
+adb uninstall org.skia.skqp > /dev/null 2>&1
+
+adb install "$APK" || exit 1
+
+adb logcat -c
+
+adb shell am instrument $SKQP_ARGS -w org.skia.skqp 2>&1 | tee "$DST"/stdout
+
+adb logcat -d TestRunner org.skia.skqp skia DEBUG '*:S' > "$DST"/logcat
+
+ODIR="$(sed -n "$SED_CMD" "$DST"/logcat | head -1)"
+
+if adb shell "test -d '$ODIR'"; then adb pull "$ODIR" "$DST"; fi
diff --git a/src/third_party/skia/tools/skqp/run_skqp_exe b/src/third_party/skia/tools/skqp/run_skqp_exe
new file mode 100755
index 0000000..7b17425
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/run_skqp_exe
@@ -0,0 +1,53 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import tempfile
+import sysopen
+import sys
+
+def skqp(build):
+ def adb(*args):
+ sys.stdout.write("adb '" + "' '".join(args) + "'\n")
+ subprocess.check_call(['adb'] + list(args))
+
+ assert os.path.isdir(build)
+ build = os.path.abspath(build)
+
+ os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
+
+ adb('shell', 'rm -rf /data/local/tmp/skqp; mkdir -p /data/local/tmp/skqp')
+
+ adb('push',
+ os.path.join(*'platform_tools/android/apps/skqp/src/main/assets'.split('/')),
+ '/data/local/tmp/skqp/skqp_assets')
+
+ adb('push', os.path.join(build, 'skqp'), '/data/local/tmp/skqp/skqp')
+
+ cmd = "cd /data/local/tmp/skqp; ./skqp skqp_assets report"
+ sys.stdout.write("adb 'shell' '%s'\n" % cmd)
+ ret = subprocess.call(['adb', 'shell', cmd])
+
+ tmpdir = tempfile.mkdtemp(prefix='skqp')
+
+ adb('pull', "/data/local/tmp/report", tmpdir)
+
+ return ret, os.path.join(tmpdir, 'report')
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2 or not os.path.isdir(sys.argv[1]):
+ sys.stderr.write('Usage\n %s BUILD_DIR\n\n' % sys.argv[0])
+ sys.exit(1)
+ try:
+ ret, report = skqp(sys.argv[1])
+ except subprocess.CalledProcessError:
+ sys.stderr.write('Command failed.\n')
+ sys.exit(1)
+
+ sys.stdout.write('\nReturn code: %d\nOutput written to "%s"\n' % (ret, report))
+ sysopen.sysopen(os.path.join(report, 'report.html'))
+
diff --git a/src/third_party/skia/tools/skqp/setup_resources b/src/third_party/skia/tools/skqp/setup_resources
new file mode 100755
index 0000000..22f27a8
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/setup_resources
@@ -0,0 +1,20 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+
+if __name__ == '__main__':
+ skia = os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)
+ dst = os.path.join(skia, 'platform_tools', 'android', 'apps', 'skqp',
+ 'src', 'main', 'assets', 'resources')
+ if os.path.isdir(dst) and not os.path.islink(dst):
+ shutil.rmtree(dst)
+ elif os.path.exists(dst):
+ os.remove(dst)
+ shutil.copytree(os.path.join(skia, 'resources'), dst)
+
diff --git a/src/third_party/skia/tools/skqp/skqp_gn_args.py b/src/third_party/skia/tools/skqp/skqp_gn_args.py
new file mode 100644
index 0000000..1f1f052
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/skqp_gn_args.py
@@ -0,0 +1,32 @@
+# Copyright 2019 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+SkqpGnArgs = {
+ 'extra_cflags': '[ "-DSK_ENABLE_DUMP_GPU", "-DSK_BUILD_FOR_SKQP" ]',
+ 'skia_enable_fontmgr_android': 'false',
+ 'skia_enable_fontmgr_empty': 'true',
+ 'skia_enable_pdf': 'false',
+ 'skia_enable_skottie': 'false',
+ 'skia_skqp_global_error_tolerance': '8',
+ 'skia_tools_require_resources': 'true',
+ 'skia_use_dng_sdk': 'false',
+ 'skia_use_expat': 'true',
+ 'skia_use_icu': 'false',
+ 'skia_use_libheif': 'false',
+ 'skia_use_lua': 'false',
+ 'skia_use_piex': 'false',
+ 'skia_use_vulkan': 'true',
+}
+
+def GetGNArgs(arch, android_ndk, debug, api_level):
+ def gn_quote(s):
+ return '"%s"' % s
+ gn_args = {
+ 'target_cpu': gn_quote(arch),
+ 'ndk': gn_quote(android_ndk),
+ 'is_debug': 'true' if debug else 'false',
+ 'ndk_api': api_level,
+ }
+ gn_args.update(SkqpGnArgs)
+ return gn_args
diff --git a/src/third_party/skia/tools/skqp/src/jni_skqp.cpp b/src/third_party/skia/tools/skqp/src/jni_skqp.cpp
new file mode 100644
index 0000000..43d8dd2
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/jni_skqp.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <mutex>
+
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <jni.h>
+#include <sys/stat.h>
+
+#include "include/core/SkStream.h"
+#include "include/private/SkTo.h"
+#include "tools/ResourceFactory.h"
+
+#include "tools/skqp/src/skqp.h"
+
+////////////////////////////////////////////////////////////////////////////////
+extern "C" {
+JNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nInit(JNIEnv*, jobject, jobject, jstring);
+JNIEXPORT jlong JNICALL Java_org_skia_skqp_SkQP_nExecuteGM(JNIEnv*, jobject, jint, jint);
+JNIEXPORT jobjectArray JNICALL Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv*, jobject, jint);
+JNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nMakeReport(JNIEnv*, jobject);
+} // extern "C"
+////////////////////////////////////////////////////////////////////////////////
+
+static AAssetManager* gAAssetManager = nullptr;
+
+static sk_sp<SkData> open_asset_data(const char* path) {
+ sk_sp<SkData> data;
+ if (gAAssetManager) {
+ if (AAsset* asset = AAssetManager_open(gAAssetManager, path, AASSET_MODE_STREAMING)) {
+ if (size_t size = SkToSizeT(AAsset_getLength(asset))) {
+ data = SkData::MakeUninitialized(size);
+ int ret = AAsset_read(asset, data->writable_data(), size);
+ if (ret != SkToInt(size)) {
+ SkDebugf("ERROR: AAsset_read != AAsset_getLength (%s)\n", path);
+ }
+ }
+ AAsset_close(asset);
+ }
+ }
+ return data;
+}
+
+namespace {
+struct AndroidAssetManager : public SkQPAssetManager {
+ sk_sp<SkData> open(const char* path) override { return open_asset_data(path); }
+};
+}
+
+// TODO(halcanary): Should not have global variables; SkQP Java object should
+// own pointers and manage concurency.
+static AndroidAssetManager gAndroidAssetManager;
+static std::mutex gMutex;
+static SkQP gSkQP;
+
+#define jassert(env, cond, ret) do { if (!(cond)) { \
+ (env)->ThrowNew((env)->FindClass("java/lang/Exception"), \
+ __FILE__ ": assert(" #cond ") failed."); \
+ return ret; } } while (0)
+
+static void set_string_array_element(JNIEnv* env, jobjectArray a, const char* s, unsigned i) {
+ jstring jstr = env->NewStringUTF(s);
+ jassert(env, jstr != nullptr,);
+ env->SetObjectArrayElement(a, (jsize)i, jstr);
+ env->DeleteLocalRef(jstr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<SkData> get_resource(const char* resource) {
+ return open_asset_data((std::string("resources/") + resource).c_str());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T, typename F>
+jobjectArray to_java_string_array(JNIEnv* env,
+ const std::vector<T>& array,
+ F toString) {
+ jclass stringClass = env->FindClass("java/lang/String");
+ jassert(env, stringClass, nullptr);
+ jobjectArray jarray = env->NewObjectArray((jint)array.size(), stringClass, nullptr);
+ jassert(env, jarray != nullptr, nullptr);
+ for (unsigned i = 0; i < array.size(); ++i) {
+ set_string_array_element(env, jarray, std::string(toString(array[i])).c_str(), i);
+ }
+ return jarray;
+}
+
+static std::string to_string(JNIEnv* env, jstring jString) {
+ const char* utf8String = env->GetStringUTFChars(jString, nullptr);
+ jassert(env, utf8String && utf8String[0], "");
+ std::string sString(utf8String);
+ env->ReleaseStringUTFChars(jString, utf8String);
+ return sString;
+}
+
+void Java_org_skia_skqp_SkQP_nInit(JNIEnv* env, jobject object, jobject assetManager,
+ jstring dataDir) {
+ jclass SkQP_class = env->GetObjectClass(object);
+
+ // tools/Resources
+ gResourceFactory = &get_resource;
+
+ std::string reportDirectory = to_string(env, dataDir);
+
+ jassert(env, assetManager,);
+ // This global must be set before using AndroidAssetManager
+ gAAssetManager = AAssetManager_fromJava(env, assetManager);
+ jassert(env, gAAssetManager,);
+
+ std::lock_guard<std::mutex> lock(gMutex);
+ gSkQP.init(&gAndroidAssetManager, reportDirectory.c_str());
+
+ auto backends = gSkQP.getSupportedBackends();
+ jassert(env, backends.size() > 0,);
+ auto gms = gSkQP.getGMs();
+ jassert(env, gms.size() > 0,);
+ auto unitTests = gSkQP.getUnitTests();
+ jassert(env, unitTests.size() > 0,);
+
+ constexpr char kStringArrayType[] = "[Ljava/lang/String;";
+ env->SetObjectField(object, env->GetFieldID(SkQP_class, "mBackends", kStringArrayType),
+ to_java_string_array(env, backends, SkQP::GetBackendName));
+ env->SetObjectField(object, env->GetFieldID(SkQP_class, "mUnitTests", kStringArrayType),
+ to_java_string_array(env, unitTests, SkQP::GetUnitTestName));
+ env->SetObjectField(object, env->GetFieldID(SkQP_class, "mGMs", kStringArrayType),
+ to_java_string_array(env, gms, SkQP::GetGMName));
+}
+
+jlong Java_org_skia_skqp_SkQP_nExecuteGM(JNIEnv* env,
+ jobject object,
+ jint gmIndex,
+ jint backendIndex) {
+ SkQP::RenderOutcome outcome;
+ std::string except;
+ {
+ std::lock_guard<std::mutex> lock(gMutex);
+ jassert(env, backendIndex < (jint)gSkQP.getSupportedBackends().size(), -1);
+ jassert(env, gmIndex < (jint)gSkQP.getGMs().size(), -1);
+ SkQP::SkiaBackend backend = gSkQP.getSupportedBackends()[backendIndex];
+ SkQP::GMFactory gm = gSkQP.getGMs()[gmIndex];
+ std::tie(outcome, except) = gSkQP.evaluateGM(backend, gm);
+ }
+
+ if (!except.empty()) {
+ (void)env->ThrowNew(env->FindClass("org/skia/skqp/SkQPException"), except.c_str());
+ }
+ return (jlong)outcome.fTotalError;
+}
+
+jobjectArray Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv* env,
+ jobject object,
+ jint index) {
+ std::vector<std::string> errors;
+ {
+ jassert(env, index < (jint)gSkQP.getUnitTests().size(), nullptr);
+ std::lock_guard<std::mutex> lock(gMutex);
+ errors = gSkQP.executeTest(gSkQP.getUnitTests()[index]);
+ }
+ if (errors.size() == 0) {
+ return nullptr;
+ }
+ jclass stringClass = env->FindClass("java/lang/String");
+ jassert(env, stringClass, nullptr);
+ jobjectArray array = env->NewObjectArray(errors.size(), stringClass, nullptr);
+ for (unsigned i = 0; i < errors.size(); ++i) {
+ set_string_array_element(env, array, errors[i].c_str(), i);
+ }
+ return (jobjectArray)env->NewGlobalRef(array);
+}
+
+void Java_org_skia_skqp_SkQP_nMakeReport(JNIEnv*, jobject) {
+ std::lock_guard<std::mutex> lock(gMutex);
+ gSkQP.makeReport();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/third_party/skia/tools/skqp/src/skqp.cpp b/src/third_party/skia/tools/skqp/src/skqp.cpp
new file mode 100644
index 0000000..04f0369
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/skqp.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/skqp/src/skqp.h"
+
+#include "gm/gm.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/encode/SkPngEncoder.h"
+#include "include/gpu/GrContext.h"
+#include "include/gpu/GrContextOptions.h"
+#include "include/private/SkImageInfoPriv.h"
+#include "src/core/SkFontMgrPriv.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkStreamPriv.h"
+#include "src/utils/SkOSPath.h"
+#include "tests/Test.h"
+#include "tools/fonts/TestFontMgr.h"
+#include "tools/gpu/gl/GLTestContext.h"
+#include "tools/gpu/vk/VkTestContext.h"
+
+#include <limits.h>
+#include <algorithm>
+#include <cinttypes>
+#include <sstream>
+
+#include "tools/skqp/src/skqp_model.h"
+
+#define IMAGES_DIRECTORY_PATH "images"
+#define PATH_MAX_PNG "max.png"
+#define PATH_MIN_PNG "min.png"
+#define PATH_IMG_PNG "image.png"
+#define PATH_ERR_PNG "errors.png"
+#define PATH_MODEL "model"
+
+static constexpr char kRenderTestCSVReport[] = "out.csv";
+static constexpr char kRenderTestReportPath[] = "report.html";
+static constexpr char kRenderTestsPath[] = "skqp/rendertests.txt";
+static constexpr char kUnitTestReportPath[] = "unit_tests.txt";
+static constexpr char kUnitTestsPath[] = "skqp/unittests.txt";
+
+// Kind of like Python's readlines(), but without any allocation.
+// Calls f() on each line.
+// F is [](const char*, size_t) -> void
+template <typename F>
+static void readlines(const void* data, size_t size, F f) {
+ const char* start = (const char*)data;
+ const char* end = start + size;
+ const char* ptr = start;
+ while (ptr < end) {
+ while (*ptr++ != '\n' && ptr < end) {}
+ size_t len = ptr - start;
+ f(start, len);
+ start = ptr;
+ }
+}
+
+static void get_unit_tests(SkQPAssetManager* mgr, std::vector<SkQP::UnitTest>* unitTests) {
+ std::unordered_set<std::string> testset;
+ auto insert = [&testset](const char* s, size_t l) {
+ SkASSERT(l > 1) ;
+ if (l > 0 && s[l - 1] == '\n') { // strip line endings.
+ --l;
+ }
+ if (l > 0) { // only add non-empty strings.
+ testset.insert(std::string(s, l));
+ }
+ };
+ if (sk_sp<SkData> dat = mgr->open(kUnitTestsPath)) {
+ readlines(dat->data(), dat->size(), insert);
+ }
+ for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
+ if ((testset.empty() || testset.count(std::string(test.name)) > 0) && test.needsGpu) {
+ unitTests->push_back(&test);
+ }
+ }
+ auto lt = [](SkQP::UnitTest u, SkQP::UnitTest v) { return strcmp(u->name, v->name) < 0; };
+ std::sort(unitTests->begin(), unitTests->end(), lt);
+}
+
+static void get_render_tests(SkQPAssetManager* mgr,
+ std::vector<SkQP::GMFactory>* gmlist,
+ std::unordered_map<std::string, int64_t>* gmThresholds) {
+ auto insert = [gmThresholds](const char* s, size_t l) {
+ SkASSERT(l > 1) ;
+ if (l > 0 && s[l - 1] == '\n') { // strip line endings.
+ --l;
+ }
+ if (l == 0) {
+ return;
+ }
+ const char* end = s + l;
+ const char* ptr = s;
+ constexpr char kDelimeter = ',';
+ while (ptr < end && *ptr != kDelimeter) { ++ptr; }
+ if (ptr + 1 >= end) {
+ SkASSERT(false); // missing delimeter
+ return;
+ }
+ std::string key(s, ptr - s);
+ ++ptr; // skip delimeter
+ std::string number(ptr, end - ptr); // null-terminated copy.
+ int64_t value = 0;
+ if (1 != sscanf(number.c_str(), "%" SCNd64 , &value)) {
+ SkASSERT(false); // Not a number
+ return;
+ }
+ gmThresholds->insert({std::move(key), value}); // (*gmThresholds)[s] = value;
+ };
+ if (sk_sp<SkData> dat = mgr->open(kRenderTestsPath)) {
+ readlines(dat->data(), dat->size(), insert);
+ }
+ using GmAndName = std::pair<SkQP::GMFactory, std::string>;
+ std::vector<GmAndName> gmsWithNames;
+ for (skiagm::GMFactory f : skiagm::GMRegistry::Range()) {
+ std::string name = SkQP::GetGMName(f);
+ if ((gmThresholds->empty() || gmThresholds->count(name) > 0)) {
+ gmsWithNames.push_back(std::make_pair(f, std::move(name)));
+ }
+ }
+ std::sort(gmsWithNames.begin(), gmsWithNames.end(),
+ [](GmAndName u, GmAndName v) { return u.second < v.second; });
+ gmlist->reserve(gmsWithNames.size());
+ for (const GmAndName& gmn : gmsWithNames) {
+ gmlist->push_back(gmn.first);
+ }
+}
+
+static std::unique_ptr<sk_gpu_test::TestContext> make_test_context(SkQP::SkiaBackend backend) {
+ using U = std::unique_ptr<sk_gpu_test::TestContext>;
+ switch (backend) {
+// TODO(halcanary): Fuchsia will have SK_SUPPORT_GPU and SK_VULKAN, but *not* SK_GL.
+#ifdef SK_GL
+ case SkQP::SkiaBackend::kGL:
+ return U(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
+ case SkQP::SkiaBackend::kGLES:
+ return U(sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
+#endif
+#ifdef SK_VULKAN
+ case SkQP::SkiaBackend::kVulkan:
+ return U(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
+#endif
+ default:
+ return nullptr;
+ }
+}
+
+static GrContextOptions context_options(skiagm::GM* gm = nullptr) {
+ GrContextOptions grContextOptions;
+ grContextOptions.fAllowPathMaskCaching = true;
+ grContextOptions.fDisableDriverCorrectnessWorkarounds = true;
+ if (gm) {
+ gm->modifyGrContextOptions(&grContextOptions);
+ }
+ return grContextOptions;
+}
+
+static std::vector<SkQP::SkiaBackend> get_backends() {
+ std::vector<SkQP::SkiaBackend> result;
+ SkQP::SkiaBackend backends[] = {
+ #ifdef SK_GL
+ #ifndef SK_BUILD_FOR_ANDROID
+ SkQP::SkiaBackend::kGL, // Used for testing on desktop machines.
+ #endif
+ SkQP::SkiaBackend::kGLES,
+ #endif // SK_GL
+ #ifdef SK_VULKAN
+ SkQP::SkiaBackend::kVulkan,
+ #endif
+ };
+ for (SkQP::SkiaBackend backend : backends) {
+ std::unique_ptr<sk_gpu_test::TestContext> testCtx = make_test_context(backend);
+ if (testCtx) {
+ testCtx->makeCurrent();
+ if (nullptr != testCtx->makeGrContext(context_options())) {
+ result.push_back(backend);
+ }
+ }
+ }
+ SkASSERT_RELEASE(result.size() > 0);
+ return result;
+}
+
+static void print_backend_info(const char* dstPath,
+ const std::vector<SkQP::SkiaBackend>& backends) {
+#ifdef SK_ENABLE_DUMP_GPU
+ SkFILEWStream out(dstPath);
+ out.writeText("[\n");
+ for (SkQP::SkiaBackend backend : backends) {
+ if (std::unique_ptr<sk_gpu_test::TestContext> testCtx = make_test_context(backend)) {
+ testCtx->makeCurrent();
+ if (sk_sp<GrContext> ctx = testCtx->makeGrContext(context_options())) {
+ SkString info = ctx->dump();
+ // remove null
+ out.write(info.c_str(), info.size());
+ out.writeText(",\n");
+ }
+ }
+ }
+ out.writeText("]\n");
+#endif
+}
+
+static void encode_png(const SkBitmap& src, const std::string& dst) {
+ SkFILEWStream wStream(dst.c_str());
+ SkPngEncoder::Options options;
+ bool success = wStream.isValid() && SkPngEncoder::Encode(&wStream, src.pixmap(), options);
+ SkASSERT_RELEASE(success);
+}
+
+static void write_to_file(const sk_sp<SkData>& src, const std::string& dst) {
+ SkFILEWStream wStream(dst.c_str());
+ bool success = wStream.isValid() && wStream.write(src->data(), src->size());
+ SkASSERT_RELEASE(success);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+const char* SkQP::GetBackendName(SkQP::SkiaBackend b) {
+ switch (b) {
+ case SkQP::SkiaBackend::kGL: return "gl";
+ case SkQP::SkiaBackend::kGLES: return "gles";
+ case SkQP::SkiaBackend::kVulkan: return "vk";
+ }
+ return "";
+}
+
+std::string SkQP::GetGMName(SkQP::GMFactory f) {
+ std::unique_ptr<skiagm::GM> gm(f ? f() : nullptr);
+ return std::string(gm ? gm->getName() : "");
+}
+
+const char* SkQP::GetUnitTestName(SkQP::UnitTest t) { return t->name; }
+
+SkQP::SkQP() {}
+
+SkQP::~SkQP() {}
+
+void SkQP::init(SkQPAssetManager* am, const char* reportDirectory) {
+ SkASSERT_RELEASE(!fAssetManager);
+ SkASSERT_RELEASE(am);
+ fAssetManager = am;
+ fReportDirectory = reportDirectory;
+
+ SkGraphics::Init();
+ gSkFontMgr_DefaultFactory = &ToolUtils::MakePortableFontMgr;
+
+ /* If the file "skqp/rendertests.txt" does not exist or is empty, run all
+ render tests. Otherwise only run tests mentioned in that file. */
+ get_render_tests(fAssetManager, &fGMs, &fGMThresholds);
+ /* If the file "skqp/unittests.txt" does not exist or is empty, run all gpu
+ unit tests. Otherwise only run tests mentioned in that file. */
+ get_unit_tests(fAssetManager, &fUnitTests);
+ fSupportedBackends = get_backends();
+
+ print_backend_info((fReportDirectory + "/grdump.txt").c_str(), fSupportedBackends);
+}
+
+std::tuple<SkQP::RenderOutcome, std::string> SkQP::evaluateGM(SkQP::SkiaBackend backend,
+ SkQP::GMFactory gmFact) {
+ SkASSERT_RELEASE(fAssetManager);
+ static constexpr SkQP::RenderOutcome kError = {INT_MAX, INT_MAX, INT64_MAX};
+ static constexpr SkQP::RenderOutcome kPass = {0, 0, 0};
+
+ std::unique_ptr<sk_gpu_test::TestContext> testCtx = make_test_context(backend);
+ if (!testCtx) {
+ return std::make_tuple(kError, "Skia Failure: test context");
+ }
+ testCtx->makeCurrent();
+
+ SkASSERT(gmFact);
+ std::unique_ptr<skiagm::GM> gm(gmFact());
+ SkASSERT(gm);
+ const char* const name = gm->getName();
+ const SkISize size = gm->getISize();
+ const int w = size.width();
+ const int h = size.height();
+ const SkImageInfo info =
+ SkImageInfo::Make(w, h, skqp::kColorType, kPremul_SkAlphaType, nullptr);
+ const SkSurfaceProps props(0, SkSurfaceProps::kLegacyFontHost_InitType);
+
+ sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(
+ testCtx->makeGrContext(context_options(gm.get())).get(),
+ SkBudgeted::kNo, info, 0, &props);
+ if (!surf) {
+ return std::make_tuple(kError, "Skia Failure: gr-context");
+ }
+ gm->draw(surf->getCanvas());
+
+ SkBitmap image;
+ image.allocPixels(SkImageInfo::Make(w, h, skqp::kColorType, skqp::kAlphaType));
+
+ // SkColorTypeBytesPerPixel should be constexpr, but is not.
+ SkASSERT(SkColorTypeBytesPerPixel(skqp::kColorType) == sizeof(uint32_t));
+ // Call readPixels because we need to compare pixels.
+ if (!surf->readPixels(image.pixmap(), 0, 0)) {
+ return std::make_tuple(kError, "Skia Failure: read pixels");
+ }
+ int64_t passingThreshold = fGMThresholds.empty() ? -1 : fGMThresholds[std::string(name)];
+
+ if (-1 == passingThreshold) {
+ return std::make_tuple(kPass, "");
+ }
+ skqp::ModelResult modelResult =
+ skqp::CheckAgainstModel(name, image.pixmap(), fAssetManager);
+
+ if (!modelResult.fErrorString.empty()) {
+ return std::make_tuple(kError, std::move(modelResult.fErrorString));
+ }
+ fRenderResults.push_back(SkQP::RenderResult{backend, gmFact, modelResult.fOutcome});
+ if (modelResult.fOutcome.fMaxError <= passingThreshold) {
+ return std::make_tuple(kPass, "");
+ }
+ std::string imagesDirectory = fReportDirectory + "/" IMAGES_DIRECTORY_PATH;
+ if (!sk_mkdir(imagesDirectory.c_str())) {
+ SkDebugf("ERROR: sk_mkdir('%s');\n", imagesDirectory.c_str());
+ return std::make_tuple(modelResult.fOutcome, "");
+ }
+ std::ostringstream tmp;
+ tmp << imagesDirectory << '/' << SkQP::GetBackendName(backend) << '_' << name << '_';
+ std::string imagesPathPrefix1 = tmp.str();
+ tmp = std::ostringstream();
+ tmp << imagesDirectory << '/' << PATH_MODEL << '_' << name << '_';
+ std::string imagesPathPrefix2 = tmp.str();
+ encode_png(image, imagesPathPrefix1 + PATH_IMG_PNG);
+ encode_png(modelResult.fErrors, imagesPathPrefix1 + PATH_ERR_PNG);
+ write_to_file(modelResult.fMaxPng, imagesPathPrefix2 + PATH_MAX_PNG);
+ write_to_file(modelResult.fMinPng, imagesPathPrefix2 + PATH_MIN_PNG);
+ return std::make_tuple(modelResult.fOutcome, "");
+}
+
+std::vector<std::string> SkQP::executeTest(SkQP::UnitTest test) {
+ SkASSERT_RELEASE(fAssetManager);
+ struct : public skiatest::Reporter {
+ std::vector<std::string> fErrors;
+ void reportFailed(const skiatest::Failure& failure) override {
+ SkString desc = failure.toString();
+ fErrors.push_back(std::string(desc.c_str(), desc.size()));
+ }
+ } r;
+ GrContextOptions options;
+ options.fDisableDriverCorrectnessWorkarounds = true;
+ if (test->fContextOptionsProc) {
+ test->fContextOptionsProc(&options);
+ }
+ test->proc(&r, options);
+ fUnitTestResults.push_back(UnitTestResult{test, r.fErrors});
+ return r.fErrors;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static constexpr char kDocHead[] =
+ "<!doctype html>\n"
+ "<html lang=\"en\">\n"
+ "<head>\n"
+ "<meta charset=\"UTF-8\">\n"
+ "<title>SkQP Report</title>\n"
+ "<style>\n"
+ "img { max-width:48%; border:1px green solid;\n"
+ " image-rendering: pixelated;\n"
+ " background-image:url('data:image/png;base64,iVBORw0KGgoA"
+ "AAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAAXNSR0IArs4c6QAAAAJiS0dEAP+H"
+ "j8y/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH3gUBEi4DGRAQYgAAAB1J"
+ "REFUGNNjfMoAAVJQmokBDdBHgPE/lPFsYN0BABdaAwN6tehMAAAAAElFTkSuQmCC"
+ "'); }\n"
+ "</style>\n"
+ "<script>\n"
+ "function ce(t) { return document.createElement(t); }\n"
+ "function ct(n) { return document.createTextNode(n); }\n"
+ "function ac(u,v) { return u.appendChild(v); }\n"
+ "function br(u) { ac(u, ce(\"br\")); }\n"
+ "function ma(s, c) { var a = ce(\"a\"); a.href = s; ac(a, c); return a; }\n"
+ "function f(backend, gm, e1, e2, e3) {\n"
+ " var b = ce(\"div\");\n"
+ " var x = ce(\"h2\");\n"
+ " var t = backend + \"_\" + gm;\n"
+ " ac(x, ct(t));\n"
+ " ac(b, x);\n"
+ " ac(b, ct(\"backend: \" + backend));\n"
+ " br(b);\n"
+ " ac(b, ct(\"gm name: \" + gm));\n"
+ " br(b);\n"
+ " ac(b, ct(\"maximum error: \" + e1));\n"
+ " br(b);\n"
+ " ac(b, ct(\"bad pixel counts: \" + e2));\n"
+ " br(b);\n"
+ " ac(b, ct(\"total error: \" + e3));\n"
+ " br(b);\n"
+ " var q = \"" IMAGES_DIRECTORY_PATH "/\" + backend + \"_\" + gm + \"_\";\n"
+ " var p = \"" IMAGES_DIRECTORY_PATH "/" PATH_MODEL "_\" + gm + \"_\";\n"
+ " var i = ce(\"img\");\n"
+ " i.src = q + \"" PATH_IMG_PNG "\";\n"
+ " i.alt = \"img\";\n"
+ " ac(b, ma(i.src, i));\n"
+ " i = ce(\"img\");\n"
+ " i.src = q + \"" PATH_ERR_PNG "\";\n"
+ " i.alt = \"err\";\n"
+ " ac(b, ma(i.src, i));\n"
+ " br(b);\n"
+ " ac(b, ct(\"Expectation: \"));\n"
+ " ac(b, ma(p + \"" PATH_MAX_PNG "\", ct(\"max\")));\n"
+ " ac(b, ct(\" | \"));\n"
+ " ac(b, ma(p + \"" PATH_MIN_PNG "\", ct(\"min\")));\n"
+ " ac(b, ce(\"hr\"));\n"
+ " b.id = backend + \":\" + gm;\n"
+ " ac(document.body, b);\n"
+ " l = ce(\"li\");\n"
+ " ac(l, ct(\"[\" + e3 + \"] \"));\n"
+ " ac(l, ma(\"#\" + backend +\":\"+ gm , ct(t)));\n"
+ " ac(document.getElementById(\"toc\"), l);\n"
+ "}\n"
+ "function main() {\n";
+
+static constexpr char kDocMiddle[] =
+ "}\n"
+ "</script>\n"
+ "</head>\n"
+ "<body onload=\"main()\">\n"
+ "<h1>SkQP Report</h1>\n";
+
+static constexpr char kDocTail[] =
+ "<ul id=\"toc\"></ul>\n"
+ "<hr>\n"
+ "<p>Left image: test result<br>\n"
+ "Right image: errors (white = no error, black = smallest error, red = biggest error; "
+ "other errors are a color between black and red.)</p>\n"
+ "<hr>\n"
+ "</body>\n"
+ "</html>\n";
+
+template <typename T>
+inline void write(SkWStream* wStream, const T& text) {
+ wStream->write(text.c_str(), text.size());
+}
+
+void SkQP::makeReport() {
+ SkASSERT_RELEASE(fAssetManager);
+ int glesErrorCount = 0, vkErrorCount = 0, gles = 0, vk = 0;
+
+ if (!sk_isdir(fReportDirectory.c_str())) {
+ SkDebugf("Report destination does not exist: '%s'\n", fReportDirectory.c_str());
+ return;
+ }
+ SkFILEWStream csvOut(SkOSPath::Join(fReportDirectory.c_str(), kRenderTestCSVReport).c_str());
+ SkFILEWStream htmOut(SkOSPath::Join(fReportDirectory.c_str(), kRenderTestReportPath).c_str());
+ SkASSERT_RELEASE(csvOut.isValid() && htmOut.isValid());
+ htmOut.writeText(kDocHead);
+ for (const SkQP::RenderResult& run : fRenderResults) {
+ switch (run.fBackend) {
+ case SkQP::SkiaBackend::kGLES: ++gles; break;
+ case SkQP::SkiaBackend::kVulkan: ++vk; break;
+ default: break;
+ }
+ const char* backendName = SkQP::GetBackendName(run.fBackend);
+ std::string gmName = SkQP::GetGMName(run.fGM);
+ const SkQP::RenderOutcome& outcome = run.fOutcome;
+ auto str = SkStringPrintf("\"%s\",\"%s\",%d,%d,%" PRId64, backendName, gmName.c_str(),
+ outcome.fMaxError, outcome.fBadPixelCount, outcome.fTotalError);
+ write(&csvOut, SkStringPrintf("%s\n", str.c_str()));
+
+ int64_t passingThreshold = fGMThresholds.empty() ? 0 : fGMThresholds[gmName];
+ if (passingThreshold == -1 || outcome.fMaxError <= passingThreshold) {
+ continue;
+ }
+ write(&htmOut, SkStringPrintf(" f(%s);\n", str.c_str()));
+ switch (run.fBackend) {
+ case SkQP::SkiaBackend::kGLES: ++glesErrorCount; break;
+ case SkQP::SkiaBackend::kVulkan: ++vkErrorCount; break;
+ default: break;
+ }
+ }
+ htmOut.writeText(kDocMiddle);
+ write(&htmOut, SkStringPrintf("<p>gles errors: %d (of %d)</br>\n"
+ "vk errors: %d (of %d)</p>\n",
+ glesErrorCount, gles, vkErrorCount, vk));
+ htmOut.writeText(kDocTail);
+ SkFILEWStream unitOut(SkOSPath::Join(fReportDirectory.c_str(), kUnitTestReportPath).c_str());
+ SkASSERT_RELEASE(unitOut.isValid());
+ for (const SkQP::UnitTestResult& result : fUnitTestResults) {
+ unitOut.writeText(GetUnitTestName(result.fUnitTest));
+ if (result.fErrors.empty()) {
+ unitOut.writeText(" PASSED\n* * *\n");
+ } else {
+ write(&unitOut, SkStringPrintf(" FAILED (%u errors)\n", result.fErrors.size()));
+ for (const std::string& err : result.fErrors) {
+ write(&unitOut, err);
+ unitOut.newline();
+ }
+ unitOut.writeText("* * *\n");
+ }
+ }
+}
diff --git a/src/third_party/skia/tools/skqp/src/skqp.h b/src/third_party/skia/tools/skqp/src/skqp.h
new file mode 100644
index 0000000..0ff31bb
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/skqp.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skqp_DEFINED
+#define skqp_DEFINED
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <unordered_set>
+#include <unordered_map>
+#include <vector>
+
+class SkData;
+template <typename T> class sk_sp;
+
+namespace skiagm {
+class GM;
+}
+
+namespace skiatest {
+struct Test;
+}
+
+class SkStreamAsset;
+
+////////////////////////////////////////////////////////////////////////////////
+class SkQPAssetManager {
+public:
+ SkQPAssetManager() {}
+ virtual ~SkQPAssetManager() {}
+ virtual sk_sp<SkData> open(const char* path) = 0;
+private:
+ SkQPAssetManager(const SkQPAssetManager&) = delete;
+ SkQPAssetManager& operator=(const SkQPAssetManager&) = delete;
+};
+
+class SkQP {
+public:
+ enum class SkiaBackend {
+ kGL,
+ kGLES,
+ kVulkan,
+ };
+ using GMFactory = std::unique_ptr<skiagm::GM> (*)();
+ using UnitTest = const skiatest::Test*;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ /** These functions provide a descriptive name for the given value.*/
+ static std::string GetGMName(GMFactory);
+ static const char* GetUnitTestName(UnitTest);
+ static const char* GetBackendName(SkiaBackend);
+
+ SkQP();
+ ~SkQP();
+
+ /**
+ Initialize Skia and the SkQP. Should be executed only once.
+
+ @param assetManager - provides assets for the models. Does not take ownership.
+ @param reportDirectory - where to write out report.
+ */
+ void init(SkQPAssetManager* assetManager, const char* reportDirectory);
+
+ struct RenderOutcome {
+ // All three values will be 0 if the test passes.
+ int fMaxError = 0; // maximum error of all pixel.
+ int fBadPixelCount = 0; // number of pixels with non-zero error.
+ int64_t fTotalError = 0; // sum of error for all bad pixels.
+ };
+
+ /**
+ @return render outcome and error string. Only errors running or
+ evaluating the GM will result in a non-empty error string.
+ */
+ std::tuple<RenderOutcome, std::string> evaluateGM(SkiaBackend, GMFactory);
+
+ /** @return a (hopefully empty) list of errors produced by this unit test. */
+ std::vector<std::string> executeTest(UnitTest);
+
+ /** Call this after running all checks to write a report into the given
+ report directory. */
+ void makeReport();
+
+ /** @return a list of backends that this version of SkQP supports. */
+ const std::vector<SkiaBackend>& getSupportedBackends() const { return fSupportedBackends; }
+ /** @return a list of all Skia GMs in lexicographic order. */
+ const std::vector<GMFactory>& getGMs() const { return fGMs; }
+ /** @return a list of all Skia GPU unit tests in lexicographic order. */
+ const std::vector<UnitTest>& getUnitTests() const { return fUnitTests; }
+ ////////////////////////////////////////////////////////////////////////////
+
+private:
+ struct RenderResult {
+ SkiaBackend fBackend;
+ GMFactory fGM;
+ RenderOutcome fOutcome;
+ };
+ struct UnitTestResult {
+ UnitTest fUnitTest;
+ std::vector<std::string> fErrors;
+ };
+ std::vector<RenderResult> fRenderResults;
+ std::vector<UnitTestResult> fUnitTestResults;
+ std::vector<SkiaBackend> fSupportedBackends;
+ SkQPAssetManager* fAssetManager = nullptr;
+ std::string fReportDirectory;
+ std::vector<UnitTest> fUnitTests;
+ std::vector<GMFactory> fGMs;
+ std::unordered_map<std::string, int64_t> fGMThresholds;
+
+ SkQP(const SkQP&) = delete;
+ SkQP& operator=(const SkQP&) = delete;
+};
+#endif // skqp_DEFINED
+
diff --git a/src/third_party/skia/tools/skqp/src/skqp_main.cpp b/src/third_party/skia/tools/skqp/src/skqp_main.cpp
new file mode 100644
index 0000000..16369cb
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/skqp_main.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <iostream>
+#include <sys/stat.h>
+
+#include "tools/skqp/src/skqp.h"
+
+#include "include/core/SkData.h"
+#include "src/core/SkOSFile.h"
+#include "tools/Resources.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace {
+class StdAssetManager : public SkQPAssetManager {
+public:
+ StdAssetManager(const char* p) : fPrefix(p) {
+ SkASSERT(!fPrefix.empty());
+ //TODO(halcanary): does this need to be changed if I run SkQP in Windows?
+ fPrefix += "/";
+ }
+ sk_sp<SkData> open(const char* path) override {
+ return SkData::MakeFromFileName((fPrefix + path).c_str());
+ }
+private:
+ std::string fPrefix;
+};
+}
+
+static constexpr char kSkipUsage[] =
+ " TEST_MATCH_RULES:"
+ " [~][^]substring[$] [...] of name to run.\n"
+ " Multiple matches may be separated by spaces.\n"
+ " ~ causes a matching name to always be skipped\n"
+ " ^ requires the start of the name to match\n"
+ " $ requires the end of the name to match\n"
+ " ^ and $ requires an exact match\n"
+ " If a name does not match any list entry,\n"
+ " it is skipped unless some list entry starts with ~\n";
+
+static bool should_skip(const char* const* rules, size_t count, const char* name) {
+ size_t testLen = strlen(name);
+ bool anyExclude = count == 0;
+ for (size_t i = 0; i < count; ++i) {
+ const char* matchName = rules[i];
+ size_t matchLen = strlen(matchName);
+ bool matchExclude, matchStart, matchEnd;
+ if ((matchExclude = matchName[0] == '~')) {
+ anyExclude = true;
+ matchName++;
+ matchLen--;
+ }
+ if ((matchStart = matchName[0] == '^')) {
+ matchName++;
+ matchLen--;
+ }
+ if ((matchEnd = matchName[matchLen - 1] == '$')) {
+ matchLen--;
+ }
+ if (matchStart ? (!matchEnd || matchLen == testLen)
+ && strncmp(name, matchName, matchLen) == 0
+ : matchEnd ? matchLen <= testLen
+ && strncmp(name + testLen - matchLen, matchName, matchLen) == 0
+ : strstr(name, matchName) != nullptr) {
+ return matchExclude;
+ }
+ }
+ return !anyExclude;
+}
+
+int main(int argc, char** argv) {
+ if (argc < 3) {
+ std::cerr << "Usage:\n " << argv[0]
+ << " ASSET_DIRECTORY_PATH SKQP_REPORT_PATH [TEST_MATCH_RULES]\n"
+ << kSkipUsage << '\n';
+ return 1;
+ }
+ SetResourcePath((std::string(argv[1]) + "/resources").c_str());
+ if (!sk_mkdir(argv[2])) {
+ std::cerr << "sk_mkdir(" << argv[2] << ") failed.\n";
+ return 2;
+ }
+ StdAssetManager mgr(argv[1]);
+ SkQP skqp;
+ skqp.init(&mgr, argv[2]);
+ int ret = 0;
+
+ const char* const* matchRules = &argv[3];
+ size_t matchRulesCount = (size_t)(argc - 3);
+
+ // Rendering Tests
+ std::ostream& out = std::cout;
+ for (auto backend : skqp.getSupportedBackends()) {
+ auto testPrefix = std::string(SkQP::GetBackendName(backend)) + "_";
+ for (auto gmFactory : skqp.getGMs()) {
+ auto testName = testPrefix + SkQP::GetGMName(gmFactory);
+ if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
+ continue;
+ }
+ out << "Starting: " << testName << std::endl;
+ SkQP::RenderOutcome outcome;
+ std::string except;
+
+ std::tie(outcome, except) = skqp.evaluateGM(backend, gmFactory);
+ if (!except.empty()) {
+ out << "ERROR: " << testName << " (" << except << ")\n";
+ ret = 1;
+ } else if (outcome.fMaxError != 0) {
+ out << "FAILED: " << testName << " (" << outcome.fMaxError << ")\n";
+ ret = 1;
+ } else {
+ out << "Passed: " << testName << "\n";
+ }
+ out.flush();
+ }
+ }
+
+ // Unit Tests
+ for (auto test : skqp.getUnitTests()) {
+ auto testName = std::string("unitTest_") + SkQP::GetUnitTestName(test);
+ if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
+ continue;
+ }
+ out << "Starting test: " << testName << std::endl;
+ std::vector<std::string> errors = skqp.executeTest(test);
+ if (!errors.empty()) {
+ out << "TEST FAILED (" << errors.size() << "): " << testName << "\n";
+ for (const std::string& error : errors) {
+ out << error << "\n";
+ }
+ ret = 1;
+ } else {
+ out << "Test passed: " << testName << "\n";
+ }
+ out.flush();
+ }
+ skqp.makeReport();
+
+ return ret;
+}
diff --git a/src/third_party/skia/tools/skqp/src/skqp_model.cpp b/src/third_party/skia/tools/skqp/src/skqp_model.cpp
new file mode 100644
index 0000000..230a14f
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/skqp_model.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/skqp/src/skqp.h"
+#include "tools/skqp/src/skqp_model.h"
+
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkStream.h"
+#include "src/utils/SkOSPath.h"
+
+#include <limits.h>
+
+#ifndef SK_SKQP_GLOBAL_ERROR_TOLERANCE
+#define SK_SKQP_GLOBAL_ERROR_TOLERANCE 0
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+static inline uint32_t color(const SkPixmap& pm, SkIPoint p) {
+ return *pm.addr32(p.x(), p.y());
+}
+
+static inline bool inside(SkIPoint point, SkISize dimensions) {
+ return (unsigned)point.x() < (unsigned)dimensions.width() &&
+ (unsigned)point.y() < (unsigned)dimensions.height();
+}
+
+SkQP::RenderOutcome skqp::Check(const SkPixmap& minImg,
+ const SkPixmap& maxImg,
+ const SkPixmap& img,
+ unsigned tolerance,
+ SkBitmap* errorOut) {
+ SkQP::RenderOutcome result;
+ SkISize dim = img.info().dimensions();
+ SkASSERT(minImg.info().dimensions() == dim);
+ SkASSERT(maxImg.info().dimensions() == dim);
+ static const SkIPoint kNeighborhood[9] = {
+ { 0, 0}, // ordered by closest pixels first.
+ {-1, 0}, { 1, 0}, { 0, -1}, { 0, 1},
+ {-1, -1}, { 1, -1}, {-1, 1}, { 1, 1},
+ };
+ for (int y = 0; y < dim.height(); ++y) {
+ for (int x = 0; x < dim.width(); ++x) {
+ const SkIPoint xy{x, y};
+ const uint32_t c = color(img, xy);
+ int error = INT_MAX;
+ // loop over neighborhood (halo);
+ for (SkIPoint delta : kNeighborhood) {
+ SkIPoint point = xy + delta;
+ if (inside(point, dim)) { // skip out of pixmap bounds.
+ int err = 0;
+ // loop over four color channels.
+ // Return Manhattan distance in channel-space.
+ for (int component : {0, 8, 16, 24}) {
+ uint8_t v = (c >> component) & 0xFF,
+ vmin = (color(minImg, point) >> component) & 0xFF,
+ vmax = (color(maxImg, point) >> component) & 0xFF;
+ err = SkMax32(err, SkMax32((int)v - (int)vmax, (int)vmin - (int)v));
+ }
+ error = SkMin32(error, err);
+ }
+ }
+ if (error > (int)tolerance) {
+ ++result.fBadPixelCount;
+ result.fTotalError += error;
+ result.fMaxError = SkMax32(error, result.fMaxError);
+ if (errorOut) {
+ if (!errorOut->getPixels()) {
+ errorOut->allocPixels(SkImageInfo::Make(
+ dim.width(), dim.height(),
+ kBGRA_8888_SkColorType,
+ kOpaque_SkAlphaType));
+ errorOut->eraseColor(SK_ColorWHITE);
+ }
+ SkASSERT((unsigned)error < 256);
+ *(errorOut->getAddr32(x, y)) = SkColorSetARGB(0xFF, (uint8_t)error, 0, 0);
+ }
+ }
+ }
+ }
+ return result;
+}
+
+static SkBitmap decode(sk_sp<SkData> data) {
+ SkBitmap bitmap;
+ if (auto codec = SkCodec::MakeFromData(std::move(data))) {
+ SkISize size = codec->getInfo().dimensions();
+ SkASSERT(!size.isEmpty());
+ SkImageInfo info = SkImageInfo::Make(size, skqp::kColorType, skqp::kAlphaType);
+ bitmap.allocPixels(info);
+ if (SkCodec::kSuccess != codec->getPixels(bitmap.pixmap())) {
+ bitmap.reset();
+ }
+ }
+ return bitmap;
+}
+
+skqp::ModelResult skqp::CheckAgainstModel(const char* name,
+ const SkPixmap& pm,
+ SkQPAssetManager* mgr) {
+ skqp::ModelResult result;
+ if (pm.colorType() != kColorType || pm.alphaType() != kAlphaType) {
+ result.fErrorString = "Model failed: source image format.";
+ return result;
+ }
+ if (pm.info().isEmpty()) {
+ result.fErrorString = "Model failed: empty source image";
+ return result;
+ }
+ constexpr char PATH_ROOT[] = "gmkb";
+ SkString img_path = SkOSPath::Join(PATH_ROOT, name);
+ SkString max_path = SkOSPath::Join(img_path.c_str(), kMaxPngPath);
+ SkString min_path = SkOSPath::Join(img_path.c_str(), kMinPngPath);
+
+ result.fMaxPng = mgr->open(max_path.c_str());
+ result.fMinPng = mgr->open(min_path.c_str());
+
+ SkBitmap max_image = decode(result.fMaxPng);
+ SkBitmap min_image = decode(result.fMinPng);
+
+ if (max_image.isNull() || min_image.isNull()) {
+ result.fErrorString = "Model missing";
+ return result;
+ }
+ if (max_image.info().dimensions() != min_image.info().dimensions()) {
+ result.fErrorString = "Model has mismatched data.";
+ return result;
+ }
+
+ if (max_image.info().dimensions() != pm.info().dimensions()) {
+ result.fErrorString = "Model data does not match source size.";
+ return result;
+ }
+ result.fOutcome = Check(min_image.pixmap(),
+ max_image.pixmap(),
+ pm,
+ SK_SKQP_GLOBAL_ERROR_TOLERANCE,
+ &result.fErrors);
+ return result;
+}
diff --git a/src/third_party/skia/tools/skqp/src/skqp_model.h b/src/third_party/skia/tools/skqp/src/skqp_model.h
new file mode 100644
index 0000000..a2feaa0
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/src/skqp_model.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef skqp_model_DEFINED
+#define skqp_model_DEFINED
+
+#include <cstdint>
+#include <string>
+
+#include "include/core/SkBitmap.h"
+
+#include "tools/skqp/src/skqp.h"
+
+class SkQPAssetManager;
+class SkStreamAsset;
+
+namespace skqp {
+
+/** Prefered colortype for comparing test outcomes. */
+constexpr SkColorType kColorType = kRGBA_8888_SkColorType;
+
+/** Prefered alphatype for comparing test outcomes. */
+constexpr SkAlphaType kAlphaType = kUnpremul_SkAlphaType;
+
+/** Where to find the maximum and minimum of the model. */
+constexpr char kMaxPngPath[] = "max.png";
+constexpr char kMinPngPath[] = "min.png";
+
+struct ModelResult {
+ SkBitmap fErrors; // Correct pixels are white, failing pixels scale from black
+ // (1 value off) to red (255 off in some channel).
+ sk_sp<SkData> fMinPng; // original model data, PNG encoded image.
+ sk_sp<SkData> fMaxPng; // original model data, PNG encoded image.
+ SkQP::RenderOutcome fOutcome;
+ std::string fErrorString; // if non-empty, an error occured.
+};
+
+SkQP::RenderOutcome Check(const SkPixmap& minImg,
+ const SkPixmap& maxImg,
+ const SkPixmap& img,
+ unsigned tolerance,
+ SkBitmap* errorOut);
+
+/** Check if the given test image matches the expected results.
+
+ @param name the name of the rendering test that produced the image
+ @param image the image to be tested. Should be kRGBA_8888_SkColorType
+ and kUnpremul_SkAlphaType.
+ @param assetManager provides model data files
+*/
+
+ModelResult CheckAgainstModel(const char* name, const SkPixmap& image,
+ SkQPAssetManager* assetManager);
+}
+#endif // skqp_model_DEFINED
diff --git a/src/third_party/skia/tools/skqp/test_apk.sh b/src/third_party/skia/tools/skqp/test_apk.sh
new file mode 100755
index 0000000..adeb8e3
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/test_apk.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+# If you have more than one device attached, run `adb devices -l` and then set
+# the ANDROID_SERIAL environment variable to the correct serial number.
+
+APK="$1"
+shift
+
+if ! [ -f "$APK" ]; then
+ cat >&2 <<- EOM
+
+ Usage:
+ $0 SKQP_APK_FILE_PATH [OPTIONAL_TESTS_TO_RUN...]
+
+ e.g.:
+ $0 skqp-universal-debug.apk
+ or:
+ $0 skqp-universal-debug.apk vk_hairmodes gles_gammatext gles_aarectmodes
+
+ EOM
+ exit 1
+fi
+
+if [ "$#" -gt 0 ]; then
+ SKQP_ARGS="-e class org.skia.skqp.SkQPRunner#${1}"
+ shift
+ for arg; do
+ SKQP_ARGS="${SKQP_ARGS},org.skia.skqp.SkQPRunner#${arg}"
+ done
+ export SKQP_ARGS
+fi
+
+TDIR="$(mktemp -d "${TMPDIR:-/tmp}/skqp_report.XXXXXXXXXX")"
+THIS="$(dirname "$0")"
+
+sh "$THIS/run_apk.sh" "$APK" "$TDIR"
+
+"$THIS/../../bin/sysopen" "$TDIR"/skqp_report_*/report.html
diff --git a/src/third_party/skia/tools/skqp/upload_apk b/src/third_party/skia/tools/skqp/upload_apk
new file mode 100755
index 0000000..6eb242b
--- /dev/null
+++ b/src/third_party/skia/tools/skqp/upload_apk
@@ -0,0 +1,13 @@
+#! /bin/sh
+# Copyright 2018 Google LLC.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+if [ -z "$1" ] || [ -z "$2" ]; then
+ echo usage: $0 COMMIT APK_PATH >&2
+ exit 1;
+fi
+NAME="skia-skqp/skqp-universal-$(git rev-parse "$1" | cut -b 1-16).apk"
+gsutil cp "$2" "gs://$NAME"
+echo "https://storage.googleapis.com/$NAME"
+python tools/skqp/make_apk_list.py
+
diff --git a/src/third_party/skia/tools/skui/InputState.h b/src/third_party/skia/tools/skui/InputState.h
new file mode 100644
index 0000000..90d5c6c
--- /dev/null
+++ b/src/third_party/skia/tools/skui/InputState.h
@@ -0,0 +1,14 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef skui_inputstate_DEFINED
+#define skui_inputstate_DEFINED
+namespace skui {
+enum class InputState {
+ kDown,
+ kUp,
+ kMove, // only valid for mouse
+ kRight, // only valid for fling
+ kLeft, // only valid for fling
+};
+}
+#endif // skui_inputstate_DEFINED
diff --git a/src/third_party/skia/tools/skui/Key.h b/src/third_party/skia/tools/skui/Key.h
new file mode 100644
index 0000000..d8d2cf7
--- /dev/null
+++ b/src/third_party/skia/tools/skui/Key.h
@@ -0,0 +1,59 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef skui_key_DEFINED
+#define skui_key_DEFINED
+namespace skui {
+enum class Key {
+ kNONE, //corresponds to android's UNKNOWN
+
+ kLeftSoftKey,
+ kRightSoftKey,
+
+ kHome, //!< the home key - added to match android
+ kBack, //!< (CLR)
+ kSend, //!< the green (talk) key
+ kEnd, //!< the red key
+
+ k0,
+ k1,
+ k2,
+ k3,
+ k4,
+ k5,
+ k6,
+ k7,
+ k8,
+ k9,
+ kStar, //!< the * key
+ kHash, //!< the # key
+
+ kUp,
+ kDown,
+ kLeft,
+ kRight,
+
+ // Keys needed by ImGui
+ kTab,
+ kPageUp,
+ kPageDown,
+ kDelete,
+ kEscape,
+ kShift,
+ kCtrl,
+ kOption, // AKA Alt
+ kA,
+ kC,
+ kV,
+ kX,
+ kY,
+ kZ,
+
+ kOK, //!< the center key
+
+ kVolUp, //!< volume up - match android
+ kVolDown, //!< volume down - same
+ kPower, //!< power button - same
+ kCamera, //!< camera - same
+};
+}
+#endif // skui_key_DEFINED
diff --git a/src/third_party/skia/tools/skui/ModifierKey.h b/src/third_party/skia/tools/skui/ModifierKey.h
new file mode 100644
index 0000000..09c5536
--- /dev/null
+++ b/src/third_party/skia/tools/skui/ModifierKey.h
@@ -0,0 +1,22 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef skui_modifierkey_defined
+#define skui_modifierkey_defined
+
+#include "include/private/SkBitmaskEnum.h"
+
+namespace skui {
+enum class ModifierKey {
+ kNone = 0,
+ kShift = 1 << 0,
+ kControl = 1 << 1,
+ kOption = 1 << 2, // same as ALT
+ kCommand = 1 << 3,
+ kFirstPress = 1 << 4,
+};
+}
+
+namespace skstd {
+template <> struct is_bitmask_enum<skui::ModifierKey> : std::true_type {};
+}
+#endif // skui_modifierkey_defined
diff --git a/src/third_party/skia/tools/svg/README.md b/src/third_party/skia/tools/svg/README.md
index 501f3c6..a3718c2 100644
--- a/src/third_party/skia/tools/svg/README.md
+++ b/src/third_party/skia/tools/svg/README.md
@@ -7,13 +7,19 @@
svgs.txt
--------
This text file contains an SVG URL per line.
-The SVGs in this file have been downloaded from the internal doc here:
-https://docs.google.com/document/d/1kYRvUxZTnm1tI_0bTU0BX9jqSSTqPUhGXJVcD3Rcg2c/edit
+It is a list of the SVG files used to test rendering correctness.
+svgs_parse_only.txt
+-------------------
+This text file contains an SVG URL per line.
+It is a list of the SVG files used to exercise the SVG parsing code.
svg_downloader.py
-----------------
-This python script parses svgs.txt and downloads SVGs into a specified directory.
+This python script parses txt files and downloads SVGs into a specified directory.
The script can be run by hand:
$ python svg_downloader.py --output_dir /tmp/svgs/
+OR
+$ python svg_downloader.py --output_dir /tmp/svgs/ --svgs_file svgs_parse_only.txt --prefix svgparse_
+
diff --git a/src/third_party/skia/tools/svg/svg_downloader.py b/src/third_party/skia/tools/svg/svg_downloader.py
index 94a0b6f..769c8ff 100644
--- a/src/third_party/skia/tools/svg/svg_downloader.py
+++ b/src/third_party/skia/tools/svg/svg_downloader.py
@@ -15,11 +15,11 @@
PARENT_DIR = os.path.dirname(os.path.realpath(__file__))
-def downloadSVGs(svgs_file, output_dir):
+def downloadSVGs(svgs_file, output_dir, prefix):
with open(svgs_file, 'r') as f:
for url in f.xreadlines():
svg_url = url.strip()
- dest_file = os.path.join(output_dir, os.path.basename(svg_url))
+ dest_file = os.path.join(output_dir, prefix + os.path.basename(svg_url))
print 'Downloading %s' % svg_url
urllib.urlretrieve(svg_url, dest_file)
@@ -34,8 +34,12 @@
option_parser.add_option(
'-o', '--output_dir',
help='The output dir where downloaded SVGs will be stored in.')
+ option_parser.add_option(
+ '-p', '--prefix',
+ help='The prefix which downloaded SVG file will begin with.',
+ default='')
options, unused_args = option_parser.parse_args()
if not options.output_dir:
raise Exception('Must specify --output_dir')
- sys.exit(downloadSVGs(options.svgs_file, options.output_dir))
+ sys.exit(downloadSVGs(options.svgs_file, options.output_dir, options.prefix))
diff --git a/src/third_party/skia/tools/svg/svgs.txt b/src/third_party/skia/tools/svg/svgs.txt
index 0ffc80a..1fff186 100644
--- a/src/third_party/skia/tools/svg/svgs.txt
+++ b/src/third_party/skia/tools/svg/svgs.txt
@@ -1,68 +1,10 @@
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/AJ_Digital_Camera.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/acid.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/alphachannel.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/bozo.svg
+https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/car.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/rg1024_green_grapes.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/gallardo.svg
https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/cartman.svg
https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/bzrfeed.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/car.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/compass.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/displayWebStats.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/eff.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/fsm.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/gallardo.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/rg1024_green_grapes.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/usaf.svg
-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/yinyang.svg
-https://upload.wikimedia.org/wikipedia/commons/6/6d/Alabama-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/2/2b/Alaska-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/7/7e/Arizona-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/0/0f/Seal_of_California.svg
-https://upload.wikimedia.org/wikipedia/commons/5/51/Colorado-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e5/Connecticut-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/c/c0/Delaware-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/b/bf/Florida-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e0/Georgia-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/c/c5/Hawaii-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/4/49/Idaho-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e7/Seal_of_Illinois.svg
-https://upload.wikimedia.org/wikipedia/commons/c/c4/Indiana-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/5/5a/Iowa-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/4/45/Seal_of_Kansas.svg
-https://upload.wikimedia.org/wikipedia/commons/3/35/Seal_of_Kentucky.svg
-https://upload.wikimedia.org/wikipedia/commons/2/2f/Seal_of_Louisiana.svg
-https://upload.wikimedia.org/wikipedia/commons/a/a0/Maine-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/0/00/Seal_of_Maryland_%28reverse%29.svg
-https://upload.wikimedia.org/wikipedia/commons/8/82/Seal_of_Massachusetts.svg
-https://upload.wikimedia.org/wikipedia/commons/3/3f/Seal_of_Michigan.svg
-https://upload.wikimedia.org/wikipedia/commons/6/63/Minnesota-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e3/Seal_of_Mississippi_(2014).svg
-https://upload.wikimedia.org/wikipedia/commons/d/de/Seal_of_Missouri.svg
-https://upload.wikimedia.org/wikipedia/commons/e/ed/Montana-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/6/60/Nebraska-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/7/77/Nevada-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/a/aa/Seal_of_New_Hampshire.svg
-https://upload.wikimedia.org/wikipedia/commons/8/8d/Seal_of_New_Jersey.svg
-https://upload.wikimedia.org/wikipedia/commons/3/3b/NewMexico-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/c/ca/NewYork-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/7/72/Seal_of_North_Carolina.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e7/NorthDakota-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/6/69/Seal_of_Ohio_%281967-1996%29.svg
-https://upload.wikimedia.org/wikipedia/commons/3/39/Seal_of_Oklahoma.svg
-https://upload.wikimedia.org/wikipedia/commons/c/c9/Oregon-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/e/e8/Pennsylvania_state_seal.svg
-https://upload.wikimedia.org/wikipedia/commons/7/73/RhodeIsland-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/8/80/Seal_of_South_Carolina.svg
-https://upload.wikimedia.org/wikipedia/commons/b/bb/SouthDakota-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/3/3c/Seal_of_Tennessee.svg
-https://upload.wikimedia.org/wikipedia/commons/c/cb/Seal_of_Texas.svg
-https://upload.wikimedia.org/wikipedia/commons/7/72/Seal_of_Utah_%28Alternate%29.svg
-https://upload.wikimedia.org/wikipedia/commons/5/5b/Vermont_state_seal.svg
-https://upload.wikimedia.org/wikipedia/commons/6/6f/Seal_of_Virginia.svg
-https://upload.wikimedia.org/wikipedia/commons/9/92/Washington-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/9/92/WestVirginia-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/b/b3/Wisconsin-StateSeal.svg
-https://upload.wikimedia.org/wikipedia/commons/c/c0/Wyoming-StateSeal.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg
https://upload.wikimedia.org/wikipedia/commons/d/df/Seal_of_American_Samoa.svg
-https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg
-https://upload.wikimedia.org/wikipedia/commons/6/6c/Trajans-Column-lower-animated.svg
+https://upload.wikimedia.org/wikipedia/commons/e/e7/Seal_of_Illinois.svg
+https://upload.wikimedia.org/wikipedia/commons/6/63/A_large_blank_world_map_with_oceans_marked_in_blue.svg
diff --git a/src/third_party/skia/tools/svg/svgs_parse_only.txt b/src/third_party/skia/tools/svg/svgs_parse_only.txt
new file mode 100644
index 0000000..4aab1cb
--- /dev/null
+++ b/src/third_party/skia/tools/svg/svgs_parse_only.txt
@@ -0,0 +1,59 @@
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/AJ_Digital_Camera.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/acid.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/alphachannel.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/bozo.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/compass.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/displayWebStats.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/eff.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/fsm.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/usaf.svg
+https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/yinyang.svg
+https://upload.wikimedia.org/wikipedia/commons/6/6d/Alabama-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/2/2b/Alaska-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/7/7e/Arizona-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/0/0f/Seal_of_California.svg
+https://upload.wikimedia.org/wikipedia/commons/5/51/Colorado-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/e/e5/Connecticut-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/c/c0/Delaware-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/b/bf/Florida-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/e/e0/Georgia-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/c/c5/Hawaii-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/4/49/Idaho-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/c/c4/Indiana-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/5/5a/Iowa-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/4/45/Seal_of_Kansas.svg
+https://upload.wikimedia.org/wikipedia/commons/3/35/Seal_of_Kentucky.svg
+https://upload.wikimedia.org/wikipedia/commons/2/2f/Seal_of_Louisiana.svg
+https://upload.wikimedia.org/wikipedia/commons/a/a0/Maine-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/0/00/Seal_of_Maryland_%28reverse%29.svg
+https://upload.wikimedia.org/wikipedia/commons/8/82/Seal_of_Massachusetts.svg
+https://upload.wikimedia.org/wikipedia/commons/3/3f/Seal_of_Michigan.svg
+https://upload.wikimedia.org/wikipedia/commons/6/63/Minnesota-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/d/d1/Seal_of_Mississippi_%282014-present%29.svg
+https://upload.wikimedia.org/wikipedia/commons/d/de/Seal_of_Missouri.svg
+https://upload.wikimedia.org/wikipedia/commons/e/ed/Montana-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/6/60/Nebraska-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/7/77/Nevada-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/a/aa/Seal_of_New_Hampshire.svg
+https://upload.wikimedia.org/wikipedia/commons/8/8d/Seal_of_New_Jersey.svg
+https://upload.wikimedia.org/wikipedia/commons/3/3b/NewMexico-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/c/ca/NewYork-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/7/72/Seal_of_North_Carolina.svg
+https://upload.wikimedia.org/wikipedia/commons/e/e7/NorthDakota-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/6/69/Seal_of_Ohio_%281967-1996%29.svg
+https://upload.wikimedia.org/wikipedia/commons/3/39/Seal_of_Oklahoma.svg
+https://upload.wikimedia.org/wikipedia/commons/c/c9/Oregon-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/e/e8/Pennsylvania_state_seal.svg
+https://upload.wikimedia.org/wikipedia/commons/7/73/RhodeIsland-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/8/80/Seal_of_South_Carolina.svg
+https://upload.wikimedia.org/wikipedia/commons/b/bb/SouthDakota-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/3/3c/Seal_of_Tennessee.svg
+https://upload.wikimedia.org/wikipedia/commons/c/cb/Seal_of_Texas.svg
+https://upload.wikimedia.org/wikipedia/commons/7/72/Seal_of_Utah_%28Alternate%29.svg
+https://upload.wikimedia.org/wikipedia/commons/5/5b/Vermont_state_seal.svg
+https://upload.wikimedia.org/wikipedia/commons/6/6f/Seal_of_Virginia.svg
+https://upload.wikimedia.org/wikipedia/commons/9/92/Washington-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/9/92/WestVirginia-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/b/b3/Wisconsin-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/c/c0/Wyoming-StateSeal.svg
+https://upload.wikimedia.org/wikipedia/commons/6/6c/Trajans-Column-lower-animated.svg
diff --git a/src/third_party/skia/tools/test_font_data.cpp b/src/third_party/skia/tools/test_font_data.cpp
deleted file mode 100644
index ff0aacc..0000000
--- a/src/third_party/skia/tools/test_font_data.cpp
+++ /dev/null
@@ -1,8622 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Auto-generated by create_test_font.cpp
-
-const SkScalar CourierNewkNormalPoints[] = {
-0.339355f, -0.571289f, 0.320801f, -0.240234f, 0.319824f, -0.224609f, 0.314209f, -0.218262f,
-0.308594f, -0.211914f, 0.300293f, -0.211914f, 0.291504f, -0.211914f, 0.285889f, -0.218262f,
-0.280273f, -0.224609f, 0.279297f, -0.240234f, 0.26123f, -0.571289f, 0.260254f, -0.583008f,
-0.260254f, -0.588379f, 0.260254f, -0.60498f, 0.271729f, -0.616211f, 0.283203f, -0.627441f,
-0.300293f, -0.627441f, 0.317383f, -0.627441f, 0.328613f, -0.616211f, 0.339844f, -0.60498f,
-0.339844f, -0.587891f, 0.339844f, -0.583008f, 0.339355f, -0.571289f, 0.290527f, -0.0869141f,
-0.30957f, -0.0869141f, 0.330566f, -0.0869141f, 0.345459f, -0.0720215f, 0.360352f,
--0.0571289f, 0.360352f, -0.0361328f, 0.360352f, -0.0146484f, 0.345215f, 0, 0.330078f,
-0.0146484f, 0.30957f, 0.0146484f, 0.290527f, 0.0146484f, 0.269531f, 0.0146484f, 0.254639f,
--0.000244141f, 0.239746f, -0.0151367f, 0.239746f, -0.0356445f, 0.239746f, -0.0576172f,
-0.254883f, -0.0722656f, 0.27002f, -0.0869141f, 0.290527f, -0.0869141f, 0.484375f,
--0.642578f, 0.154297f, 0.0644531f, 0.145996f, 0.0825195f, 0.132812f, 0.0825195f,
-0.124512f, 0.0825195f, 0.118408f, 0.076416f, 0.112305f, 0.0703125f, 0.112305f, 0.0629883f,
-0.112305f, 0.0571289f, 0.117188f, 0.046875f, 0.446777f, -0.660156f, 0.452148f, -0.671387f,
-0.457031f, -0.674805f, 0.461914f, -0.678223f, 0.46875f, -0.678223f, 0.477051f, -0.678223f,
-0.483154f, -0.672119f, 0.489258f, -0.666016f, 0.489258f, -0.658691f, 0.489258f, -0.65332f,
-0.484375f, -0.642578f, 0.0478516f, -0.284668f, 0.491211f, -0.531738f, 0.501953f,
--0.537598f, 0.507324f, -0.537598f, 0.515625f, -0.537598f, 0.521729f, -0.531494f,
-0.527832f, -0.525391f, 0.527832f, -0.51709f, 0.527832f, -0.504883f, 0.51123f, -0.495605f,
-0.131348f, -0.284668f, 0.510742f, -0.0737305f, 0.527344f, -0.0644531f, 0.527344f,
--0.0522461f, 0.527344f, -0.0439453f, 0.52124f, -0.0378418f, 0.515137f, -0.0317383f,
-0.506836f, -0.0317383f, 0.501465f, -0.0317383f, 0.490723f, -0.0375977f, 0.552246f,
--0.284668f, 0.108887f, -0.0375977f, 0.0981445f, -0.0317383f, 0.0927734f, -0.0317383f,
-0.0844727f, -0.0317383f, 0.0783691f, -0.0378418f, 0.0722656f, -0.0439453f, 0.0722656f,
--0.0522461f, 0.0722656f, -0.0644531f, 0.0888672f, -0.0737305f, 0.46875f, -0.284668f,
-0.0893555f, -0.495605f, 0.0727539f, -0.504883f, 0.0727539f, -0.51709f, 0.0727539f,
--0.525391f, 0.0788574f, -0.531494f, 0.0849609f, -0.537598f, 0.0932617f, -0.537598f,
-0.0986328f, -0.537598f, 0.109375f, -0.531738f, 0.435059f, -0.190918f, 0.165527f,
--0.190918f, 0.110352f, -0.0410156f, 0.188965f, -0.0410156f, 0.203613f, -0.0410156f,
-0.209961f, -0.0354004f, 0.216309f, -0.0297852f, 0.216309f, -0.0205078f, 0.216309f,
--0.0117188f, 0.209961f, -0.00585938f, 0.203613f, 0, 0.188965f, 0, 0.0356445f, 0,
-0.0209961f, 0, 0.0146484f, -0.00585938f, 0.00830078f, -0.0117188f, 0.00830078f, -0.0205078f,
-0.00830078f, -0.0297852f, 0.0146484f, -0.0354004f, 0.0209961f, -0.0410156f, 0.0356445f,
--0.0410156f, 0.0673828f, -0.0410156f, 0.248535f, -0.530273f, 0.127441f, -0.530273f,
-0.112793f, -0.530273f, 0.106445f, -0.535889f, 0.100098f, -0.541504f, 0.100098f, -0.550781f,
-0.100098f, -0.560059f, 0.106445f, -0.565674f, 0.112793f, -0.571289f, 0.127441f, -0.571289f,
-0.333984f, -0.571289f, 0.53418f, -0.0410156f, 0.565918f, -0.0410156f, 0.580566f,
--0.0410156f, 0.586914f, -0.0354004f, 0.593262f, -0.0297852f, 0.593262f, -0.0205078f,
-0.593262f, -0.0117188f, 0.586914f, -0.00585938f, 0.580566f, 0, 0.565918f, 0, 0.413086f,
-0, 0.397949f, 0, 0.391602f, -0.00585938f, 0.385254f, -0.0117188f, 0.385254f, -0.0205078f,
-0.385254f, -0.0297852f, 0.391602f, -0.0354004f, 0.397949f, -0.0410156f, 0.413086f,
--0.0410156f, 0.491211f, -0.0410156f, 0.419434f, -0.231934f, 0.306152f, -0.530273f,
-0.291016f, -0.530273f, 0.181152f, -0.231934f, 0.480469f, -0.515137f, 0.480469f, -0.543945f,
-0.480469f, -0.558594f, 0.486084f, -0.564941f, 0.491699f, -0.571289f, 0.500977f, -0.571289f,
-0.510254f, -0.571289f, 0.515869f, -0.564941f, 0.521484f, -0.558594f, 0.521484f, -0.543945f,
-0.521484f, -0.430176f, 0.521484f, -0.415039f, 0.515869f, -0.408691f, 0.510254f, -0.402344f,
-0.500977f, -0.402344f, 0.492676f, -0.402344f, 0.487061f, -0.408203f, 0.481445f, -0.414062f,
-0.480469f, -0.427246f, 0.478027f, -0.468262f, 0.436035f, -0.5f, 0.379395f, -0.543457f,
-0.307129f, -0.543457f, 0.259766f, -0.543457f, 0.217773f, -0.522461f, 0.186523f, -0.507324f,
-0.167969f, -0.485352f, 0.135742f, -0.447266f, 0.116699f, -0.400879f, 0.103027f, -0.366699f,
-0.103027f, -0.32373f, 0.103027f, -0.251953f, 0.103027f, -0.160156f, 0.169434f, -0.0925293f,
-0.23584f, -0.0249023f, 0.32373f, -0.0249023f, 0.376465f, -0.0249023f, 0.418213f,
--0.0478516f, 0.459961f, -0.0708008f, 0.499023f, -0.117188f, 0.507324f, -0.127441f,
-0.517578f, -0.127441f, 0.526367f, -0.127441f, 0.531738f, -0.12207f, 0.537109f, -0.116699f,
-0.537109f, -0.108398f, 0.537109f, -0.097168f, 0.516113f, -0.0742188f, 0.476074f,
--0.0292969f, 0.426025f, -0.0065918f, 0.375977f, 0.0161133f, 0.324707f, 0.0161133f,
-0.280273f, 0.0161133f, 0.234375f, -0.000976562f, 0.199219f, -0.0141602f, 0.17627f,
--0.0317383f, 0.15332f, -0.0493164f, 0.119873f, -0.0910645f, 0.0864258f, -0.132812f,
-0.0742188f, -0.168213f, 0.0620117f, -0.203613f, 0.0620117f, -0.246094f, 0.0620117f,
--0.32959f, 0.0620117f, -0.390137f, 0.0944824f, -0.453369f, 0.126953f, -0.516602f,
-0.18335f, -0.550537f, 0.239746f, -0.584473f, 0.305664f, -0.584473f, 0.407227f, -0.584473f,
-0.480469f, -0.515137f, 0.438965f, -0.276367f, 0.166992f, -0.276367f, 0.166992f, -0.0410156f,
-0.222168f, -0.0410156f, 0.236816f, -0.0410156f, 0.243164f, -0.0354004f, 0.249512f,
--0.0297852f, 0.249512f, -0.0205078f, 0.249512f, -0.0117188f, 0.243164f, -0.00585938f,
-0.236816f, 0, 0.222168f, 0, 0.0795898f, 0, 0.0649414f, 0, 0.0585938f, -0.00585938f,
-0.0522461f, -0.0117188f, 0.0522461f, -0.0205078f, 0.0522461f, -0.0297852f, 0.0585938f,
--0.0354004f, 0.0649414f, -0.0410156f, 0.0795898f, -0.0410156f, 0.125977f, -0.0410156f,
-0.125977f, -0.530273f, 0.100586f, -0.530273f, 0.0854492f, -0.530273f, 0.0791016f,
--0.535889f, 0.0727539f, -0.541504f, 0.0727539f, -0.550781f, 0.0727539f, -0.560059f,
-0.0791016f, -0.565674f, 0.0854492f, -0.571289f, 0.100586f, -0.571289f, 0.222168f,
--0.571289f, 0.236816f, -0.571289f, 0.243164f, -0.565674f, 0.249512f, -0.560059f,
-0.249512f, -0.550781f, 0.249512f, -0.541504f, 0.243164f, -0.535889f, 0.236816f, -0.530273f,
-0.222168f, -0.530273f, 0.166992f, -0.530273f, 0.166992f, -0.317383f, 0.438965f, -0.317383f,
-0.438965f, -0.530273f, 0.384277f, -0.530273f, 0.369629f, -0.530273f, 0.363281f, -0.535889f,
-0.356934f, -0.541504f, 0.356934f, -0.550781f, 0.356934f, -0.560059f, 0.363037f, -0.565674f,
-0.369141f, -0.571289f, 0.384277f, -0.571289f, 0.505859f, -0.571289f, 0.520996f, -0.571289f,
-0.527344f, -0.565674f, 0.533691f, -0.560059f, 0.533691f, -0.550781f, 0.533691f, -0.541504f,
-0.527344f, -0.535889f, 0.520996f, -0.530273f, 0.505859f, -0.530273f, 0.480469f, -0.530273f,
-0.480469f, -0.0410156f, 0.526855f, -0.0410156f, 0.541504f, -0.0410156f, 0.547852f,
--0.0354004f, 0.554199f, -0.0297852f, 0.554199f, -0.0205078f, 0.554199f, -0.0117188f,
-0.547852f, -0.00585938f, 0.541504f, 0, 0.526855f, 0, 0.384277f, 0, 0.369629f, 0,
-0.363281f, -0.00585938f, 0.356934f, -0.0117188f, 0.356934f, -0.0205078f, 0.356934f,
--0.0297852f, 0.363037f, -0.0354004f, 0.369141f, -0.0410156f, 0.384277f, -0.0410156f,
-0.438965f, -0.0410156f, 0.327148f, -0.171387f, 0.280273f, -0.171387f, 0.122559f,
--0.530273f, 0.114746f, -0.530273f, 0.114746f, -0.0410156f, 0.19043f, -0.0410156f,
-0.205078f, -0.0410156f, 0.211426f, -0.0354004f, 0.217773f, -0.0297852f, 0.217773f,
--0.0205078f, 0.217773f, -0.0117188f, 0.211426f, -0.00585938f, 0.205078f, 0, 0.19043f,
-0, 0.0390625f, 0, 0.0244141f, 0, 0.0180664f, -0.00585938f, 0.0117188f, -0.0117188f,
-0.0117188f, -0.0205078f, 0.0117188f, -0.0297852f, 0.0180664f, -0.0354004f, 0.0244141f,
--0.0410156f, 0.0390625f, -0.0410156f, 0.0737305f, -0.0410156f, 0.0737305f, -0.530273f,
-0.0478516f, -0.530273f, 0.0332031f, -0.530273f, 0.0268555f, -0.535889f, 0.0205078f,
--0.541504f, 0.0205078f, -0.550781f, 0.0205078f, -0.560059f, 0.0268555f, -0.565674f,
-0.0332031f, -0.571289f, 0.0478516f, -0.571289f, 0.148438f, -0.571289f, 0.303711f,
--0.217773f, 0.456543f, -0.571289f, 0.557129f, -0.571289f, 0.572266f, -0.571289f,
-0.578613f, -0.565674f, 0.584961f, -0.560059f, 0.584961f, -0.550781f, 0.584961f, -0.541504f,
-0.578613f, -0.535889f, 0.572266f, -0.530273f, 0.557129f, -0.530273f, 0.531738f, -0.530273f,
-0.531738f, -0.0410156f, 0.565918f, -0.0410156f, 0.581055f, -0.0410156f, 0.587402f,
--0.0354004f, 0.59375f, -0.0297852f, 0.59375f, -0.0205078f, 0.59375f, -0.0117188f,
-0.587402f, -0.00585938f, 0.581055f, 0, 0.565918f, 0, 0.415039f, 0, 0.400391f, 0,
-0.393799f, -0.00585938f, 0.387207f, -0.0117188f, 0.387207f, -0.0205078f, 0.387207f,
--0.0297852f, 0.393555f, -0.0354004f, 0.399902f, -0.0410156f, 0.415039f, -0.0410156f,
-0.490723f, -0.0410156f, 0.490723f, -0.530273f, 0.481934f, -0.530273f, 0.320312f,
--0.530273f, 0.320312f, -0.0410156f, 0.426758f, -0.0410156f, 0.441406f, -0.0410156f,
-0.447754f, -0.0354004f, 0.454102f, -0.0297852f, 0.454102f, -0.0205078f, 0.454102f,
--0.0117188f, 0.447754f, -0.00585938f, 0.441406f, 0, 0.426758f, 0, 0.172363f, 0, 0.157715f,
-0, 0.151367f, -0.00585938f, 0.14502f, -0.0117188f, 0.14502f, -0.0205078f, 0.14502f,
--0.0297852f, 0.151367f, -0.0354004f, 0.157715f, -0.0410156f, 0.172363f, -0.0410156f,
-0.278809f, -0.0410156f, 0.278809f, -0.530273f, 0.11084f, -0.530273f, 0.11084f, -0.388184f,
-0.11084f, -0.373047f, 0.105225f, -0.366699f, 0.0996094f, -0.360352f, 0.090332f, -0.360352f,
-0.081543f, -0.360352f, 0.0756836f, -0.366699f, 0.0698242f, -0.373047f, 0.0698242f,
--0.388184f, 0.0698242f, -0.571289f, 0.529297f, -0.571289f, 0.529297f, -0.388184f,
-0.529297f, -0.373047f, 0.523682f, -0.366699f, 0.518066f, -0.360352f, 0.508789f, -0.360352f,
-0.499512f, -0.360352f, 0.493896f, -0.366699f, 0.488281f, -0.373047f, 0.488281f, -0.388184f,
-0.488281f, -0.530273f, 0.47998f, 0, 0.415527f, 0, 0.299316f, -0.405762f, 0.185547f,
-0, 0.121094f, 0, 0.0605469f, -0.530273f, 0.0454102f, -0.530273f, 0.0307617f, -0.530273f,
-0.0244141f, -0.535889f, 0.0180664f, -0.541504f, 0.0180664f, -0.550781f, 0.0180664f,
--0.560059f, 0.0244141f, -0.565674f, 0.0307617f, -0.571289f, 0.0454102f, -0.571289f,
-0.197754f, -0.571289f, 0.212891f, -0.571289f, 0.219238f, -0.565674f, 0.225586f, -0.560059f,
-0.225586f, -0.550781f, 0.225586f, -0.541504f, 0.219238f, -0.535889f, 0.212891f, -0.530273f,
-0.197754f, -0.530273f, 0.102051f, -0.530273f, 0.15625f, -0.046875f, 0.26709f, -0.444824f,
-0.330078f, -0.444824f, 0.443848f, -0.046875f, 0.49707f, -0.530273f, 0.400879f, -0.530273f,
-0.38623f, -0.530273f, 0.379883f, -0.535889f, 0.373535f, -0.541504f, 0.373535f, -0.550781f,
-0.373535f, -0.560059f, 0.379883f, -0.565674f, 0.38623f, -0.571289f, 0.400879f, -0.571289f,
-0.552246f, -0.571289f, 0.567383f, -0.571289f, 0.57373f, -0.565674f, 0.580078f, -0.560059f,
-0.580078f, -0.550781f, 0.580078f, -0.541504f, 0.57373f, -0.535889f, 0.567383f, -0.530273f,
-0.552246f, -0.530273f, 0.537109f, -0.530273f, 0.321777f, -0.257812f, 0.321777f, -0.0410156f,
-0.428223f, -0.0410156f, 0.442871f, -0.0410156f, 0.449219f, -0.0354004f, 0.455566f,
--0.0297852f, 0.455566f, -0.0205078f, 0.455566f, -0.0117188f, 0.449219f, -0.00585938f,
-0.442871f, 0, 0.428223f, 0, 0.173828f, 0, 0.15918f, 0, 0.152832f, -0.00585938f, 0.146484f,
--0.0117188f, 0.146484f, -0.0205078f, 0.146484f, -0.0297852f, 0.152588f, -0.0354004f,
-0.158691f, -0.0410156f, 0.173828f, -0.0410156f, 0.280273f, -0.0410156f, 0.280273f,
--0.257812f, 0.100098f, -0.530273f, 0.0756836f, -0.530273f, 0.0610352f, -0.530273f,
-0.0546875f, -0.535889f, 0.0483398f, -0.541504f, 0.0483398f, -0.550781f, 0.0483398f,
--0.560059f, 0.0546875f, -0.565674f, 0.0610352f, -0.571289f, 0.0756836f, -0.571289f,
-0.188477f, -0.571289f, 0.203125f, -0.571289f, 0.209473f, -0.565674f, 0.21582f, -0.560059f,
-0.21582f, -0.550781f, 0.21582f, -0.541504f, 0.209473f, -0.535889f, 0.203125f, -0.530273f,
-0.188477f, -0.530273f, 0.147949f, -0.530273f, 0.30127f, -0.299316f, 0.451172f, -0.530273f,
-0.411133f, -0.530273f, 0.395996f, -0.530273f, 0.389648f, -0.535889f, 0.383301f, -0.541504f,
-0.383301f, -0.550781f, 0.383301f, -0.560059f, 0.389648f, -0.565674f, 0.395996f, -0.571289f,
-0.411133f, -0.571289f, 0.523438f, -0.571289f, 0.538086f, -0.571289f, 0.544434f, -0.565674f,
-0.550781f, -0.560059f, 0.550781f, -0.550781f, 0.550781f, -0.541504f, 0.544434f, -0.535889f,
-0.538086f, -0.530273f, 0.523438f, -0.530273f, 0.499023f, -0.530273f, 0.417969f, 0,
-0.417969f, -0.059082f, 0.328613f, 0.0161133f, 0.227051f, 0.0161133f, 0.15332f, 0.0161133f,
-0.111816f, -0.0212402f, 0.0703125f, -0.0585938f, 0.0703125f, -0.112793f, 0.0703125f,
--0.172363f, 0.125f, -0.216797f, 0.179688f, -0.26123f, 0.284668f, -0.26123f, 0.312988f,
--0.26123f, 0.346191f, -0.257568f, 0.379395f, -0.253906f, 0.417969f, -0.246094f, 0.417969f,
--0.3125f, 0.417969f, -0.346191f, 0.386719f, -0.371094f, 0.355469f, -0.395996f, 0.292969f,
--0.395996f, 0.245117f, -0.395996f, 0.158691f, -0.368164f, 0.143066f, -0.363281f,
-0.138672f, -0.363281f, 0.130859f, -0.363281f, 0.125244f, -0.369141f, 0.119629f, -0.375f,
-0.119629f, -0.383789f, 0.119629f, -0.39209f, 0.124512f, -0.396973f, 0.131348f, -0.404297f,
-0.179688f, -0.416992f, 0.255859f, -0.4375f, 0.294922f, -0.4375f, 0.372559f, -0.4375f,
-0.416016f, -0.39917f, 0.459473f, -0.36084f, 0.459473f, -0.3125f, 0.459473f, -0.0410156f,
-0.51416f, -0.0410156f, 0.529297f, -0.0410156f, 0.535645f, -0.0354004f, 0.541992f,
--0.0297852f, 0.541992f, -0.0205078f, 0.541992f, -0.0117188f, 0.535645f, -0.00585938f,
-0.529297f, 0, 0.51416f, 0, 0.417969f, -0.204102f, 0.38916f, -0.212402f, 0.356934f,
--0.216309f, 0.324707f, -0.220215f, 0.289062f, -0.220215f, 0.199707f, -0.220215f,
-0.149414f, -0.181641f, 0.111328f, -0.152832f, 0.111328f, -0.112793f, 0.111328f, -0.0756836f,
-0.140381f, -0.050293f, 0.169434f, -0.0249023f, 0.225098f, -0.0249023f, 0.27832f,
--0.0249023f, 0.323975f, -0.0461426f, 0.369629f, -0.0673828f, 0.417969f, -0.11377f,
-0.145508f, -0.612793f, 0.145508f, -0.34082f, 0.219727f, -0.4375f, 0.324707f, -0.4375f,
-0.414551f, -0.4375f, 0.478516f, -0.372314f, 0.54248f, -0.307129f, 0.54248f, -0.212402f,
-0.54248f, -0.116699f, 0.477783f, -0.050293f, 0.413086f, 0.0161133f, 0.324707f, 0.0161133f,
-0.217285f, 0.0161133f, 0.145508f, -0.0805664f, 0.145508f, 0, 0.0493164f, 0, 0.034668f,
-0, 0.0283203f, -0.00585938f, 0.0219727f, -0.0117188f, 0.0219727f, -0.0205078f, 0.0219727f,
--0.0297852f, 0.0283203f, -0.0354004f, 0.034668f, -0.0410156f, 0.0493164f, -0.0410156f,
-0.104492f, -0.0410156f, 0.104492f, -0.571289f, 0.0493164f, -0.571289f, 0.034668f,
--0.571289f, 0.0283203f, -0.577148f, 0.0219727f, -0.583008f, 0.0219727f, -0.592285f,
-0.0219727f, -0.601074f, 0.0283203f, -0.606934f, 0.034668f, -0.612793f, 0.0493164f,
--0.612793f, 0.501465f, -0.210449f, 0.501465f, -0.288086f, 0.448242f, -0.342041f,
-0.39502f, -0.395996f, 0.32373f, -0.395996f, 0.252441f, -0.395996f, 0.199219f, -0.342041f,
-0.145996f, -0.288086f, 0.145996f, -0.210449f, 0.145996f, -0.132812f, 0.199219f, -0.0788574f,
-0.252441f, -0.0249023f, 0.32373f, -0.0249023f, 0.39502f, -0.0249023f, 0.448242f,
--0.0788574f, 0.501465f, -0.132812f, 0.501465f, -0.210449f, 0.471191f, -0.381348f,
-0.471191f, -0.39502f, 0.471191f, -0.410156f, 0.477051f, -0.416504f, 0.48291f, -0.422852f,
-0.491699f, -0.422852f, 0.500977f, -0.422852f, 0.506836f, -0.416504f, 0.512695f, -0.410156f,
-0.512695f, -0.39502f, 0.512695f, -0.302246f, 0.512207f, -0.287109f, 0.506592f, -0.280762f,
-0.500977f, -0.274414f, 0.491699f, -0.274414f, 0.483398f, -0.274414f, 0.477783f, -0.280029f,
-0.472168f, -0.285645f, 0.471191f, -0.298828f, 0.468262f, -0.333496f, 0.425537f, -0.364746f,
-0.382812f, -0.395996f, 0.310547f, -0.395996f, 0.219238f, -0.395996f, 0.171875f, -0.338867f,
-0.124512f, -0.281738f, 0.124512f, -0.208008f, 0.124512f, -0.128418f, 0.176758f, -0.0766602f,
-0.229004f, -0.0249023f, 0.312012f, -0.0249023f, 0.359863f, -0.0249023f, 0.409424f,
--0.0424805f, 0.458984f, -0.0600586f, 0.499023f, -0.0991211f, 0.509277f, -0.108887f,
-0.51709f, -0.108887f, 0.525391f, -0.108887f, 0.531006f, -0.103271f, 0.536621f, -0.0976562f,
-0.536621f, -0.0893555f, 0.536621f, -0.0683594f, 0.487305f, -0.0361328f, 0.407715f,
-0.0161133f, 0.310059f, 0.0161133f, 0.210938f, 0.0161133f, 0.147217f, -0.0471191f,
-0.0834961f, -0.110352f, 0.0834961f, -0.20752f, 0.0834961f, -0.306641f, 0.148682f,
--0.37207f, 0.213867f, -0.4375f, 0.312988f, -0.4375f, 0.407227f, -0.4375f, 0.471191f,
--0.381348f, 0.500977f, -0.612793f, 0.500977f, -0.0410156f, 0.555664f, -0.0410156f,
-0.570801f, -0.0410156f, 0.577148f, -0.0354004f, 0.583496f, -0.0297852f, 0.583496f,
--0.0205078f, 0.583496f, -0.0117188f, 0.577148f, -0.00585938f, 0.570801f, 0, 0.555664f,
-0, 0.459473f, 0, 0.459473f, -0.081543f, 0.388184f, 0.0161133f, 0.27832f, 0.0161133f,
-0.222656f, 0.0161133f, 0.171631f, -0.0134277f, 0.120605f, -0.0429688f, 0.0910645f,
--0.0976562f, 0.0615234f, -0.152344f, 0.0615234f, -0.210449f, 0.0615234f, -0.269043f,
-0.0910645f, -0.323486f, 0.120605f, -0.37793f, 0.171631f, -0.407715f, 0.222656f, -0.4375f,
-0.278809f, -0.4375f, 0.38623f, -0.4375f, 0.459473f, -0.339844f, 0.459473f, -0.571289f,
-0.404785f, -0.571289f, 0.389648f, -0.571289f, 0.383301f, -0.577148f, 0.376953f, -0.583008f,
-0.376953f, -0.592285f, 0.376953f, -0.601074f, 0.383301f, -0.606934f, 0.389648f, -0.612793f,
-0.404785f, -0.612793f, 0.459473f, -0.210449f, 0.459473f, -0.288574f, 0.406738f, -0.342285f,
-0.354004f, -0.395996f, 0.28125f, -0.395996f, 0.208008f, -0.395996f, 0.155273f, -0.342285f,
-0.102539f, -0.288574f, 0.102539f, -0.210449f, 0.102539f, -0.132812f, 0.155273f, -0.0788574f,
-0.208008f, -0.0249023f, 0.28125f, -0.0249023f, 0.354004f, -0.0249023f, 0.406738f,
--0.0788574f, 0.459473f, -0.132812f, 0.459473f, -0.210449f, 0.521973f, -0.20166f,
-0.104004f, -0.20166f, 0.114746f, -0.12207f, 0.170654f, -0.0734863f, 0.226562f, -0.0249023f,
-0.309082f, -0.0249023f, 0.35498f, -0.0249023f, 0.405273f, -0.0400391f, 0.455566f,
--0.0551758f, 0.487305f, -0.0800781f, 0.496582f, -0.0874023f, 0.503418f, -0.0874023f,
-0.51123f, -0.0874023f, 0.51709f, -0.0812988f, 0.522949f, -0.0751953f, 0.522949f,
--0.0668945f, 0.522949f, -0.0585938f, 0.515137f, -0.0507812f, 0.491699f, -0.0263672f,
-0.431885f, -0.00512695f, 0.37207f, 0.0161133f, 0.309082f, 0.0161133f, 0.203613f,
-0.0161133f, 0.133057f, -0.0529785f, 0.0625f, -0.12207f, 0.0625f, -0.220215f, 0.0625f,
--0.30957f, 0.128662f, -0.373535f, 0.194824f, -0.4375f, 0.29248f, -0.4375f, 0.393066f,
--0.4375f, 0.458008f, -0.371826f, 0.522949f, -0.306152f, 0.521973f, -0.20166f, 0.480469f,
--0.243164f, 0.468262f, -0.311035f, 0.41626f, -0.353516f, 0.364258f, -0.395996f, 0.29248f,
--0.395996f, 0.220703f, -0.395996f, 0.168945f, -0.354004f, 0.117188f, -0.312012f,
-0.104492f, -0.243164f, 0.272949f, -0.381348f, 0.272949f, -0.0410156f, 0.453125f,
--0.0410156f, 0.467773f, -0.0410156f, 0.474121f, -0.0354004f, 0.480469f, -0.0297852f,
-0.480469f, -0.0205078f, 0.480469f, -0.0117188f, 0.474121f, -0.00585938f, 0.467773f,
-0, 0.453125f, 0, 0.132324f, 0, 0.117676f, 0, 0.111328f, -0.00585938f, 0.10498f, -0.0117188f,
-0.10498f, -0.0205078f, 0.10498f, -0.0297852f, 0.111328f, -0.0354004f, 0.117676f,
--0.0410156f, 0.132324f, -0.0410156f, 0.231445f, -0.0410156f, 0.231445f, -0.381348f,
-0.142578f, -0.381348f, 0.12793f, -0.381348f, 0.121582f, -0.387207f, 0.115234f, -0.393066f,
-0.115234f, -0.402344f, 0.115234f, -0.411133f, 0.121582f, -0.416992f, 0.12793f, -0.422852f,
-0.142578f, -0.422852f, 0.231445f, -0.422852f, 0.231445f, -0.484863f, 0.231445f, -0.536621f,
-0.273438f, -0.574707f, 0.31543f, -0.612793f, 0.384766f, -0.612793f, 0.442871f, -0.612793f,
-0.508789f, -0.602051f, 0.533691f, -0.598145f, 0.538818f, -0.592773f, 0.543945f, -0.587402f,
-0.543945f, -0.578613f, 0.543945f, -0.569824f, 0.538086f, -0.564209f, 0.532227f, -0.558594f,
-0.522461f, -0.558594f, 0.518555f, -0.558594f, 0.509277f, -0.560059f, 0.435547f, -0.571289f,
-0.384766f, -0.571289f, 0.331055f, -0.571289f, 0.302002f, -0.544922f, 0.272949f, -0.518555f,
-0.272949f, -0.484863f, 0.272949f, -0.422852f, 0.464844f, -0.422852f, 0.479492f, -0.422852f,
-0.48584f, -0.416992f, 0.492188f, -0.411133f, 0.492188f, -0.401855f, 0.492188f, -0.393066f,
-0.48584f, -0.387207f, 0.479492f, -0.381348f, 0.464844f, -0.381348f, 0.437988f, -0.347656f,
-0.437988f, -0.422852f, 0.53418f, -0.422852f, 0.548828f, -0.422852f, 0.555176f, -0.416992f,
-0.561523f, -0.411133f, 0.561523f, -0.401855f, 0.561523f, -0.393066f, 0.555176f, -0.387207f,
-0.548828f, -0.381348f, 0.53418f, -0.381348f, 0.479004f, -0.381348f, 0.479004f, 0.0283203f,
-0.479004f, 0.0693359f, 0.461426f, 0.101562f, 0.449707f, 0.123047f, 0.422363f, 0.145996f,
-0.39502f, 0.168945f, 0.372559f, 0.178711f, 0.350098f, 0.188477f, 0.3125f, 0.188477f,
-0.196289f, 0.188477f, 0.181641f, 0.188477f, 0.175293f, 0.182861f, 0.168945f, 0.177246f,
-0.168945f, 0.167969f, 0.168945f, 0.158691f, 0.175293f, 0.152832f, 0.181641f, 0.146973f,
-0.196289f, 0.146973f, 0.313965f, 0.147461f, 0.350098f, 0.147461f, 0.37915f, 0.128906f,
-0.408203f, 0.110352f, 0.427246f, 0.074707f, 0.437988f, 0.0541992f, 0.437988f, 0.0224609f,
-0.437988f, -0.100586f, 0.37207f, -0.0102539f, 0.268066f, -0.0102539f, 0.183594f,
--0.0102539f, 0.122314f, -0.072998f, 0.0610352f, -0.135742f, 0.0610352f, -0.224121f,
-0.0610352f, -0.3125f, 0.122314f, -0.375f, 0.183594f, -0.4375f, 0.268066f, -0.4375f,
-0.37207f, -0.4375f, 0.437988f, -0.347656f, 0.437988f, -0.224121f, 0.437988f, -0.296387f,
-0.388428f, -0.346191f, 0.338867f, -0.395996f, 0.27002f, -0.395996f, 0.201172f, -0.395996f,
-0.151855f, -0.345947f, 0.102539f, -0.295898f, 0.102539f, -0.224121f, 0.102539f, -0.151855f,
-0.151855f, -0.101807f, 0.201172f, -0.0517578f, 0.27002f, -0.0517578f, 0.338867f,
--0.0517578f, 0.388428f, -0.101807f, 0.437988f, -0.151855f, 0.437988f, -0.224121f,
-0.320312f, -0.633301f, 0.320312f, -0.527344f, 0.259766f, -0.527344f, 0.259766f, -0.633301f,
-0.321777f, -0.422852f, 0.321777f, -0.0410156f, 0.48291f, -0.0410156f, 0.498047f,
--0.0410156f, 0.504395f, -0.0354004f, 0.510742f, -0.0297852f, 0.510742f, -0.0205078f,
-0.510742f, -0.0117188f, 0.504395f, -0.00585938f, 0.498047f, 0, 0.48291f, 0, 0.119629f,
-0, 0.10498f, 0, 0.0986328f, -0.00585938f, 0.0922852f, -0.0117188f, 0.0922852f, -0.0205078f,
-0.0922852f, -0.0297852f, 0.0986328f, -0.0354004f, 0.10498f, -0.0410156f, 0.119629f,
--0.0410156f, 0.280762f, -0.0410156f, 0.280762f, -0.381348f, 0.161133f, -0.381348f,
-0.146484f, -0.381348f, 0.139893f, -0.387207f, 0.133301f, -0.393066f, 0.133301f, -0.401855f,
-0.133301f, -0.411133f, 0.139648f, -0.416992f, 0.145996f, -0.422852f, 0.161133f, -0.422852f,
-0.320801f, -0.612793f, 0.320801f, -0.0410156f, 0.481934f, -0.0410156f, 0.49707f,
--0.0410156f, 0.503418f, -0.0354004f, 0.509766f, -0.0297852f, 0.509766f, -0.0205078f,
-0.509766f, -0.0117188f, 0.503418f, -0.00585938f, 0.49707f, 0, 0.481934f, 0, 0.118652f,
-0, 0.104004f, 0, 0.0976562f, -0.00585938f, 0.0913086f, -0.0117188f, 0.0913086f, -0.0205078f,
-0.0913086f, -0.0297852f, 0.0976562f, -0.0354004f, 0.104004f, -0.0410156f, 0.118652f,
--0.0410156f, 0.279785f, -0.0410156f, 0.279785f, -0.571289f, 0.161621f, -0.571289f,
-0.146973f, -0.571289f, 0.140381f, -0.577148f, 0.133789f, -0.583008f, 0.133789f, -0.592285f,
-0.133789f, -0.601074f, 0.140137f, -0.606934f, 0.146484f, -0.612793f, 0.161621f, -0.612793f,
-0.113281f, -0.422852f, 0.113281f, -0.381348f, 0.165527f, -0.4375f, 0.218262f, -0.4375f,
-0.25f, -0.4375f, 0.273926f, -0.420654f, 0.297852f, -0.403809f, 0.313965f, -0.369629f,
-0.341309f, -0.403809f, 0.369385f, -0.420654f, 0.397461f, -0.4375f, 0.425781f, -0.4375f,
-0.470215f, -0.4375f, 0.496582f, -0.408691f, 0.53125f, -0.371582f, 0.53125f, -0.327637f,
-0.53125f, -0.0410156f, 0.565918f, -0.0410156f, 0.580566f, -0.0410156f, 0.586914f,
--0.0354004f, 0.593262f, -0.0297852f, 0.593262f, -0.0205078f, 0.593262f, -0.0117188f,
-0.586914f, -0.00585938f, 0.580566f, 0, 0.565918f, 0, 0.490234f, 0, 0.490234f, -0.32373f,
-0.490234f, -0.35498f, 0.471191f, -0.375488f, 0.452148f, -0.395996f, 0.427246f, -0.395996f,
-0.404785f, -0.395996f, 0.379883f, -0.37915f, 0.35498f, -0.362305f, 0.323242f, -0.312988f,
-0.323242f, -0.0410156f, 0.357422f, -0.0410156f, 0.37207f, -0.0410156f, 0.378418f,
--0.0354004f, 0.384766f, -0.0297852f, 0.384766f, -0.0205078f, 0.384766f, -0.0117188f,
-0.378418f, -0.00585938f, 0.37207f, 0, 0.357422f, 0, 0.281738f, 0, 0.281738f, -0.320801f,
-0.281738f, -0.353516f, 0.262451f, -0.374756f, 0.243164f, -0.395996f, 0.219238f, -0.395996f,
-0.197266f, -0.395996f, 0.175781f, -0.381836f, 0.145996f, -0.361816f, 0.113281f, -0.312988f,
-0.113281f, -0.0410156f, 0.147949f, -0.0410156f, 0.162598f, -0.0410156f, 0.168945f,
--0.0354004f, 0.175293f, -0.0297852f, 0.175293f, -0.0205078f, 0.175293f, -0.0117188f,
-0.168945f, -0.00585938f, 0.162598f, 0, 0.147949f, 0, 0.0375977f, 0, 0.0229492f, 0,
-0.0166016f, -0.00585938f, 0.0102539f, -0.0117188f, 0.0102539f, -0.0205078f, 0.0102539f,
--0.0297852f, 0.0166016f, -0.0354004f, 0.0229492f, -0.0410156f, 0.0375977f, -0.0410156f,
-0.0722656f, -0.0410156f, 0.0722656f, -0.381348f, 0.0375977f, -0.381348f, 0.0229492f,
--0.381348f, 0.0166016f, -0.387207f, 0.0102539f, -0.393066f, 0.0102539f, -0.402344f,
-0.0102539f, -0.411133f, 0.0166016f, -0.416992f, 0.0229492f, -0.422852f, 0.0375977f,
--0.422852f, 0.16748f, -0.422852f, 0.16748f, -0.36084f, 0.210449f, -0.404297f, 0.245117f,
--0.420898f, 0.279785f, -0.4375f, 0.323242f, -0.4375f, 0.370117f, -0.4375f, 0.408691f,
--0.41748f, 0.436035f, -0.402832f, 0.458252f, -0.368896f, 0.480469f, -0.334961f, 0.480469f,
--0.299316f, 0.480469f, -0.0410156f, 0.515137f, -0.0410156f, 0.529785f, -0.0410156f,
-0.536133f, -0.0354004f, 0.54248f, -0.0297852f, 0.54248f, -0.0205078f, 0.54248f, -0.0117188f,
-0.536133f, -0.00585938f, 0.529785f, 0, 0.515137f, 0, 0.405273f, 0, 0.390137f, 0,
-0.383789f, -0.00585938f, 0.377441f, -0.0117188f, 0.377441f, -0.0205078f, 0.377441f,
--0.0297852f, 0.383789f, -0.0354004f, 0.390137f, -0.0410156f, 0.405273f, -0.0410156f,
-0.439453f, -0.0410156f, 0.439453f, -0.29248f, 0.439453f, -0.335938f, 0.407715f, -0.365967f,
-0.375977f, -0.395996f, 0.322754f, -0.395996f, 0.282227f, -0.395996f, 0.252441f, -0.379639f,
-0.222656f, -0.363281f, 0.16748f, -0.29834f, 0.16748f, -0.0410156f, 0.213867f, -0.0410156f,
-0.228516f, -0.0410156f, 0.234863f, -0.0354004f, 0.241211f, -0.0297852f, 0.241211f,
--0.0205078f, 0.241211f, -0.0117188f, 0.234863f, -0.00585938f, 0.228516f, 0, 0.213867f,
-0, 0.0800781f, 0, 0.0654297f, 0, 0.059082f, -0.00585938f, 0.0527344f, -0.0117188f,
-0.0527344f, -0.0205078f, 0.0527344f, -0.0297852f, 0.059082f, -0.0354004f, 0.0654297f,
--0.0410156f, 0.0800781f, -0.0410156f, 0.126465f, -0.0410156f, 0.126465f, -0.381348f,
-0.0917969f, -0.381348f, 0.0771484f, -0.381348f, 0.0708008f, -0.387207f, 0.0644531f,
--0.393066f, 0.0644531f, -0.402344f, 0.0644531f, -0.411133f, 0.0708008f, -0.416992f,
-0.0771484f, -0.422852f, 0.0917969f, -0.422852f, 0.529297f, -0.210449f, 0.529297f,
--0.116699f, 0.462158f, -0.050293f, 0.39502f, 0.0161133f, 0.300293f, 0.0161133f, 0.20459f,
-0.0161133f, 0.137695f, -0.0505371f, 0.0708008f, -0.117188f, 0.0708008f, -0.210449f,
-0.0708008f, -0.304199f, 0.137695f, -0.37085f, 0.20459f, -0.4375f, 0.300293f, -0.4375f,
-0.39502f, -0.4375f, 0.462158f, -0.371094f, 0.529297f, -0.304688f, 0.529297f, -0.210449f,
-0.487793f, -0.210449f, 0.487793f, -0.287598f, 0.432861f, -0.341797f, 0.37793f, -0.395996f,
-0.299805f, -0.395996f, 0.22168f, -0.395996f, 0.166748f, -0.341553f, 0.111816f, -0.287109f,
-0.111816f, -0.210449f, 0.111816f, -0.134277f, 0.166748f, -0.0795898f, 0.22168f, -0.0249023f,
-0.299805f, -0.0249023f, 0.37793f, -0.0249023f, 0.432861f, -0.0793457f, 0.487793f,
--0.133789f, 0.487793f, -0.210449f, 0.145508f, -0.422852f, 0.145508f, -0.348145f,
-0.182129f, -0.392578f, 0.224121f, -0.415039f, 0.266113f, -0.4375f, 0.323242f, -0.4375f,
-0.383789f, -0.4375f, 0.435059f, -0.40918f, 0.486328f, -0.380859f, 0.514404f, -0.330322f,
-0.54248f, -0.279785f, 0.54248f, -0.224121f, 0.54248f, -0.135742f, 0.479248f, -0.072998f,
-0.416016f, -0.0102539f, 0.32373f, -0.0102539f, 0.213867f, -0.0102539f, 0.145508f,
--0.0996094f, 0.145508f, 0.147461f, 0.245117f, 0.147461f, 0.259766f, 0.147461f, 0.266113f,
-0.153076f, 0.272461f, 0.158691f, 0.272461f, 0.167969f, 0.272461f, 0.176758f, 0.266113f,
-0.182617f, 0.259766f, 0.188477f, 0.245117f, 0.188477f, 0.0493164f, 0.188477f, 0.034668f,
-0.188477f, 0.0283203f, 0.182861f, 0.0219727f, 0.177246f, 0.0219727f, 0.167969f, 0.0219727f,
-0.158691f, 0.0283203f, 0.153076f, 0.034668f, 0.147461f, 0.0493164f, 0.147461f, 0.104492f,
-0.147461f, 0.104492f, -0.381348f, 0.0493164f, -0.381348f, 0.034668f, -0.381348f,
-0.0283203f, -0.387207f, 0.0219727f, -0.393066f, 0.0219727f, -0.402344f, 0.0219727f,
--0.411133f, 0.0283203f, -0.416992f, 0.034668f, -0.422852f, 0.0493164f, -0.422852f,
-0.500977f, -0.224121f, 0.500977f, -0.294922f, 0.449463f, -0.345459f, 0.397949f, -0.395996f,
-0.32373f, -0.395996f, 0.249023f, -0.395996f, 0.197266f, -0.345215f, 0.145508f, -0.294434f,
-0.145508f, -0.224121f, 0.145508f, -0.15332f, 0.197266f, -0.102539f, 0.249023f, -0.0517578f,
-0.32373f, -0.0517578f, 0.397461f, -0.0517578f, 0.449219f, -0.102295f, 0.500977f,
--0.152832f, 0.500977f, -0.224121f, 0.250977f, -0.422852f, 0.250977f, -0.319336f,
-0.331055f, -0.391602f, 0.37085f, -0.412354f, 0.410645f, -0.433105f, 0.444336f, -0.433105f,
-0.480957f, -0.433105f, 0.512451f, -0.408447f, 0.543945f, -0.383789f, 0.543945f, -0.371094f,
-0.543945f, -0.361816f, 0.537842f, -0.355713f, 0.531738f, -0.349609f, 0.522461f, -0.349609f,
-0.517578f, -0.349609f, 0.51416f, -0.351318f, 0.510742f, -0.353027f, 0.501465f, -0.362305f,
-0.484375f, -0.379395f, 0.47168f, -0.385742f, 0.458984f, -0.39209f, 0.446777f, -0.39209f,
-0.419922f, -0.39209f, 0.38208f, -0.370605f, 0.344238f, -0.349121f, 0.250977f, -0.265625f,
-0.250977f, -0.0410156f, 0.432617f, -0.0410156f, 0.447754f, -0.0410156f, 0.454102f,
--0.0354004f, 0.460449f, -0.0297852f, 0.460449f, -0.0205078f, 0.460449f, -0.0117188f,
-0.454102f, -0.00585938f, 0.447754f, 0, 0.432617f, 0, 0.11084f, 0, 0.0961914f, 0,
-0.0898438f, -0.00561523f, 0.0834961f, -0.0112305f, 0.0834961f, -0.0200195f, 0.0834961f,
--0.0283203f, 0.0895996f, -0.0339355f, 0.0957031f, -0.0395508f, 0.11084f, -0.0395508f,
-0.209961f, -0.0395508f, 0.209961f, -0.381348f, 0.134277f, -0.381348f, 0.119629f,
--0.381348f, 0.113281f, -0.387207f, 0.106934f, -0.393066f, 0.106934f, -0.402344f,
-0.106934f, -0.411133f, 0.113037f, -0.416992f, 0.119141f, -0.422852f, 0.134277f, -0.422852f,
-0.435547f, -0.395996f, 0.435547f, -0.410156f, 0.441406f, -0.416504f, 0.447266f, -0.422852f,
-0.456055f, -0.422852f, 0.465332f, -0.422852f, 0.471191f, -0.416504f, 0.477051f, -0.410156f,
-0.477051f, -0.39502f, 0.477051f, -0.324707f, 0.477051f, -0.310059f, 0.471191f, -0.303711f,
-0.465332f, -0.297363f, 0.456055f, -0.297363f, 0.447754f, -0.297363f, 0.442139f, -0.302734f,
-0.436523f, -0.308105f, 0.435547f, -0.320312f, 0.432617f, -0.349609f, 0.405273f, -0.368652f,
-0.365234f, -0.395996f, 0.299316f, -0.395996f, 0.230469f, -0.395996f, 0.192383f, -0.368164f,
-0.163574f, -0.347168f, 0.163574f, -0.321289f, 0.163574f, -0.291992f, 0.197754f, -0.272461f,
-0.221191f, -0.258789f, 0.286621f, -0.251465f, 0.37207f, -0.242188f, 0.405273f, -0.230469f,
-0.452637f, -0.213379f, 0.47583f, -0.183105f, 0.499023f, -0.152832f, 0.499023f, -0.117676f,
-0.499023f, -0.0654297f, 0.44873f, -0.0246582f, 0.398438f, 0.0161133f, 0.30127f, 0.0161133f,
-0.204102f, 0.0161133f, 0.14209f, -0.0332031f, 0.14209f, -0.0166016f, 0.140137f, -0.0117188f,
-0.138184f, -0.00683594f, 0.133057f, -0.00341797f, 0.12793f, 0, 0.121582f, 0, 0.112793f,
-0, 0.106934f, -0.00634766f, 0.101074f, -0.0126953f, 0.101074f, -0.0273438f, 0.101074f,
--0.111816f, 0.101074f, -0.126465f, 0.106689f, -0.132812f, 0.112305f, -0.13916f, 0.121582f,
--0.13916f, 0.130371f, -0.13916f, 0.136475f, -0.133057f, 0.142578f, -0.126953f, 0.142578f,
--0.116699f, 0.142578f, -0.0942383f, 0.153809f, -0.0791016f, 0.170898f, -0.0556641f,
-0.208252f, -0.0402832f, 0.245605f, -0.0249023f, 0.299805f, -0.0249023f, 0.379883f,
--0.0249023f, 0.418945f, -0.0546875f, 0.458008f, -0.0844727f, 0.458008f, -0.117676f,
-0.458008f, -0.155762f, 0.418457f, -0.178711f, 0.378418f, -0.20166f, 0.302002f, -0.209473f,
-0.225586f, -0.217285f, 0.192383f, -0.22998f, 0.15918f, -0.242676f, 0.140625f, -0.268066f,
-0.12207f, -0.293457f, 0.12207f, -0.322754f, 0.12207f, -0.375488f, 0.173828f, -0.406494f,
-0.225586f, -0.4375f, 0.297363f, -0.4375f, 0.382324f, -0.4375f, 0.435547f, -0.395996f,
-0.21582f, -0.422852f, 0.438477f, -0.422852f, 0.453125f, -0.422852f, 0.459473f, -0.416992f,
-0.46582f, -0.411133f, 0.46582f, -0.401855f, 0.46582f, -0.393066f, 0.459473f, -0.387207f,
-0.453125f, -0.381348f, 0.438477f, -0.381348f, 0.21582f, -0.381348f, 0.21582f, -0.108398f,
-0.21582f, -0.0727539f, 0.244385f, -0.0488281f, 0.272949f, -0.0249023f, 0.328125f,
--0.0249023f, 0.369629f, -0.0249023f, 0.417969f, -0.0373535f, 0.466309f, -0.0498047f,
-0.493164f, -0.0654297f, 0.50293f, -0.0717773f, 0.509277f, -0.0717773f, 0.51709f,
--0.0717773f, 0.522949f, -0.0656738f, 0.528809f, -0.0595703f, 0.528809f, -0.0512695f,
-0.528809f, -0.0439453f, 0.522461f, -0.0375977f, 0.506836f, -0.0214844f, 0.446533f,
--0.00268555f, 0.38623f, 0.0161133f, 0.331055f, 0.0161133f, 0.259277f, 0.0161133f,
-0.216797f, -0.0175781f, 0.174316f, -0.0512695f, 0.174316f, -0.108398f, 0.174316f,
--0.381348f, 0.0986328f, -0.381348f, 0.0839844f, -0.381348f, 0.0776367f, -0.387207f,
-0.0712891f, -0.393066f, 0.0712891f, -0.402344f, 0.0712891f, -0.411133f, 0.0776367f,
--0.416992f, 0.0839844f, -0.422852f, 0.0986328f, -0.422852f, 0.174316f, -0.422852f,
-0.174316f, -0.543945f, 0.174316f, -0.558594f, 0.180176f, -0.564941f, 0.186035f, -0.571289f,
-0.194824f, -0.571289f, 0.204102f, -0.571289f, 0.209961f, -0.564941f, 0.21582f, -0.558594f,
-0.21582f, -0.543945f, 0.44043f, 0, 0.44043f, -0.0600586f, 0.356445f, 0.0161133f,
-0.258789f, 0.0161133f, 0.19873f, 0.0161133f, 0.16748f, -0.0166016f, 0.126953f, -0.0595703f,
-0.126953f, -0.116699f, 0.126953f, -0.381348f, 0.0717773f, -0.381348f, 0.0571289f,
--0.381348f, 0.0507812f, -0.387207f, 0.0444336f, -0.393066f, 0.0444336f, -0.402344f,
-0.0444336f, -0.411133f, 0.0507812f, -0.416992f, 0.0571289f, -0.422852f, 0.0717773f,
--0.422852f, 0.167969f, -0.422852f, 0.167969f, -0.116699f, 0.167969f, -0.0766602f,
-0.193359f, -0.0507812f, 0.21875f, -0.0249023f, 0.256836f, -0.0249023f, 0.356934f,
--0.0249023f, 0.44043f, -0.116699f, 0.44043f, -0.381348f, 0.364746f, -0.381348f, 0.350098f,
--0.381348f, 0.34375f, -0.387207f, 0.337402f, -0.393066f, 0.337402f, -0.402344f, 0.337402f,
--0.411133f, 0.34375f, -0.416992f, 0.350098f, -0.422852f, 0.364746f, -0.422852f, 0.481445f,
--0.422852f, 0.481445f, -0.0410156f, 0.516113f, -0.0410156f, 0.530762f, -0.0410156f,
-0.537109f, -0.0354004f, 0.543457f, -0.0297852f, 0.543457f, -0.0205078f, 0.543457f,
--0.0117188f, 0.537109f, -0.00585938f, 0.530762f, 0, 0.516113f, 0, 0.302734f, 0, 0.112305f,
--0.381348f, 0.100098f, -0.381348f, 0.0854492f, -0.381348f, 0.0791016f, -0.387207f,
-0.0727539f, -0.393066f, 0.0727539f, -0.401855f, 0.0727539f, -0.408203f, 0.0759277f,
--0.41333f, 0.0791016f, -0.418457f, 0.0842285f, -0.420654f, 0.0893555f, -0.422852f,
-0.100098f, -0.422852f, 0.212402f, -0.422852f, 0.227051f, -0.422852f, 0.233398f, -0.416992f,
-0.239746f, -0.411133f, 0.239746f, -0.401855f, 0.239746f, -0.393066f, 0.233398f, -0.387207f,
-0.227051f, -0.381348f, 0.212402f, -0.381348f, 0.157227f, -0.381348f, 0.324707f, -0.0449219f,
-0.489746f, -0.381348f, 0.43457f, -0.381348f, 0.419922f, -0.381348f, 0.413574f, -0.387207f,
-0.407227f, -0.393066f, 0.407227f, -0.402344f, 0.407227f, -0.411133f, 0.413574f, -0.416992f,
-0.419922f, -0.422852f, 0.43457f, -0.422852f, 0.546387f, -0.422852f, 0.561523f, -0.422852f,
-0.567871f, -0.416992f, 0.574219f, -0.411133f, 0.574219f, -0.401855f, 0.574219f, -0.395508f,
-0.570312f, -0.390137f, 0.566406f, -0.384766f, 0.561523f, -0.383057f, 0.556641f, -0.381348f,
-0.53418f, -0.381348f, 0.274414f, 0.147461f, 0.338379f, 0.147461f, 0.353027f, 0.147461f,
-0.359375f, 0.153076f, 0.365723f, 0.158691f, 0.365723f, 0.167969f, 0.365723f, 0.176758f,
-0.359375f, 0.182617f, 0.353027f, 0.188477f, 0.338379f, 0.188477f, 0.102051f, 0.188477f,
-0.0874023f, 0.188477f, 0.0810547f, 0.182861f, 0.074707f, 0.177246f, 0.074707f, 0.167969f,
-0.074707f, 0.158691f, 0.0810547f, 0.153076f, 0.0874023f, 0.147461f, 0.102051f, 0.147461f,
-0.230469f, 0.147461f
-};
-
-const unsigned char CourierNewkNormalVerbs[] = {
-6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5,
-6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 0, 1, 1, 1,
-5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1,
-1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 0, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2,
-2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1,
-1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5,
-6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2,
-2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6,
-0, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2,
-2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2,
-2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2,
-2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6
-};
-
-const unsigned CourierNewkNormalCharCodes[] = {
-32, 33, 47, 60, 62,
-65, 67, 72, 77, 84, 87, 89, 97, 98, 99, 100, 101, 102, 103, 105, 108, 109, 110,
-111, 112, 114, 115, 116, 117, 121
-};
-
-const SkFixed CourierNewkNormalWidths[] = {
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0
-};
-
-const int CourierNewkNormalCharCodesCount = (int) SK_ARRAY_COUNT(CourierNewkNormalCharCodes);
-
-const SkPaint::FontMetrics CourierNewkNormalMetrics = {
-0x00000003, -1.021f, -0.83252f, 0.300293f, 0.679688f, 0, 0.744141f, 0, -0.121582f,
-0.622559f, 0.437988f, 0, 0.0410156f, 0.23291f
-};
-
-const SkScalar CourierNewkBoldPoints[] = {
-0.422363f, -0.161133f, 0.179199f, -0.161133f, 0.154785f, -0.100098f, 0.179199f, -0.100098f,
-0.215332f, -0.100098f, 0.230713f, -0.0861816f, 0.246094f, -0.0722656f, 0.246094f,
--0.0498047f, 0.246094f, -0.027832f, 0.230713f, -0.013916f, 0.215332f, 0, 0.179199f,
-0, 0.0444336f, 0, 0.00830078f, 0, -0.00708008f, -0.013916f, -0.0224609f, -0.027832f,
--0.0224609f, -0.050293f, -0.0224609f, -0.0727539f, -0.00634766f, -0.0869141f, 0.00976562f,
--0.101074f, 0.046875f, -0.100098f, 0.204102f, -0.491699f, 0.138672f, -0.491699f,
-0.102539f, -0.491699f, 0.0871582f, -0.505615f, 0.0717773f, -0.519531f, 0.0717773f,
--0.541992f, 0.0717773f, -0.564453f, 0.0871582f, -0.578369f, 0.102539f, -0.592285f,
-0.138672f, -0.592285f, 0.35498f, -0.591797f, 0.554199f, -0.100098f, 0.589355f, -0.100098f,
-0.600586f, -0.0922852f, 0.623047f, -0.0761719f, 0.623047f, -0.0498047f, 0.623047f,
--0.027832f, 0.60791f, -0.013916f, 0.592773f, 0, 0.556641f, 0, 0.421875f, 0, 0.385742f,
-0, 0.370361f, -0.013916f, 0.35498f, -0.027832f, 0.35498f, -0.050293f, 0.35498f, -0.0722656f,
-0.370361f, -0.0861816f, 0.385742f, -0.100098f, 0.421875f, -0.100098f, 0.446289f,
--0.100098f, 0.380859f, -0.26123f, 0.300293f, -0.459473f, 0.219238f, -0.26123f, 0.409668f,
--0.245117f, 0.195801f, -0.245117f, 0.195801f, -0.100098f, 0.211426f, -0.100098f,
-0.247559f, -0.100098f, 0.262939f, -0.0861816f, 0.27832f, -0.0722656f, 0.27832f, -0.0498047f,
-0.27832f, -0.027832f, 0.262939f, -0.013916f, 0.247559f, 0, 0.211426f, 0, 0.0888672f,
-0, 0.0527344f, 0, 0.0373535f, -0.013916f, 0.0219727f, -0.027832f, 0.0219727f, -0.050293f,
-0.0219727f, -0.0776367f, 0.0458984f, -0.0927734f, 0.0576172f, -0.100586f, 0.0957031f,
--0.100098f, 0.0957031f, -0.491699f, 0.0693359f, -0.494141f, 0.0559082f, -0.507812f,
-0.0424805f, -0.521484f, 0.0424805f, -0.541992f, 0.0424805f, -0.564453f, 0.0578613f,
--0.578369f, 0.0732422f, -0.592285f, 0.109375f, -0.592285f, 0.211426f, -0.591797f,
-0.247559f, -0.591797f, 0.262939f, -0.578125f, 0.27832f, -0.564453f, 0.27832f, -0.541992f,
-0.27832f, -0.519531f, 0.262939f, -0.505615f, 0.247559f, -0.491699f, 0.211426f, -0.491699f,
-0.195801f, -0.491699f, 0.195801f, -0.345215f, 0.409668f, -0.345215f, 0.409668f, -0.491699f,
-0.394043f, -0.491699f, 0.35791f, -0.491699f, 0.342529f, -0.505615f, 0.327148f, -0.519531f,
-0.327148f, -0.541992f, 0.327148f, -0.564453f, 0.342529f, -0.578369f, 0.35791f, -0.592285f,
-0.394043f, -0.592285f, 0.496094f, -0.591797f, 0.532227f, -0.591797f, 0.547607f, -0.578125f,
-0.562988f, -0.564453f, 0.562988f, -0.541992f, 0.562988f, -0.521484f, 0.549561f, -0.507812f,
-0.536133f, -0.494141f, 0.509766f, -0.491699f, 0.509766f, -0.100098f, 0.54834f, -0.100098f,
-0.55957f, -0.0927734f, 0.583496f, -0.0776367f, 0.583496f, -0.0498047f, 0.583496f,
--0.027832f, 0.568115f, -0.013916f, 0.552734f, 0, 0.516602f, 0, 0.394043f, 0, 0.35791f,
-0, 0.342529f, -0.013916f, 0.327148f, -0.027832f, 0.327148f, -0.050293f, 0.327148f,
--0.0722656f, 0.342773f, -0.0861816f, 0.358398f, -0.100098f, 0.394043f, -0.100098f,
-0.409668f, -0.100098f, 0.348633f, -0.491699f, 0.348633f, -0.100098f, 0.416016f, -0.100098f,
-0.452148f, -0.100098f, 0.467529f, -0.0861816f, 0.48291f, -0.0722656f, 0.48291f, -0.0498047f,
-0.48291f, -0.027832f, 0.467529f, -0.013916f, 0.452148f, 0, 0.416016f, 0, 0.181641f,
-0, 0.145508f, 0, 0.130127f, -0.013916f, 0.114746f, -0.027832f, 0.114746f, -0.050293f,
-0.114746f, -0.0722656f, 0.130127f, -0.0861816f, 0.145508f, -0.100098f, 0.181641f,
--0.100098f, 0.248535f, -0.100098f, 0.248535f, -0.491699f, 0.140137f, -0.491699f,
-0.140137f, -0.396973f, 0.140137f, -0.36084f, 0.126221f, -0.345459f, 0.112305f, -0.330078f,
-0.0898438f, -0.330078f, 0.0678711f, -0.330078f, 0.0539551f, -0.345459f, 0.0400391f,
--0.36084f, 0.0400391f, -0.396973f, 0.0400391f, -0.592285f, 0.558594f, -0.591797f,
-0.558594f, -0.396973f, 0.558594f, -0.36084f, 0.544678f, -0.345459f, 0.530762f, -0.330078f,
-0.508301f, -0.330078f, 0.486328f, -0.330078f, 0.472412f, -0.345459f, 0.458496f, -0.36084f,
-0.458496f, -0.396973f, 0.458496f, -0.491699f, 0.300293f, -0.28418f, 0.20752f, 0,
-0.0952148f, 0, 0.0356445f, -0.491699f, 0.0126953f, -0.494629f, 0.000976562f, -0.507568f,
--0.0107422f, -0.520508f, -0.0107422f, -0.540527f, -0.0107422f, -0.563965f, 0.00463867f,
--0.578125f, 0.0200195f, -0.592285f, 0.0561523f, -0.592285f, 0.189453f, -0.591797f,
-0.225586f, -0.591797f, 0.240967f, -0.578125f, 0.256348f, -0.564453f, 0.256348f, -0.541992f,
-0.256348f, -0.519531f, 0.240967f, -0.505615f, 0.225586f, -0.491699f, 0.189453f, -0.491699f,
-0.137207f, -0.491699f, 0.17041f, -0.211914f, 0.249023f, -0.444824f, 0.353027f, -0.444824f,
-0.431152f, -0.211914f, 0.464355f, -0.491699f, 0.412109f, -0.491699f, 0.375977f, -0.491699f,
-0.360596f, -0.505615f, 0.345215f, -0.519531f, 0.345215f, -0.541992f, 0.345215f, -0.564453f,
-0.360596f, -0.578369f, 0.375977f, -0.592285f, 0.412109f, -0.592285f, 0.544922f, -0.591797f,
-0.581055f, -0.591797f, 0.596436f, -0.578125f, 0.611816f, -0.564453f, 0.611816f, -0.541992f,
-0.611816f, -0.522949f, 0.599609f, -0.509277f, 0.587402f, -0.495605f, 0.564453f, -0.491699f,
-0.506836f, 0, 0.396484f, 0, 0.350586f, -0.248535f, 0.350586f, -0.100098f, 0.417969f,
--0.100098f, 0.454102f, -0.100098f, 0.469482f, -0.0861816f, 0.484863f, -0.0722656f,
-0.484863f, -0.0498047f, 0.484863f, -0.027832f, 0.469482f, -0.013916f, 0.454102f,
-0, 0.417969f, 0, 0.183105f, 0, 0.147461f, 0, 0.13208f, -0.013916f, 0.116699f, -0.027832f,
-0.116699f, -0.050293f, 0.116699f, -0.0722656f, 0.13208f, -0.0861816f, 0.147461f,
--0.100098f, 0.183105f, -0.100098f, 0.250488f, -0.100098f, 0.250488f, -0.248535f,
-0.0849609f, -0.491699f, 0.0517578f, -0.491699f, 0.036377f, -0.505859f, 0.0209961f,
--0.52002f, 0.0209961f, -0.541992f, 0.0209961f, -0.564453f, 0.036377f, -0.578369f,
-0.0517578f, -0.592285f, 0.0878906f, -0.592285f, 0.178711f, -0.591797f, 0.214844f,
--0.591797f, 0.230225f, -0.578125f, 0.245605f, -0.564453f, 0.245605f, -0.541992f,
-0.245605f, -0.508301f, 0.206055f, -0.491699f, 0.300781f, -0.352051f, 0.393555f, -0.491699f,
-0.371582f, -0.5f, 0.362305f, -0.512695f, 0.353027f, -0.525391f, 0.353027f, -0.541992f,
-0.353027f, -0.564453f, 0.368408f, -0.578125f, 0.383789f, -0.591797f, 0.419922f, -0.592285f,
-0.51416f, -0.591797f, 0.550293f, -0.591797f, 0.565674f, -0.578125f, 0.581055f, -0.564453f,
-0.581055f, -0.541992f, 0.581055f, -0.519531f, 0.56543f, -0.505615f, 0.549805f, -0.491699f,
-0.514648f, -0.491699f, 0.390137f, 0, 0.390137f, -0.0234375f, 0.352539f, -0.00341797f,
-0.307129f, 0.0065918f, 0.261719f, 0.0166016f, 0.224609f, 0.0166016f, 0.144043f, 0.0166016f,
-0.09375f, -0.026123f, 0.043457f, -0.0688477f, 0.043457f, -0.120605f, 0.043457f, -0.183594f,
-0.107666f, -0.237549f, 0.171875f, -0.291504f, 0.285156f, -0.291504f, 0.330566f, -0.291504f,
-0.390137f, -0.281738f, 0.390137f, -0.305664f, 0.390137f, -0.328125f, 0.37085f, -0.342285f,
-0.351562f, -0.356445f, 0.297363f, -0.356445f, 0.25293f, -0.356445f, 0.182129f, -0.338867f,
-0.155762f, -0.33252f, 0.141113f, -0.33252f, 0.121094f, -0.33252f, 0.107178f, -0.346924f,
-0.0932617f, -0.361328f, 0.0932617f, -0.383789f, 0.0932617f, -0.396484f, 0.0981445f,
--0.405762f, 0.103027f, -0.415039f, 0.111816f, -0.420654f, 0.120605f, -0.42627f, 0.148438f,
--0.434082f, 0.185547f, -0.444336f, 0.224121f, -0.450439f, 0.262695f, -0.456543f,
-0.293945f, -0.456543f, 0.387207f, -0.456543f, 0.438721f, -0.41626f, 0.490234f, -0.375977f,
-0.490234f, -0.306152f, 0.490234f, -0.100098f, 0.507324f, -0.100098f, 0.543457f, -0.100098f,
-0.558838f, -0.0861816f, 0.574219f, -0.0722656f, 0.574219f, -0.0498047f, 0.574219f,
--0.027832f, 0.558838f, -0.013916f, 0.543457f, 0, 0.507324f, 0, 0.390137f, -0.179199f,
-0.330078f, -0.190918f, 0.279297f, -0.190918f, 0.218262f, -0.190918f, 0.174316f, -0.161133f,
-0.146973f, -0.14209f, 0.146973f, -0.122559f, 0.146973f, -0.108398f, 0.160156f, -0.0996094f,
-0.18457f, -0.0834961f, 0.227051f, -0.0834961f, 0.263184f, -0.0834961f, 0.308838f,
--0.0976562f, 0.354492f, -0.111816f, 0.390137f, -0.13623f, 0.173828f, -0.633301f,
-0.173828f, -0.408691f, 0.210449f, -0.432617f, 0.248291f, -0.44458f, 0.286133f, -0.456543f,
-0.324707f, -0.456543f, 0.428711f, -0.456543f, 0.500977f, -0.384766f, 0.573242f, -0.312988f,
-0.573242f, -0.211426f, 0.573242f, -0.114258f, 0.504395f, -0.0490723f, 0.435547f,
-0.0161133f, 0.322754f, 0.0161133f, 0.282715f, 0.0161133f, 0.245605f, 0.00585938f,
-0.208496f, -0.00439453f, 0.173828f, -0.0244141f, 0.173828f, 0, 0.0566406f, 0, 0.0205078f,
-0, 0.00512695f, -0.013916f, -0.0102539f, -0.027832f, -0.0102539f, -0.050293f, -0.0102539f,
--0.0722656f, 0.00537109f, -0.0861816f, 0.0209961f, -0.100098f, 0.0566406f, -0.100098f,
-0.0737305f, -0.100098f, 0.0737305f, -0.533203f, 0.0566406f, -0.533203f, 0.0205078f,
--0.533203f, 0.00512695f, -0.547119f, -0.0102539f, -0.561035f, -0.0102539f, -0.583496f,
--0.0102539f, -0.605469f, 0.00512695f, -0.619385f, 0.0205078f, -0.633301f, 0.0566406f,
--0.633301f, 0.473145f, -0.208496f, 0.473145f, -0.270508f, 0.429688f, -0.313477f,
-0.38623f, -0.356445f, 0.323242f, -0.356445f, 0.260742f, -0.356445f, 0.217285f, -0.313477f,
-0.173828f, -0.270508f, 0.173828f, -0.209961f, 0.173828f, -0.154785f, 0.212891f, -0.119385f,
-0.251953f, -0.0839844f, 0.323242f, -0.0839844f, 0.394531f, -0.0839844f, 0.433838f,
--0.119385f, 0.473145f, -0.154785f, 0.473145f, -0.208496f, 0.55127f, -0.170898f, 0.140625f,
--0.170898f, 0.15625f, -0.131836f, 0.196045f, -0.10791f, 0.23584f, -0.0839844f, 0.303711f,
--0.0839844f, 0.359375f, -0.0839844f, 0.45166f, -0.10791f, 0.489746f, -0.117676f,
-0.504395f, -0.117676f, 0.524414f, -0.117676f, 0.538086f, -0.103516f, 0.551758f, -0.0893555f,
-0.551758f, -0.0678711f, 0.551758f, -0.0483398f, 0.537109f, -0.034668f, 0.517578f,
--0.0166016f, 0.441895f, -0.000244141f, 0.366211f, 0.0161133f, 0.296387f, 0.0161133f,
-0.17627f, 0.0161133f, 0.104248f, -0.0517578f, 0.0322266f, -0.119629f, 0.0322266f,
--0.21875f, 0.0322266f, -0.324219f, 0.110107f, -0.390381f, 0.187988f, -0.456543f,
-0.289551f, -0.456543f, 0.350586f, -0.456543f, 0.401611f, -0.435059f, 0.452637f, -0.413574f,
-0.477539f, -0.388672f, 0.512695f, -0.352539f, 0.535645f, -0.299316f, 0.55127f, -0.262207f,
-0.55127f, -0.213379f, 0.44043f, -0.270996f, 0.41748f, -0.313965f, 0.380371f, -0.335205f,
-0.343262f, -0.356445f, 0.291992f, -0.356445f, 0.241211f, -0.356445f, 0.204102f, -0.335205f,
-0.166992f, -0.313965f, 0.143555f, -0.270996f, 0.299316f, -0.343262f, 0.299316f, -0.100098f,
-0.441895f, -0.100098f, 0.478027f, -0.100098f, 0.493408f, -0.0861816f, 0.508789f,
--0.0722656f, 0.508789f, -0.0498047f, 0.508789f, -0.027832f, 0.493408f, -0.013916f,
-0.478027f, 0, 0.441895f, 0, 0.139648f, 0, 0.103516f, 0, 0.0881348f, -0.013916f, 0.0727539f,
--0.027832f, 0.0727539f, -0.050293f, 0.0727539f, -0.0722656f, 0.0881348f, -0.0861816f,
-0.103516f, -0.100098f, 0.139648f, -0.100098f, 0.199219f, -0.100098f, 0.199219f, -0.343262f,
-0.151367f, -0.343262f, 0.115234f, -0.343262f, 0.0998535f, -0.357178f, 0.0844727f,
--0.371094f, 0.0844727f, -0.393555f, 0.0844727f, -0.415527f, 0.0998535f, -0.429443f,
-0.115234f, -0.443359f, 0.151367f, -0.443359f, 0.199219f, -0.443359f, 0.199219f, -0.481445f,
-0.199219f, -0.546875f, 0.248291f, -0.590088f, 0.297363f, -0.633301f, 0.390625f, -0.633301f,
-0.432129f, -0.633301f, 0.486572f, -0.625732f, 0.541016f, -0.618164f, 0.556396f, -0.604492f,
-0.571777f, -0.59082f, 0.571777f, -0.569336f, 0.571777f, -0.546387f, 0.558105f, -0.531982f,
-0.544434f, -0.517578f, 0.524414f, -0.517578f, 0.515137f, -0.517578f, 0.496582f, -0.520996f,
-0.43457f, -0.533203f, 0.386719f, -0.533203f, 0.336914f, -0.533203f, 0.318115f, -0.518311f,
-0.299316f, -0.503418f, 0.299316f, -0.481445f, 0.299316f, -0.443359f, 0.453613f, -0.443359f,
-0.489746f, -0.443359f, 0.505127f, -0.429443f, 0.520508f, -0.415527f, 0.520508f, -0.393066f,
-0.520508f, -0.371094f, 0.505127f, -0.357178f, 0.489746f, -0.343262f, 0.453613f, -0.343262f,
-0.410156f, -0.413574f, 0.410156f, -0.443359f, 0.527344f, -0.443359f, 0.563477f, -0.443359f,
-0.578857f, -0.429443f, 0.594238f, -0.415527f, 0.594238f, -0.393066f, 0.594238f, -0.371094f,
-0.578857f, -0.357178f, 0.563477f, -0.343262f, 0.527344f, -0.343262f, 0.510254f, -0.343262f,
-0.510254f, 0.0209961f, 0.510254f, 0.0737305f, 0.488037f, 0.113037f, 0.46582f, 0.152344f,
-0.419922f, 0.180664f, 0.374023f, 0.208984f, 0.316406f, 0.208984f, 0.203125f, 0.208984f,
-0.166992f, 0.208984f, 0.151611f, 0.195068f, 0.13623f, 0.181152f, 0.13623f, 0.15918f,
-0.13623f, 0.136719f, 0.151611f, 0.122803f, 0.166992f, 0.108887f, 0.203125f, 0.108887f,
-0.313477f, 0.108887f, 0.359375f, 0.108887f, 0.384766f, 0.0839844f, 0.410156f, 0.059082f,
-0.410156f, 0.0209961f, 0.410156f, -0.027832f, 0.376953f, -0.00634766f, 0.342529f,
-0.00439453f, 0.308105f, 0.0151367f, 0.271973f, 0.0151367f, 0.169922f, 0.0151367f,
-0.101074f, -0.0529785f, 0.0322266f, -0.121094f, 0.0322266f, -0.221191f, 0.0322266f,
--0.321777f, 0.101074f, -0.389893f, 0.169922f, -0.458008f, 0.271973f, -0.458008f,
-0.310059f, -0.458008f, 0.344482f, -0.447021f, 0.378906f, -0.436035f, 0.410156f, -0.413574f,
-0.409668f, -0.22168f, 0.409668f, -0.276855f, 0.368896f, -0.317383f, 0.328125f, -0.35791f,
-0.270996f, -0.35791f, 0.213867f, -0.35791f, 0.173096f, -0.317383f, 0.132324f, -0.276855f,
-0.132324f, -0.22168f, 0.132324f, -0.166016f, 0.173096f, -0.125732f, 0.213867f, -0.0854492f,
-0.270996f, -0.0854492f, 0.328125f, -0.0854492f, 0.368896f, -0.125732f, 0.409668f,
--0.166016f, 0.409668f, -0.22168f, 0.145508f, -0.443359f, 0.145508f, -0.415039f, 0.169922f,
--0.438965f, 0.189697f, -0.447998f, 0.209473f, -0.457031f, 0.235352f, -0.457031f,
-0.257324f, -0.457031f, 0.278809f, -0.446289f, 0.300293f, -0.435547f, 0.320801f, -0.414062f,
-0.34668f, -0.435547f, 0.373291f, -0.446045f, 0.399902f, -0.456543f, 0.427734f, -0.456543f,
-0.483398f, -0.456543f, 0.518066f, -0.426758f, 0.563965f, -0.387695f, 0.563965f, -0.324219f,
-0.563965f, -0.100098f, 0.595215f, -0.100098f, 0.610352f, -0.0859375f, 0.625488f,
--0.0717773f, 0.625488f, -0.0498047f, 0.625488f, -0.027832f, 0.610352f, -0.013916f,
-0.595215f, 0, 0.559082f, 0, 0.463867f, 0, 0.463867f, -0.315918f, 0.463867f, -0.338867f,
-0.455566f, -0.347656f, 0.447266f, -0.356445f, 0.430176f, -0.356445f, 0.413574f, -0.356445f,
-0.399414f, -0.347656f, 0.381348f, -0.335449f, 0.355469f, -0.301758f, 0.355469f, -0.100098f,
-0.386719f, -0.100098f, 0.401855f, -0.0859375f, 0.416992f, -0.0717773f, 0.416992f,
--0.0498047f, 0.416992f, -0.027832f, 0.401855f, -0.013916f, 0.386719f, 0, 0.350586f,
-0, 0.255371f, 0, 0.255371f, -0.315918f, 0.255371f, -0.338379f, 0.246826f, -0.347412f,
-0.238281f, -0.356445f, 0.221191f, -0.356445f, 0.203613f, -0.356445f, 0.186523f, -0.345459f,
-0.169434f, -0.334473f, 0.145508f, -0.301758f, 0.145508f, -0.100098f, 0.176758f, -0.100098f,
-0.192139f, -0.0859375f, 0.20752f, -0.0717773f, 0.20752f, -0.0498047f, 0.20752f, -0.027832f,
-0.192139f, -0.013916f, 0.176758f, 0, 0.140625f, 0, 0.050293f, 0, 0.0141602f, 0, -0.0012207f,
--0.013916f, -0.0166016f, -0.027832f, -0.0166016f, -0.050293f, -0.0166016f, -0.0722656f,
--0.00146484f, -0.0861816f, 0.0136719f, -0.100098f, 0.0454102f, -0.100098f, 0.0454102f,
--0.343262f, 0.0136719f, -0.343262f, -0.00146484f, -0.357422f, -0.0166016f, -0.371582f,
--0.0166016f, -0.393555f, -0.0166016f, -0.415527f, -0.0012207f, -0.429443f, 0.0141602f,
--0.443359f, 0.050293f, -0.443359f, 0.19873f, -0.443359f, 0.19873f, -0.409668f, 0.226074f,
--0.433105f, 0.259033f, -0.444824f, 0.291992f, -0.456543f, 0.330566f, -0.456543f,
-0.419434f, -0.456543f, 0.471191f, -0.401367f, 0.512207f, -0.357422f, 0.512207f, -0.286133f,
-0.512207f, -0.100098f, 0.543945f, -0.100098f, 0.559082f, -0.0861816f, 0.574219f,
--0.0722656f, 0.574219f, -0.0498047f, 0.574219f, -0.027832f, 0.558838f, -0.013916f,
-0.543457f, 0, 0.507324f, 0, 0.416992f, 0, 0.380859f, 0, 0.365479f, -0.013916f, 0.350098f,
--0.027832f, 0.350098f, -0.050293f, 0.350098f, -0.0722656f, 0.365234f, -0.0861816f,
-0.380371f, -0.100098f, 0.412109f, -0.100098f, 0.412109f, -0.289062f, 0.412109f, -0.321777f,
-0.394531f, -0.336914f, 0.371582f, -0.356445f, 0.325684f, -0.356445f, 0.291016f, -0.356445f,
-0.264893f, -0.343018f, 0.23877f, -0.32959f, 0.19873f, -0.286133f, 0.19873f, -0.100098f,
-0.237305f, -0.100098f, 0.248535f, -0.0927734f, 0.272461f, -0.078125f, 0.272461f,
--0.0498047f, 0.272461f, -0.027832f, 0.25708f, -0.013916f, 0.241699f, 0, 0.205566f,
-0, 0.0917969f, 0, 0.0556641f, 0, 0.0402832f, -0.013916f, 0.0249023f, -0.027832f,
-0.0249023f, -0.050293f, 0.0249023f, -0.0776367f, 0.0483398f, -0.0927734f, 0.0600586f,
--0.100098f, 0.0986328f, -0.100098f, 0.0986328f, -0.343262f, 0.0668945f, -0.343262f,
-0.0517578f, -0.357422f, 0.0366211f, -0.371582f, 0.0366211f, -0.393555f, 0.0366211f,
--0.415527f, 0.052002f, -0.429443f, 0.0673828f, -0.443359f, 0.103516f, -0.443359f,
-0.560059f, -0.213379f, 0.560059f, -0.155762f, 0.528076f, -0.101807f, 0.496094f, -0.0478516f,
-0.432861f, -0.0158691f, 0.369629f, 0.0161133f, 0.300781f, 0.0161133f, 0.232422f,
-0.0161133f, 0.169922f, -0.0153809f, 0.107422f, -0.046875f, 0.074707f, -0.101074f,
-0.0419922f, -0.155273f, 0.0419922f, -0.214355f, 0.0419922f, -0.274414f, 0.0751953f,
--0.332275f, 0.108398f, -0.390137f, 0.170654f, -0.42334f, 0.23291f, -0.456543f, 0.300781f,
--0.456543f, 0.369141f, -0.456543f, 0.432373f, -0.422607f, 0.495605f, -0.388672f,
-0.527832f, -0.331299f, 0.560059f, -0.273926f, 0.560059f, -0.213379f, 0.459961f, -0.212891f,
-0.459961f, -0.26123f, 0.425293f, -0.301758f, 0.37793f, -0.356445f, 0.300781f, -0.356445f,
-0.23291f, -0.356445f, 0.1875f, -0.312988f, 0.14209f, -0.269531f, 0.14209f, -0.212402f,
-0.14209f, -0.165527f, 0.187988f, -0.124756f, 0.233887f, -0.0839844f, 0.300781f, -0.0839844f,
-0.368164f, -0.0839844f, 0.414062f, -0.124756f, 0.459961f, -0.165527f, 0.459961f,
--0.212891f, 0.175781f, -0.0551758f, 0.175781f, 0.108887f, 0.23584f, 0.108887f, 0.271973f,
-0.108887f, 0.287354f, 0.122803f, 0.302734f, 0.136719f, 0.302734f, 0.15918f, 0.302734f,
-0.181152f, 0.287354f, 0.195068f, 0.271973f, 0.208984f, 0.23584f, 0.208984f, 0.0585938f,
-0.208984f, 0.0224609f, 0.208984f, 0.00708008f, 0.195068f, -0.00830078f, 0.181152f,
--0.00830078f, 0.15918f, -0.00830078f, 0.136719f, 0.00732422f, 0.122803f, 0.0229492f,
-0.108887f, 0.0585938f, 0.108887f, 0.0756836f, 0.108887f, 0.0756836f, -0.343262f,
-0.0585938f, -0.343262f, 0.0224609f, -0.343262f, 0.00708008f, -0.357178f, -0.00830078f,
--0.371094f, -0.00830078f, -0.393555f, -0.00830078f, -0.415527f, 0.00708008f, -0.429443f,
-0.0224609f, -0.443359f, 0.0585938f, -0.443359f, 0.175781f, -0.443359f, 0.175781f,
--0.40918f, 0.210938f, -0.433105f, 0.248535f, -0.444824f, 0.286133f, -0.456543f, 0.325684f,
--0.456543f, 0.428223f, -0.456543f, 0.500488f, -0.386963f, 0.572754f, -0.317383f,
-0.572754f, -0.227539f, 0.572754f, -0.128418f, 0.487305f, -0.0639648f, 0.416016f,
--0.0102539f, 0.32666f, -0.0102539f, 0.288086f, -0.0102539f, 0.250488f, -0.0214844f,
-0.212891f, -0.0327148f, 0.175781f, -0.0551758f, 0.472656f, -0.227051f, 0.472656f,
--0.248047f, 0.456055f, -0.280518f, 0.439453f, -0.312988f, 0.405029f, -0.334717f,
-0.370605f, -0.356445f, 0.324219f, -0.356445f, 0.249512f, -0.356445f, 0.205566f, -0.300293f,
-0.175781f, -0.261719f, 0.175781f, -0.226074f, 0.175781f, -0.186035f, 0.218506f, -0.148193f,
-0.26123f, -0.110352f, 0.324219f, -0.110352f, 0.387695f, -0.110352f, 0.430176f, -0.147949f,
-0.472656f, -0.185547f, 0.472656f, -0.227051f, 0.279297f, -0.443359f, 0.279297f, -0.380859f,
-0.342285f, -0.42627f, 0.378662f, -0.441406f, 0.415039f, -0.456543f, 0.446777f, -0.456543f,
-0.495605f, -0.456543f, 0.541504f, -0.42041f, 0.572754f, -0.395996f, 0.572754f, -0.370605f,
-0.572754f, -0.349121f, 0.557861f, -0.334229f, 0.542969f, -0.319336f, 0.521973f, -0.319336f,
-0.503418f, -0.319336f, 0.48291f, -0.337891f, 0.462402f, -0.356445f, 0.446289f, -0.356445f,
-0.425293f, -0.356445f, 0.383545f, -0.330078f, 0.341797f, -0.303711f, 0.279297f, -0.250977f,
-0.279297f, -0.100098f, 0.421875f, -0.100098f, 0.458008f, -0.100098f, 0.473389f, -0.0861816f,
-0.48877f, -0.0722656f, 0.48877f, -0.0498047f, 0.48877f, -0.027832f, 0.473389f, -0.013916f,
-0.458008f, 0, 0.421875f, 0, 0.119629f, 0, 0.0834961f, 0, 0.0681152f, -0.013916f,
-0.0527344f, -0.027832f, 0.0527344f, -0.050293f, 0.0527344f, -0.0722656f, 0.0681152f,
--0.0861816f, 0.0834961f, -0.100098f, 0.119629f, -0.100098f, 0.179199f, -0.100098f,
-0.179199f, -0.343262f, 0.143066f, -0.343262f, 0.106934f, -0.343262f, 0.0915527f,
--0.357178f, 0.0761719f, -0.371094f, 0.0761719f, -0.393555f, 0.0761719f, -0.415527f,
-0.0915527f, -0.429443f, 0.106934f, -0.443359f, 0.143066f, -0.443359f, 0.408203f,
--0.326172f, 0.383789f, -0.341309f, 0.356934f, -0.348877f, 0.330078f, -0.356445f,
-0.300781f, -0.356445f, 0.242676f, -0.356445f, 0.208496f, -0.337402f, 0.193359f, -0.329102f,
-0.193359f, -0.319336f, 0.193359f, -0.308105f, 0.213867f, -0.297363f, 0.229492f, -0.289551f,
-0.283691f, -0.282227f, 0.383301f, -0.268555f, 0.422363f, -0.254883f, 0.473633f, -0.236816f,
-0.501465f, -0.201172f, 0.529297f, -0.165527f, 0.529297f, -0.125977f, 0.529297f, -0.0722656f,
-0.481934f, -0.0361328f, 0.414062f, 0.0161133f, 0.305664f, 0.0161133f, 0.262207f,
-0.0161133f, 0.225342f, 0.00854492f, 0.188477f, 0.000976562f, 0.157715f, -0.0136719f,
-0.150391f, -0.00732422f, 0.14209f, -0.00390625f, 0.133789f, -0.000488281f, 0.125f,
--0.000488281f, 0.101562f, -0.000488281f, 0.0876465f, -0.0158691f, 0.0737305f, -0.03125f,
-0.0737305f, -0.0673828f, 0.0737305f, -0.101074f, 0.0737305f, -0.137207f, 0.0876465f,
--0.152588f, 0.101562f, -0.167969f, 0.124023f, -0.167969f, 0.14209f, -0.167969f, 0.154297f,
--0.157959f, 0.166504f, -0.147949f, 0.17334f, -0.123535f, 0.196289f, -0.104004f, 0.228516f,
--0.0939941f, 0.260742f, -0.0839844f, 0.302734f, -0.0839844f, 0.371582f, -0.0839844f,
-0.409668f, -0.105469f, 0.427734f, -0.116211f, 0.427734f, -0.12793f, 0.427734f, -0.147461f,
-0.401855f, -0.160156f, 0.375977f, -0.172852f, 0.294922f, -0.181641f, 0.174316f, -0.194336f,
-0.133789f, -0.230469f, 0.0932617f, -0.266113f, 0.0932617f, -0.318359f, 0.0932617f,
--0.37207f, 0.138672f, -0.407715f, 0.200195f, -0.456543f, 0.299805f, -0.456543f, 0.334473f,
--0.456543f, 0.366455f, -0.449951f, 0.398438f, -0.443359f, 0.427734f, -0.429688f,
-0.437012f, -0.436523f, 0.445068f, -0.439941f, 0.453125f, -0.443359f, 0.459961f, -0.443359f,
-0.480469f, -0.443359f, 0.494141f, -0.427979f, 0.507812f, -0.412598f, 0.507812f, -0.376465f,
-0.507812f, -0.352051f, 0.507812f, -0.319336f, 0.5f, -0.307617f, 0.484375f, -0.285156f,
-0.45752f, -0.285156f, 0.439453f, -0.285156f, 0.425781f, -0.296387f, 0.412109f, -0.307617f,
-0.408203f, -0.326172f, 0.512695f, -0.443359f, 0.512695f, -0.100098f, 0.544434f, -0.100098f,
-0.55957f, -0.0859375f, 0.574707f, -0.0717773f, 0.574707f, -0.0498047f, 0.574707f,
--0.027832f, 0.559326f, -0.013916f, 0.543945f, 0, 0.507812f, 0, 0.412598f, 0, 0.412598f,
--0.0229492f, 0.369629f, -0.00341797f, 0.330566f, 0.00634766f, 0.291504f, 0.0161133f,
-0.256348f, 0.0161133f, 0.207031f, 0.0161133f, 0.170898f, -0.00463867f, 0.134766f,
--0.0253906f, 0.11377f, -0.0620117f, 0.0986328f, -0.0883789f, 0.0986328f, -0.12793f,
-0.0986328f, -0.343262f, 0.081543f, -0.343262f, 0.0454102f, -0.343262f, 0.0300293f,
--0.357178f, 0.0146484f, -0.371094f, 0.0146484f, -0.393555f, 0.0146484f, -0.415527f,
-0.0300293f, -0.429443f, 0.0454102f, -0.443359f, 0.081543f, -0.443359f, 0.19873f,
--0.443359f, 0.19873f, -0.145508f, 0.19873f, -0.11377f, 0.214111f, -0.098877f, 0.229492f,
--0.0839844f, 0.26123f, -0.0839844f, 0.291504f, -0.0839844f, 0.326416f, -0.0959473f,
-0.361328f, -0.10791f, 0.412598f, -0.13916f, 0.412598f, -0.343262f, 0.376465f, -0.343262f,
-0.340332f, -0.343262f, 0.324951f, -0.357178f, 0.30957f, -0.371094f, 0.30957f, -0.393555f,
-0.30957f, -0.415527f, 0.324951f, -0.429443f, 0.340332f, -0.443359f, 0.376465f, -0.443359f,
-0.244141f, -0.00341797f, 0.0708008f, -0.343262f, 0.0463867f, -0.346191f, 0.0336914f,
--0.359863f, 0.0209961f, -0.373535f, 0.0209961f, -0.393066f, 0.0209961f, -0.415527f,
-0.036377f, -0.429443f, 0.0517578f, -0.443359f, 0.0878906f, -0.443359f, 0.179199f,
--0.443359f, 0.215332f, -0.443359f, 0.230713f, -0.429443f, 0.246094f, -0.415527f,
-0.246094f, -0.393066f, 0.246094f, -0.371094f, 0.230713f, -0.357178f, 0.215332f, -0.343262f,
-0.182129f, -0.343262f, 0.300293f, -0.113281f, 0.41748f, -0.343262f, 0.385254f, -0.343262f,
-0.369873f, -0.357178f, 0.354492f, -0.371094f, 0.354492f, -0.393555f, 0.354492f, -0.415527f,
-0.369873f, -0.429443f, 0.385254f, -0.443359f, 0.421387f, -0.443359f, 0.515625f, -0.443359f,
-0.55127f, -0.443359f, 0.56665f, -0.429443f, 0.582031f, -0.415527f, 0.582031f, -0.393066f,
-0.582031f, -0.373047f, 0.568848f, -0.359131f, 0.555664f, -0.345215f, 0.529785f, -0.343262f,
-0.300293f, 0.108887f, 0.337891f, 0.108887f, 0.349609f, 0.116211f, 0.373047f, 0.131348f,
-0.373047f, 0.15918f, 0.373047f, 0.181152f, 0.357666f, 0.195068f, 0.342285f, 0.208984f,
-0.306152f, 0.208984f, 0.0878906f, 0.208984f, 0.0517578f, 0.208984f, 0.036377f, 0.195068f,
-0.0209961f, 0.181152f, 0.0209961f, 0.15918f, 0.0209961f, 0.136719f, 0.036377f, 0.122803f,
-0.0517578f, 0.108887f, 0.0878906f, 0.108887f, 0.1875f, 0.108887f
-};
-
-const unsigned char CourierNewkBoldVerbs[] = {
-6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 5, 0, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1,
-1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-5, 0, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2,
-2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6
-};
-
-const unsigned CourierNewkBoldCharCodes[] = {
-32, 65, 72, 84, 87,
-89, 97, 98, 101, 102, 103, 109, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed CourierNewkBoldWidths[] = {
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
-};
-
-const int CourierNewkBoldCharCodesCount = (int) SK_ARRAY_COUNT(CourierNewkBoldCharCodes);
-
-const SkPaint::FontMetrics CourierNewkBoldMetrics = {
-0x00000003, -1.22119f, -0.83252f, 0.300293f, 0.710449f, 0, 0.893555f, 0, -0.191895f,
-0.70166f, 0.458008f, 0, 0.100098f, 0.23291f
-};
-
-const SkScalar CourierNewkItalicPoints[] = {
-0.496582f, -0.190918f, 0.227051f, -0.190918f, 0.139648f, -0.0410156f, 0.218262f, -0.0410156f,
-0.232422f, -0.0410156f, 0.237305f, -0.0368652f, 0.242188f, -0.0327148f, 0.242188f,
--0.0249023f, 0.242188f, -0.0146484f, 0.233887f, -0.00732422f, 0.225586f, 0, 0.209473f,
-0, 0.0566406f, 0, 0.0429688f, 0, 0.0380859f, -0.00439453f, 0.0332031f, -0.00878906f,
-0.0332031f, -0.0166016f, 0.0332031f, -0.0263672f, 0.0412598f, -0.0336914f, 0.0493164f,
--0.0410156f, 0.0654297f, -0.0410156f, 0.0966797f, -0.0410156f, 0.382324f, -0.530273f,
-0.26123f, -0.530273f, 0.247559f, -0.530273f, 0.242676f, -0.534424f, 0.237793f, -0.538574f,
-0.237793f, -0.546875f, 0.237793f, -0.556641f, 0.24585f, -0.563965f, 0.253906f, -0.571289f,
-0.27002f, -0.571289f, 0.476074f, -0.571289f, 0.563965f, -0.0410156f, 0.595703f, -0.0410156f,
-0.609375f, -0.0410156f, 0.614258f, -0.0368652f, 0.619141f, -0.0327148f, 0.619141f,
--0.0249023f, 0.619141f, -0.0146484f, 0.611084f, -0.00732422f, 0.603027f, 0, 0.586914f,
-0, 0.433594f, 0, 0.419922f, 0, 0.415039f, -0.00439453f, 0.410156f, -0.00878906f,
-0.410156f, -0.0166016f, 0.410156f, -0.0263672f, 0.418213f, -0.0336914f, 0.42627f,
--0.0410156f, 0.442383f, -0.0410156f, 0.520996f, -0.0410156f, 0.489746f, -0.231934f,
-0.439941f, -0.530273f, 0.424805f, -0.530273f, 0.250977f, -0.231934f, 0.49707f, -0.276367f,
-0.224609f, -0.276367f, 0.174805f, -0.0410156f, 0.221191f, -0.0410156f, 0.243652f,
--0.0410156f, 0.248535f, -0.0368652f, 0.253418f, -0.0327148f, 0.253418f, -0.0249023f,
-0.253418f, -0.0146484f, 0.245361f, -0.00732422f, 0.237305f, 0, 0.221191f, 0, 0.0786133f,
-0, 0.0649414f, 0, 0.0605469f, -0.00561523f, 0.0561523f, -0.0112305f, 0.0561523f,
--0.019043f, 0.0561523f, -0.0288086f, 0.0637207f, -0.0349121f, 0.0712891f, -0.0410156f,
-0.0874023f, -0.0410156f, 0.133789f, -0.0410156f, 0.237793f, -0.530273f, 0.191895f,
--0.530273f, 0.171387f, -0.530273f, 0.164307f, -0.53418f, 0.157227f, -0.538086f, 0.158203f,
--0.54834f, 0.158203f, -0.557617f, 0.164795f, -0.563721f, 0.171387f, -0.569824f, 0.192383f,
--0.571777f, 0.32959f, -0.571777f, 0.347168f, -0.569336f, 0.351807f, -0.567627f, 0.356445f,
--0.565918f, 0.35791f, -0.556152f, 0.35791f, -0.545898f, 0.352051f, -0.539062f, 0.346191f,
--0.532227f, 0.325195f, -0.530273f, 0.278809f, -0.530273f, 0.233398f, -0.317383f,
-0.505859f, -0.317383f, 0.550781f, -0.530273f, 0.504395f, -0.530273f, 0.481934f, -0.530273f,
-0.477051f, -0.534424f, 0.472168f, -0.538574f, 0.472168f, -0.546875f, 0.472168f, -0.556641f,
-0.480225f, -0.563965f, 0.488281f, -0.571289f, 0.504395f, -0.571289f, 0.626465f, -0.571289f,
-0.652832f, -0.570801f, 0.661133f, -0.567383f, 0.669434f, -0.563965f, 0.67041f, -0.555176f,
-0.671387f, -0.544922f, 0.664307f, -0.538574f, 0.657227f, -0.532227f, 0.638672f, -0.530273f,
-0.592285f, -0.530273f, 0.488281f, -0.0410156f, 0.53418f, -0.0410156f, 0.554199f,
--0.0419922f, 0.560303f, -0.0354004f, 0.566406f, -0.0288086f, 0.566406f, -0.0209961f,
-0.566406f, -0.0107422f, 0.556396f, -0.00537109f, 0.546387f, 0, 0.525391f, 0, 0.393066f,
-0, 0.379395f, 0, 0.373779f, -0.00366211f, 0.368164f, -0.00732422f, 0.368164f, -0.0151367f,
-0.368164f, -0.0249023f, 0.372559f, -0.0317383f, 0.376953f, -0.0385742f, 0.400391f,
--0.0410156f, 0.446777f, -0.0410156f, 0.433105f, -0.530273f, 0.329102f, -0.0410156f,
-0.435547f, -0.0410156f, 0.449219f, -0.0410156f, 0.454102f, -0.0368652f, 0.458984f,
--0.0327148f, 0.458984f, -0.0249023f, 0.458984f, -0.0146484f, 0.450928f, -0.00732422f,
-0.442871f, 0, 0.426758f, 0, 0.172363f, 0, 0.158691f, 0, 0.153809f, -0.00439453f,
-0.148926f, -0.00878906f, 0.148926f, -0.0166016f, 0.148926f, -0.0263672f, 0.156982f,
--0.0336914f, 0.165039f, -0.0410156f, 0.181152f, -0.0410156f, 0.287598f, -0.0410156f,
-0.391602f, -0.530273f, 0.223633f, -0.530273f, 0.193359f, -0.388184f, 0.19043f, -0.373047f,
-0.18335f, -0.366699f, 0.17627f, -0.360352f, 0.166992f, -0.360352f, 0.159668f, -0.360352f,
-0.155029f, -0.36499f, 0.150391f, -0.369629f, 0.150391f, -0.375488f, 0.150391f, -0.379883f,
-0.152344f, -0.388184f, 0.191406f, -0.571289f, 0.650879f, -0.571289f, 0.611816f, -0.388184f,
-0.608887f, -0.373047f, 0.601562f, -0.366699f, 0.594238f, -0.360352f, 0.584961f, -0.360352f,
-0.578125f, -0.360352f, 0.573486f, -0.36499f, 0.568848f, -0.369629f, 0.568848f, -0.375488f,
-0.568848f, -0.379883f, 0.570801f, -0.388184f, 0.601074f, -0.530273f, 0.47998f, 0,
-0.416016f, 0, 0.385742f, -0.405762f, 0.185547f, 0, 0.121094f, 0, 0.173828f, -0.530273f,
-0.158691f, -0.530273f, 0.14502f, -0.530273f, 0.139893f, -0.534424f, 0.134766f, -0.538574f,
-0.134766f, -0.546875f, 0.134766f, -0.556641f, 0.143066f, -0.563965f, 0.151367f, -0.571289f,
-0.16748f, -0.571289f, 0.319824f, -0.571289f, 0.333496f, -0.571289f, 0.338379f, -0.567139f,
-0.343262f, -0.562988f, 0.343262f, -0.555176f, 0.343262f, -0.544922f, 0.335205f, -0.537598f,
-0.327148f, -0.530273f, 0.311035f, -0.530273f, 0.214844f, -0.530273f, 0.166504f, -0.046875f,
-0.362305f, -0.444824f, 0.424805f, -0.444824f, 0.454102f, -0.046875f, 0.609863f, -0.530273f,
-0.513672f, -0.530273f, 0.5f, -0.530273f, 0.495117f, -0.534424f, 0.490234f, -0.538574f,
-0.490234f, -0.546875f, 0.490234f, -0.556641f, 0.498291f, -0.563965f, 0.506348f, -0.571289f,
-0.522461f, -0.571289f, 0.674316f, -0.571289f, 0.687988f, -0.571289f, 0.692871f, -0.567139f,
-0.697754f, -0.562988f, 0.697754f, -0.555176f, 0.697754f, -0.547852f, 0.692871f, -0.54126f,
-0.687988f, -0.534668f, 0.681152f, -0.532227f, 0.67627f, -0.530273f, 0.650391f, -0.530273f,
-0.375977f, -0.257812f, 0.330078f, -0.0410156f, 0.436523f, -0.0410156f, 0.450195f,
--0.0410156f, 0.455078f, -0.0368652f, 0.459961f, -0.0327148f, 0.459961f, -0.0249023f,
-0.459961f, -0.0146484f, 0.451904f, -0.00732422f, 0.443848f, 0, 0.427734f, 0, 0.17334f,
-0, 0.159668f, 0, 0.154785f, -0.00439453f, 0.149902f, -0.00878906f, 0.149902f, -0.0166016f,
-0.149902f, -0.0263672f, 0.157959f, -0.0336914f, 0.166016f, -0.0410156f, 0.182129f,
--0.0410156f, 0.288574f, -0.0410156f, 0.334961f, -0.257812f, 0.212402f, -0.530273f,
-0.187988f, -0.530273f, 0.174316f, -0.530273f, 0.169434f, -0.534424f, 0.164551f, -0.538574f,
-0.164551f, -0.546875f, 0.164551f, -0.556641f, 0.172607f, -0.563965f, 0.180664f, -0.571289f,
-0.196777f, -0.571289f, 0.30957f, -0.571289f, 0.323242f, -0.571289f, 0.328125f, -0.567139f,
-0.333008f, -0.562988f, 0.333008f, -0.555176f, 0.333008f, -0.544922f, 0.324951f, -0.537598f,
-0.316895f, -0.530273f, 0.300781f, -0.530273f, 0.260254f, -0.530273f, 0.364258f, -0.299316f,
-0.563477f, -0.530273f, 0.523438f, -0.530273f, 0.509277f, -0.530273f, 0.504395f, -0.534424f,
-0.499512f, -0.538574f, 0.499512f, -0.546875f, 0.499512f, -0.556641f, 0.507568f, -0.563965f,
-0.515625f, -0.571289f, 0.531738f, -0.571289f, 0.644531f, -0.571289f, 0.658203f, -0.571289f,
-0.663086f, -0.567139f, 0.667969f, -0.562988f, 0.667969f, -0.555176f, 0.667969f, -0.544922f,
-0.659912f, -0.537598f, 0.651855f, -0.530273f, 0.635742f, -0.530273f, 0.611328f, -0.530273f,
-0.418457f, 0, 0.430664f, -0.059082f, 0.325684f, 0.0161133f, 0.223633f, 0.0161133f,
-0.158203f, 0.0161133f, 0.125f, -0.0131836f, 0.0917969f, -0.0424805f, 0.0917969f,
--0.0864258f, 0.0917969f, -0.15332f, 0.150391f, -0.201172f, 0.223145f, -0.26123f,
-0.340332f, -0.26123f, 0.396484f, -0.26123f, 0.470703f, -0.246094f, 0.484863f, -0.3125f,
-0.486328f, -0.319824f, 0.486328f, -0.327148f, 0.486328f, -0.355469f, 0.463867f, -0.372559f,
-0.433594f, -0.395996f, 0.377441f, -0.395996f, 0.330078f, -0.395996f, 0.231934f, -0.366699f,
-0.220703f, -0.363281f, 0.21582f, -0.363281f, 0.209473f, -0.363281f, 0.205078f, -0.367676f,
-0.200684f, -0.37207f, 0.200684f, -0.379395f, 0.200684f, -0.388672f, 0.207764f, -0.395996f,
-0.214844f, -0.40332f, 0.262695f, -0.415527f, 0.347168f, -0.4375f, 0.388184f, -0.4375f,
-0.458008f, -0.4375f, 0.493408f, -0.406738f, 0.528809f, -0.375977f, 0.528809f, -0.337402f,
-0.528809f, -0.324707f, 0.525879f, -0.3125f, 0.468262f, -0.0410156f, 0.523438f, -0.0410156f,
-0.537109f, -0.0410156f, 0.541992f, -0.0368652f, 0.546875f, -0.0327148f, 0.546875f,
--0.0249023f, 0.546875f, -0.0146484f, 0.538818f, -0.00732422f, 0.530762f, 0, 0.514648f,
-0, 0.461914f, -0.204102f, 0.406738f, -0.220215f, 0.335938f, -0.220215f, 0.237793f,
--0.220215f, 0.178711f, -0.174805f, 0.134277f, -0.140625f, 0.134277f, -0.0966797f,
-0.134277f, -0.0649414f, 0.157471f, -0.0449219f, 0.180664f, -0.0249023f, 0.229004f,
--0.0249023f, 0.282227f, -0.0249023f, 0.33252f, -0.0456543f, 0.382812f, -0.0664062f,
-0.442383f, -0.11377f, 0.275879f, -0.612793f, 0.218262f, -0.34082f, 0.312012f, -0.4375f,
-0.41748f, -0.4375f, 0.494141f, -0.4375f, 0.543701f, -0.388184f, 0.593262f, -0.338867f,
-0.593262f, -0.263184f, 0.593262f, -0.196289f, 0.555664f, -0.129395f, 0.518066f, -0.0625f,
-0.451416f, -0.0231934f, 0.384766f, 0.0161133f, 0.321777f, 0.0161133f, 0.213379f,
-0.0161133f, 0.162598f, -0.0805664f, 0.145508f, 0, 0.0493164f, 0, 0.0356445f, 0, 0.0307617f,
--0.00439453f, 0.0258789f, -0.00878906f, 0.0258789f, -0.0166016f, 0.0258789f, -0.0263672f,
-0.0339355f, -0.0336914f, 0.0419922f, -0.0410156f, 0.0581055f, -0.0410156f, 0.113281f,
--0.0410156f, 0.225586f, -0.571289f, 0.170898f, -0.571289f, 0.157227f, -0.571289f,
-0.152344f, -0.575684f, 0.147461f, -0.580078f, 0.147461f, -0.587891f, 0.147461f, -0.597656f,
-0.155518f, -0.605225f, 0.163574f, -0.612793f, 0.179688f, -0.612793f, 0.32959f, -0.0249023f,
-0.368164f, -0.0249023f, 0.406982f, -0.0427246f, 0.445801f, -0.0605469f, 0.477539f,
--0.0900879f, 0.509277f, -0.119629f, 0.530029f, -0.162842f, 0.550781f, -0.206055f,
-0.550781f, -0.254883f, 0.550781f, -0.313965f, 0.509521f, -0.35498f, 0.468262f, -0.395996f,
-0.407227f, -0.395996f, 0.35791f, -0.395996f, 0.301758f, -0.363525f, 0.245605f, -0.331055f,
-0.21582f, -0.2771f, 0.186035f, -0.223145f, 0.186035f, -0.167969f, 0.186035f, -0.107422f,
-0.227295f, -0.0661621f, 0.268555f, -0.0249023f, 0.32959f, -0.0249023f, 0.56543f,
--0.20166f, 0.147461f, -0.20166f, 0.145996f, -0.186523f, 0.145996f, -0.178711f, 0.145996f,
--0.111816f, 0.191406f, -0.0683594f, 0.236816f, -0.0249023f, 0.314453f, -0.0249023f,
-0.359863f, -0.0249023f, 0.413086f, -0.0397949f, 0.466309f, -0.0546875f, 0.504395f,
--0.0800781f, 0.515625f, -0.0874023f, 0.522461f, -0.0874023f, 0.528809f, -0.0874023f,
-0.533203f, -0.0827637f, 0.537598f, -0.078125f, 0.537598f, -0.0708008f, 0.537598f,
--0.0620117f, 0.529785f, -0.0541992f, 0.507324f, -0.0302734f, 0.439941f, -0.00708008f,
-0.372559f, 0.0161133f, 0.303223f, 0.0161133f, 0.213379f, 0.0161133f, 0.158936f, -0.0371094f,
-0.104492f, -0.090332f, 0.104492f, -0.172363f, 0.104492f, -0.226562f, 0.12793f, -0.274658f,
-0.151367f, -0.322754f, 0.189697f, -0.357666f, 0.228027f, -0.392578f, 0.278076f, -0.415039f,
-0.328125f, -0.4375f, 0.387207f, -0.4375f, 0.471191f, -0.4375f, 0.522217f, -0.388184f,
-0.573242f, -0.338867f, 0.573242f, -0.262207f, 0.573242f, -0.236816f, 0.56543f, -0.20166f,
-0.532227f, -0.243164f, 0.534668f, -0.310547f, 0.492188f, -0.353516f, 0.449219f, -0.395996f,
-0.376953f, -0.395996f, 0.306641f, -0.395996f, 0.245605f, -0.354492f, 0.18457f, -0.312988f,
-0.15625f, -0.243164f, 0.354004f, -0.381348f, 0.281738f, -0.0410156f, 0.461914f, -0.0410156f,
-0.475586f, -0.0410156f, 0.480469f, -0.0368652f, 0.485352f, -0.0327148f, 0.485352f,
--0.0249023f, 0.485352f, -0.0146484f, 0.477295f, -0.00732422f, 0.469238f, 0, 0.453125f,
-0, 0.132324f, 0, 0.118652f, 0, 0.11377f, -0.00439453f, 0.108887f, -0.00878906f, 0.108887f,
--0.0166016f, 0.108887f, -0.0263672f, 0.116943f, -0.0336914f, 0.125f, -0.0410156f,
-0.141113f, -0.0410156f, 0.240234f, -0.0410156f, 0.3125f, -0.381348f, 0.223633f, -0.381348f,
-0.209961f, -0.381348f, 0.205078f, -0.385742f, 0.200195f, -0.390137f, 0.200195f, -0.397949f,
-0.200195f, -0.407715f, 0.208252f, -0.415283f, 0.216309f, -0.422852f, 0.232422f, -0.422852f,
-0.321289f, -0.422852f, 0.334473f, -0.484863f, 0.345703f, -0.537109f, 0.395752f, -0.574951f,
-0.445801f, -0.612793f, 0.515625f, -0.612793f, 0.569824f, -0.612793f, 0.632324f, -0.603027f,
-0.65918f, -0.598633f, 0.66333f, -0.594238f, 0.66748f, -0.589844f, 0.66748f, -0.583496f,
-0.66748f, -0.573242f, 0.659912f, -0.565918f, 0.652344f, -0.558594f, 0.640625f, -0.558594f,
-0.637207f, -0.558594f, 0.628418f, -0.560059f, 0.557129f, -0.571289f, 0.507324f, -0.571289f,
-0.452148f, -0.571289f, 0.41748f, -0.544678f, 0.382812f, -0.518066f, 0.375977f, -0.484863f,
-0.362793f, -0.422852f, 0.554688f, -0.422852f, 0.568359f, -0.422852f, 0.572754f, -0.418945f,
-0.578125f, -0.414062f, 0.578125f, -0.40625f, 0.578125f, -0.396484f, 0.570068f, -0.388916f,
-0.562012f, -0.381348f, 0.545898f, -0.381348f, 0.511719f, -0.347656f, 0.527832f, -0.422852f,
-0.624023f, -0.422852f, 0.637695f, -0.422852f, 0.64209f, -0.418945f, 0.647949f, -0.414062f,
-0.647949f, -0.40625f, 0.647949f, -0.396484f, 0.639648f, -0.388916f, 0.631348f, -0.381348f,
-0.615234f, -0.381348f, 0.560547f, -0.381348f, 0.473145f, 0.0283203f, 0.464844f, 0.0678711f,
-0.441406f, 0.100098f, 0.424805f, 0.122559f, 0.391113f, 0.145996f, 0.357422f, 0.169434f,
-0.333984f, 0.178955f, 0.310547f, 0.188477f, 0.272461f, 0.188477f, 0.15625f, 0.188477f,
-0.142578f, 0.188477f, 0.137695f, 0.184082f, 0.132812f, 0.179688f, 0.132812f, 0.172363f,
-0.132812f, 0.162109f, 0.140869f, 0.154541f, 0.148926f, 0.146973f, 0.165039f, 0.146973f,
-0.282715f, 0.147461f, 0.317383f, 0.147461f, 0.350098f, 0.129883f, 0.382812f, 0.112305f,
-0.410645f, 0.0751953f, 0.42627f, 0.0546875f, 0.433105f, 0.0224609f, 0.459473f, -0.100586f,
-0.374023f, -0.0102539f, 0.268555f, -0.0102539f, 0.197754f, -0.0102539f, 0.150879f,
--0.0578613f, 0.104004f, -0.105469f, 0.104004f, -0.180176f, 0.104004f, -0.232422f,
-0.128418f, -0.280518f, 0.152832f, -0.328613f, 0.1875f, -0.361572f, 0.222168f, -0.394531f,
-0.266357f, -0.416016f, 0.310547f, -0.4375f, 0.361328f, -0.4375f, 0.465332f, -0.4375f,
-0.511719f, -0.347656f, 0.279785f, -0.0517578f, 0.321289f, -0.0517578f, 0.35791f,
--0.0688477f, 0.394531f, -0.0859375f, 0.423828f, -0.114014f, 0.453125f, -0.14209f,
-0.471436f, -0.181885f, 0.489746f, -0.22168f, 0.489746f, -0.263184f, 0.489746f, -0.320312f,
-0.45166f, -0.358154f, 0.413574f, -0.395996f, 0.355957f, -0.395996f, 0.274414f, -0.395996f,
-0.210205f, -0.332031f, 0.145996f, -0.268066f, 0.145996f, -0.1875f, 0.145996f, -0.12793f,
-0.184082f, -0.0898438f, 0.222168f, -0.0517578f, 0.279785f, -0.0517578f, 0.203125f,
--0.422852f, 0.194336f, -0.381348f, 0.258301f, -0.4375f, 0.312012f, -0.4375f, 0.341309f,
--0.4375f, 0.362305f, -0.42041f, 0.383301f, -0.40332f, 0.392578f, -0.369629f, 0.427246f,
--0.403809f, 0.458984f, -0.420654f, 0.490723f, -0.4375f, 0.519531f, -0.4375f, 0.555664f,
--0.4375f, 0.57959f, -0.412842f, 0.603516f, -0.388184f, 0.603516f, -0.349121f, 0.603516f,
--0.339355f, 0.600586f, -0.327637f, 0.540039f, -0.0410156f, 0.574219f, -0.0410156f,
-0.588379f, -0.0410156f, 0.593262f, -0.0368652f, 0.598145f, -0.0327148f, 0.598145f,
--0.0249023f, 0.598145f, -0.0146484f, 0.589844f, -0.00732422f, 0.581543f, 0, 0.56543f,
-0, 0.489746f, 0, 0.558594f, -0.32373f, 0.560547f, -0.332031f, 0.560547f, -0.340332f,
-0.560547f, -0.366211f, 0.546631f, -0.381104f, 0.532715f, -0.395996f, 0.512207f, -0.395996f,
-0.489746f, -0.395996f, 0.465332f, -0.382324f, 0.432617f, -0.363281f, 0.389648f, -0.312988f,
-0.331543f, -0.0410156f, 0.366211f, -0.0410156f, 0.379883f, -0.0410156f, 0.384766f,
--0.0368652f, 0.389648f, -0.0327148f, 0.389648f, -0.0249023f, 0.389648f, -0.0146484f,
-0.381592f, -0.00732422f, 0.373535f, 0, 0.357422f, 0, 0.281738f, 0, 0.350098f, -0.320801f,
-0.352051f, -0.330566f, 0.352051f, -0.339844f, 0.352051f, -0.364746f, 0.337646f, -0.380371f,
-0.323242f, -0.395996f, 0.304199f, -0.395996f, 0.282227f, -0.395996f, 0.258301f, -0.382812f,
-0.223633f, -0.362793f, 0.179688f, -0.312988f, 0.12207f, -0.0410156f, 0.15625f, -0.0410156f,
-0.17041f, -0.0410156f, 0.175293f, -0.0368652f, 0.180176f, -0.0327148f, 0.180176f,
--0.0249023f, 0.180176f, -0.0146484f, 0.171875f, -0.00732422f, 0.163574f, 0, 0.147461f,
-0, 0.0375977f, 0, 0.0239258f, 0, 0.019043f, -0.00439453f, 0.0141602f, -0.00878906f,
-0.0141602f, -0.0166016f, 0.0141602f, -0.0263672f, 0.0222168f, -0.0336914f, 0.0302734f,
--0.0410156f, 0.0463867f, -0.0410156f, 0.0805664f, -0.0410156f, 0.15332f, -0.381348f,
-0.118652f, -0.381348f, 0.10498f, -0.381348f, 0.100098f, -0.385742f, 0.0952148f, -0.390137f,
-0.0952148f, -0.397949f, 0.0952148f, -0.407715f, 0.103271f, -0.415283f, 0.111328f,
--0.422852f, 0.127441f, -0.422852f, 0.257324f, -0.422852f, 0.244141f, -0.36084f, 0.297852f,
--0.405273f, 0.335693f, -0.421387f, 0.373535f, -0.4375f, 0.41748f, -0.4375f, 0.478027f,
--0.4375f, 0.512451f, -0.405273f, 0.546875f, -0.373047f, 0.546875f, -0.321777f, 0.546875f,
--0.312012f, 0.544434f, -0.299316f, 0.489258f, -0.0410156f, 0.523926f, -0.0410156f,
-0.537598f, -0.0410156f, 0.54248f, -0.0368652f, 0.547363f, -0.0327148f, 0.547363f,
--0.0249023f, 0.547363f, -0.0146484f, 0.539307f, -0.00732422f, 0.53125f, 0, 0.515137f,
-0, 0.404785f, 0, 0.391113f, 0, 0.38623f, -0.00439453f, 0.381348f, -0.00878906f, 0.381348f,
--0.0166016f, 0.381348f, -0.0263672f, 0.389404f, -0.0336914f, 0.397461f, -0.0410156f,
-0.413574f, -0.0410156f, 0.448242f, -0.0410156f, 0.501465f, -0.29248f, 0.503906f,
--0.303711f, 0.503906f, -0.313965f, 0.503906f, -0.349609f, 0.479004f, -0.372803f,
-0.454102f, -0.395996f, 0.407715f, -0.395996f, 0.365234f, -0.395996f, 0.331787f, -0.378906f,
-0.29834f, -0.361816f, 0.230957f, -0.29834f, 0.17627f, -0.0410156f, 0.222656f, -0.0410156f,
-0.236328f, -0.0410156f, 0.241211f, -0.0368652f, 0.246094f, -0.0327148f, 0.246094f,
--0.0249023f, 0.246094f, -0.0146484f, 0.238037f, -0.00732422f, 0.22998f, 0, 0.213867f,
-0, 0.0800781f, 0, 0.0664062f, 0, 0.0615234f, -0.00439453f, 0.0566406f, -0.00878906f,
-0.0566406f, -0.0166016f, 0.0566406f, -0.0263672f, 0.0646973f, -0.0336914f, 0.0727539f,
--0.0410156f, 0.0888672f, -0.0410156f, 0.135254f, -0.0410156f, 0.20752f, -0.381348f,
-0.172852f, -0.381348f, 0.15918f, -0.381348f, 0.154297f, -0.385742f, 0.149414f, -0.390137f,
-0.149414f, -0.397949f, 0.149414f, -0.407715f, 0.157471f, -0.415283f, 0.165527f, -0.422852f,
-0.181641f, -0.422852f, 0.294922f, 0.0161133f, 0.214355f, 0.0161133f, 0.162598f, -0.0349121f,
-0.11084f, -0.0859375f, 0.11084f, -0.164551f, 0.11084f, -0.228516f, 0.149902f, -0.294678f,
-0.188965f, -0.36084f, 0.25708f, -0.39917f, 0.325195f, -0.4375f, 0.39502f, -0.4375f,
-0.475098f, -0.4375f, 0.526855f, -0.386719f, 0.578613f, -0.335938f, 0.578613f, -0.260254f,
-0.578613f, -0.193848f, 0.540771f, -0.128418f, 0.50293f, -0.0629883f, 0.434326f, -0.0234375f,
-0.365723f, 0.0161133f, 0.294922f, 0.0161133f, 0.304199f, -0.0249023f, 0.361816f,
--0.0249023f, 0.418213f, -0.057373f, 0.474609f, -0.0898438f, 0.505615f, -0.143555f,
-0.536621f, -0.197266f, 0.536621f, -0.251465f, 0.536621f, -0.312988f, 0.494141f, -0.354492f,
-0.45166f, -0.395996f, 0.385742f, -0.395996f, 0.338379f, -0.395996f, 0.297607f, -0.377197f,
-0.256836f, -0.358398f, 0.225342f, -0.328857f, 0.193848f, -0.299316f, 0.17334f, -0.258057f,
-0.152832f, -0.216797f, 0.152832f, -0.172852f, 0.152832f, -0.108887f, 0.195312f, -0.0668945f,
-0.237793f, -0.0249023f, 0.304199f, -0.0249023f, 0.235352f, -0.422852f, 0.219727f,
--0.348145f, 0.266602f, -0.393555f, 0.313232f, -0.415527f, 0.359863f, -0.4375f, 0.416504f,
--0.4375f, 0.498047f, -0.4375f, 0.546387f, -0.390381f, 0.594727f, -0.343262f, 0.594727f,
--0.268555f, 0.594727f, -0.169434f, 0.513428f, -0.0898438f, 0.432129f, -0.0102539f,
-0.325684f, -0.0102539f, 0.216309f, -0.0102539f, 0.166992f, -0.0996094f, 0.114258f,
-0.147461f, 0.213379f, 0.147461f, 0.224609f, 0.147461f, 0.228271f, 0.148926f, 0.231934f,
-0.150391f, 0.234619f, 0.154541f, 0.237305f, 0.158691f, 0.237305f, 0.163574f, 0.237305f,
-0.173828f, 0.229004f, 0.181152f, 0.220703f, 0.188477f, 0.20459f, 0.188477f, 0.00927734f,
-0.188477f, -0.00439453f, 0.188477f, -0.00927734f, 0.184082f, -0.0141602f, 0.179688f,
--0.0141602f, 0.172363f, -0.0141602f, 0.162109f, -0.00610352f, 0.154785f, 0.00195312f,
-0.147461f, 0.0180664f, 0.147461f, 0.0732422f, 0.147461f, 0.185547f, -0.381348f, 0.130371f,
--0.381348f, 0.116699f, -0.381348f, 0.111816f, -0.385742f, 0.106934f, -0.390137f,
-0.106934f, -0.397949f, 0.106934f, -0.407715f, 0.11499f, -0.415283f, 0.123047f, -0.422852f,
-0.13916f, -0.422852f, 0.333008f, -0.0517578f, 0.42041f, -0.0517578f, 0.486328f, -0.115723f,
-0.552246f, -0.179688f, 0.552246f, -0.26123f, 0.552246f, -0.318359f, 0.511963f, -0.357178f,
-0.47168f, -0.395996f, 0.40918f, -0.395996f, 0.321777f, -0.395996f, 0.255615f, -0.332031f,
-0.189453f, -0.268066f, 0.189453f, -0.189453f, 0.189453f, -0.130371f, 0.229736f, -0.0910645f,
-0.27002f, -0.0517578f, 0.333008f, -0.0517578f, 0.34082f, -0.422852f, 0.318848f, -0.319336f,
-0.416016f, -0.392578f, 0.459717f, -0.412842f, 0.503418f, -0.433105f, 0.536621f, -0.433105f,
-0.569824f, -0.433105f, 0.596436f, -0.410645f, 0.623047f, -0.388184f, 0.623047f, -0.375488f,
-0.623047f, -0.365234f, 0.615234f, -0.357422f, 0.607422f, -0.349609f, 0.59668f, -0.349609f,
-0.591797f, -0.349609f, 0.588867f, -0.351318f, 0.585938f, -0.353027f, 0.578613f, -0.362305f,
-0.56543f, -0.379395f, 0.553955f, -0.385742f, 0.54248f, -0.39209f, 0.530762f, -0.39209f,
-0.503418f, -0.39209f, 0.461182f, -0.370605f, 0.418945f, -0.349121f, 0.307617f, -0.265625f,
-0.259766f, -0.0410156f, 0.441406f, -0.0410156f, 0.455566f, -0.0410156f, 0.460449f,
--0.0368652f, 0.465332f, -0.0327148f, 0.465332f, -0.0249023f, 0.465332f, -0.0146484f,
-0.457031f, -0.00732422f, 0.44873f, 0, 0.432617f, 0, 0.11084f, 0, 0.097168f, 0, 0.0922852f,
--0.00415039f, 0.0874023f, -0.00830078f, 0.0874023f, -0.015625f, 0.0874023f, -0.0253906f,
-0.0952148f, -0.0324707f, 0.103027f, -0.0395508f, 0.119141f, -0.0395508f, 0.218262f,
--0.0395508f, 0.291016f, -0.381348f, 0.215332f, -0.381348f, 0.20166f, -0.381348f,
-0.196777f, -0.385742f, 0.191895f, -0.390137f, 0.191895f, -0.397461f, 0.191895f, -0.407715f,
-0.199951f, -0.415283f, 0.208008f, -0.422852f, 0.224121f, -0.422852f, 0.52002f, -0.395996f,
-0.522949f, -0.410156f, 0.530273f, -0.416504f, 0.537598f, -0.422852f, 0.546387f, -0.422852f,
-0.553711f, -0.422852f, 0.55835f, -0.418213f, 0.562988f, -0.413574f, 0.562988f, -0.407715f,
-0.562988f, -0.40332f, 0.561035f, -0.39502f, 0.546387f, -0.324707f, 0.542969f, -0.310059f,
-0.535889f, -0.303711f, 0.528809f, -0.297363f, 0.519531f, -0.297363f, 0.512695f, -0.297363f,
-0.508057f, -0.301758f, 0.503418f, -0.306152f, 0.503418f, -0.312012f, 0.503906f, -0.320312f,
-0.504395f, -0.324219f, 0.504395f, -0.327637f, 0.504395f, -0.354004f, 0.480957f, -0.370605f,
-0.446289f, -0.395996f, 0.383789f, -0.395996f, 0.308594f, -0.395996f, 0.26416f, -0.36377f,
-0.230957f, -0.339844f, 0.230957f, -0.312988f, 0.230957f, -0.286621f, 0.259766f, -0.27002f,
-0.280762f, -0.258301f, 0.348633f, -0.250732f, 0.416504f, -0.243164f, 0.445801f, -0.233398f,
-0.486816f, -0.220215f, 0.506836f, -0.195312f, 0.526855f, -0.17041f, 0.526855f, -0.13916f,
-0.526855f, -0.103027f, 0.500488f, -0.0668945f, 0.474121f, -0.0307617f, 0.419922f,
--0.00732422f, 0.365723f, 0.0161133f, 0.297852f, 0.0161133f, 0.249512f, 0.0161133f,
-0.212402f, 0.00366211f, 0.175293f, -0.00878906f, 0.149414f, -0.0332031f, 0.145508f,
--0.0131836f, 0.139648f, -0.00732422f, 0.131348f, 0, 0.121582f, 0, 0.114746f, 0, 0.110107f,
--0.00439453f, 0.105469f, -0.00878906f, 0.105469f, -0.0151367f, 0.105469f, -0.0195312f,
-0.106934f, -0.0273438f, 0.125f, -0.111816f, 0.12793f, -0.126465f, 0.135254f, -0.132812f,
-0.142578f, -0.13916f, 0.151855f, -0.13916f, 0.158691f, -0.13916f, 0.16333f, -0.134521f,
-0.167969f, -0.129883f, 0.167969f, -0.123535f, 0.167969f, -0.119629f, 0.166504f, -0.112305f,
-0.165039f, -0.10498f, 0.165039f, -0.101562f, 0.165039f, -0.0737305f, 0.193848f, -0.0527344f,
-0.231934f, -0.0249023f, 0.305176f, -0.0249023f, 0.392578f, -0.0249023f, 0.438477f,
--0.0595703f, 0.484375f, -0.0942383f, 0.484375f, -0.128418f, 0.484375f, -0.146973f,
-0.470947f, -0.164795f, 0.45752f, -0.182617f, 0.430176f, -0.193115f, 0.402832f, -0.203613f,
-0.340576f, -0.210205f, 0.27832f, -0.216797f, 0.249756f, -0.226807f, 0.221191f, -0.236816f,
-0.205078f, -0.257324f, 0.188965f, -0.277832f, 0.188965f, -0.304199f, 0.188965f, -0.334961f,
-0.209961f, -0.364502f, 0.230957f, -0.394043f, 0.280029f, -0.415771f, 0.329102f, -0.4375f,
-0.390137f, -0.4375f, 0.432617f, -0.4375f, 0.465088f, -0.427246f, 0.497559f, -0.416992f,
-0.52002f, -0.395996f, 0.44043f, 0, 0.453125f, -0.0600586f, 0.353027f, 0.0161133f,
-0.253906f, 0.0161133f, 0.205078f, 0.0161133f, 0.176514f, -0.0119629f, 0.147949f,
--0.0400391f, 0.147949f, -0.0834961f, 0.147949f, -0.0991211f, 0.151855f, -0.116699f,
-0.208008f, -0.381348f, 0.152832f, -0.381348f, 0.13916f, -0.381348f, 0.134277f, -0.385742f,
-0.129395f, -0.390137f, 0.129395f, -0.397949f, 0.129395f, -0.407715f, 0.137451f, -0.415283f,
-0.145508f, -0.422852f, 0.161621f, -0.422852f, 0.257812f, -0.422852f, 0.192871f, -0.116699f,
-0.190918f, -0.106445f, 0.190918f, -0.0957031f, 0.190918f, -0.0634766f, 0.209961f,
--0.0441895f, 0.229004f, -0.0249023f, 0.261719f, -0.0249023f, 0.362793f, -0.0249023f,
-0.465332f, -0.116699f, 0.521484f, -0.381348f, 0.445801f, -0.381348f, 0.432129f, -0.381348f,
-0.427246f, -0.385742f, 0.422363f, -0.390137f, 0.422363f, -0.397949f, 0.422363f, -0.407715f,
-0.43042f, -0.415283f, 0.438477f, -0.422852f, 0.45459f, -0.422852f, 0.571289f, -0.422852f,
-0.490234f, -0.0410156f, 0.524902f, -0.0410156f, 0.538574f, -0.0410156f, 0.543457f,
--0.0368652f, 0.54834f, -0.0327148f, 0.54834f, -0.0249023f, 0.54834f, -0.0146484f,
-0.540283f, -0.00732422f, 0.532227f, 0, 0.516113f, 0, 0.278809f, 0, 0.169922f, -0.381348f,
-0.157715f, -0.381348f, 0.144043f, -0.381348f, 0.138916f, -0.385742f, 0.133789f, -0.390137f,
-0.133789f, -0.397949f, 0.133789f, -0.404297f, 0.137939f, -0.410645f, 0.14209f, -0.416992f,
-0.148193f, -0.419922f, 0.154297f, -0.422852f, 0.166504f, -0.422852f, 0.27832f, -0.422852f,
-0.289062f, -0.422852f, 0.292969f, -0.421143f, 0.296875f, -0.419434f, 0.299316f, -0.415527f,
-0.301758f, -0.411621f, 0.301758f, -0.40625f, 0.301758f, -0.396484f, 0.293701f, -0.388916f,
-0.285645f, -0.381348f, 0.269531f, -0.381348f, 0.214844f, -0.381348f, 0.310059f, -0.0449219f,
-0.546875f, -0.381348f, 0.492188f, -0.381348f, 0.478516f, -0.381348f, 0.473389f, -0.385742f,
-0.468262f, -0.390137f, 0.468262f, -0.397949f, 0.468262f, -0.407715f, 0.476318f, -0.415283f,
-0.484375f, -0.422852f, 0.500977f, -0.422852f, 0.612793f, -0.422852f, 0.626465f, -0.422852f,
-0.630371f, -0.418945f, 0.63623f, -0.414062f, 0.63623f, -0.40625f, 0.63623f, -0.399414f,
-0.631592f, -0.392822f, 0.626953f, -0.38623f, 0.620117f, -0.383301f, 0.614746f, -0.381348f,
-0.591309f, -0.381348f, 0.219238f, 0.147461f, 0.283203f, 0.147461f, 0.293945f, 0.147461f,
-0.297852f, 0.148926f, 0.301758f, 0.150391f, 0.304199f, 0.154541f, 0.306641f, 0.158691f,
-0.306641f, 0.163574f, 0.306641f, 0.173828f, 0.298584f, 0.181152f, 0.290527f, 0.188477f,
-0.274414f, 0.188477f, 0.0380859f, 0.188477f, 0.0244141f, 0.188477f, 0.0195312f, 0.184082f,
-0.0146484f, 0.179688f, 0.0146484f, 0.172363f, 0.0146484f, 0.162109f, 0.0227051f,
-0.154785f, 0.0307617f, 0.147461f, 0.046875f, 0.147461f, 0.175781f, 0.147461f
-};
-
-const unsigned char CourierNewkItalicVerbs[] = {
-6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,
-1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 5, 6,
-0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1,
-1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1,
-2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5,
-6, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6
-};
-
-const unsigned CourierNewkItalicCharCodes[] = {
-32, 65,
-72, 84, 87, 89, 97, 98, 101, 102, 103, 109, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed CourierNewkItalicWidths[] = {
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
-};
-
-const int CourierNewkItalicCharCodesCount = (int) SK_ARRAY_COUNT(CourierNewkItalicCharCodes);
-
-const SkPaint::FontMetrics CourierNewkItalicMetrics = {
-0x00000003, -1.00049f, -0.83252f, 0.300293f, 0.273926f, 0, 0.923828f, 0, -0.123535f,
-0.800293f, 0.437988f, 0, 0.0410156f, 0.23291f
-};
-
-const SkScalar CourierNewkBoldItalicPoints[] = {
-0.456543f, -0.161133f, 0.213379f, -0.161133f, 0.175781f, -0.100098f, 0.200195f, -0.100098f,
-0.233887f, -0.100098f, 0.245605f, -0.0898438f, 0.257324f, -0.0795898f, 0.257324f,
--0.0605469f, 0.257324f, -0.0302734f, 0.228516f, -0.0102539f, 0.213379f, 0, 0.179199f,
-0, 0.0439453f, 0, 0.0107422f, 0, -0.0012207f, -0.010498f, -0.0131836f, -0.0209961f,
--0.0131836f, -0.0395508f, -0.0131836f, -0.0649414f, 0.00708008f, -0.0830078f, 0.0273438f,
--0.101074f, 0.0678711f, -0.100098f, 0.308594f, -0.491699f, 0.242676f, -0.491699f,
-0.209473f, -0.491699f, 0.19751f, -0.502197f, 0.185547f, -0.512695f, 0.185547f, -0.531738f,
-0.185547f, -0.561523f, 0.213867f, -0.581543f, 0.229492f, -0.592285f, 0.26416f, -0.592285f,
-0.480469f, -0.592285f, 0.575195f, -0.100098f, 0.609375f, -0.101074f, 0.62207f, -0.090332f,
-0.634766f, -0.0795898f, 0.634766f, -0.0605469f, 0.634766f, -0.0302734f, 0.605469f,
--0.0102539f, 0.59082f, 0, 0.556152f, 0, 0.421387f, 0, 0.388184f, 0, 0.376221f, -0.010498f,
-0.364258f, -0.0209961f, 0.364258f, -0.0395508f, 0.364258f, -0.0693359f, 0.392578f,
--0.0893555f, 0.408203f, -0.100098f, 0.442871f, -0.100098f, 0.467285f, -0.100098f,
-0.436035f, -0.26123f, 0.397461f, -0.459473f, 0.274414f, -0.26123f, 0.461426f, -0.245117f,
-0.247559f, -0.245117f, 0.216797f, -0.100098f, 0.232422f, -0.100098f, 0.266113f, -0.100098f,
-0.277832f, -0.0898438f, 0.289551f, -0.0795898f, 0.289551f, -0.0605469f, 0.289551f,
--0.0302734f, 0.260742f, -0.0102539f, 0.245605f, 0, 0.211426f, 0, 0.0883789f, 0, 0.0551758f,
-0, 0.0432129f, -0.010498f, 0.03125f, -0.0209961f, 0.03125f, -0.0395508f, 0.03125f,
--0.0708008f, 0.0615234f, -0.0908203f, 0.0761719f, -0.100586f, 0.116699f, -0.100098f,
-0.199707f, -0.491699f, 0.177246f, -0.493652f, 0.166748f, -0.50415f, 0.15625f, -0.514648f,
-0.15625f, -0.531738f, 0.15625f, -0.561523f, 0.185059f, -0.581543f, 0.200195f, -0.592285f,
-0.234863f, -0.592285f, 0.336914f, -0.591797f, 0.370605f, -0.591797f, 0.382568f, -0.581543f,
-0.394531f, -0.571289f, 0.394531f, -0.552246f, 0.394531f, -0.521973f, 0.365234f, -0.501953f,
-0.350098f, -0.491699f, 0.315918f, -0.491699f, 0.299805f, -0.491699f, 0.269043f, -0.345215f,
-0.48291f, -0.345215f, 0.51416f, -0.491699f, 0.498047f, -0.491699f, 0.464844f, -0.491699f,
-0.452881f, -0.502197f, 0.440918f, -0.512695f, 0.440918f, -0.531738f, 0.440918f, -0.561523f,
-0.469238f, -0.581543f, 0.484863f, -0.592285f, 0.519531f, -0.592285f, 0.621582f, -0.591797f,
-0.655273f, -0.591797f, 0.666992f, -0.581543f, 0.678711f, -0.571289f, 0.678711f, -0.552246f,
-0.678711f, -0.529785f, 0.661377f, -0.512207f, 0.644043f, -0.494629f, 0.614258f, -0.491699f,
-0.530762f, -0.100098f, 0.570801f, -0.100098f, 0.581055f, -0.0917969f, 0.594727f,
--0.0800781f, 0.594727f, -0.0605469f, 0.594727f, -0.0302734f, 0.565918f, -0.0102539f,
-0.550781f, 0, 0.516602f, 0, 0.393555f, 0, 0.360352f, 0, 0.348389f, -0.010498f, 0.336426f,
--0.0209961f, 0.336426f, -0.0395508f, 0.336426f, -0.0693359f, 0.364746f, -0.0893555f,
-0.380371f, -0.100098f, 0.415039f, -0.100098f, 0.430664f, -0.100098f, 0.453125f, -0.491699f,
-0.370117f, -0.100098f, 0.4375f, -0.100098f, 0.470703f, -0.100098f, 0.482666f, -0.0895996f,
-0.494629f, -0.0791016f, 0.494629f, -0.0605469f, 0.494629f, -0.0307617f, 0.466309f,
--0.0107422f, 0.450684f, 0, 0.416016f, 0, 0.181152f, 0, 0.147949f, 0, 0.135986f, -0.010498f,
-0.124023f, -0.0209961f, 0.124023f, -0.0395508f, 0.124023f, -0.0698242f, 0.152344f,
--0.0893555f, 0.167969f, -0.100098f, 0.202637f, -0.100098f, 0.27002f, -0.100098f,
-0.353027f, -0.491699f, 0.244629f, -0.491699f, 0.224609f, -0.396973f, 0.216797f, -0.36084f,
-0.199707f, -0.345459f, 0.182617f, -0.330078f, 0.159668f, -0.330078f, 0.142578f, -0.330078f,
-0.131348f, -0.341064f, 0.120117f, -0.352051f, 0.120117f, -0.366699f, 0.120117f, -0.376953f,
-0.124512f, -0.396973f, 0.166016f, -0.591797f, 0.684082f, -0.591797f, 0.642578f, -0.396973f,
-0.635254f, -0.36084f, 0.61792f, -0.345459f, 0.600586f, -0.330078f, 0.578125f, -0.330078f,
-0.561035f, -0.330078f, 0.549805f, -0.341064f, 0.538574f, -0.352051f, 0.538574f, -0.366699f,
-0.538574f, -0.376953f, 0.54248f, -0.396973f, 0.562988f, -0.491699f, 0.36084f, -0.28418f,
-0.20752f, 0, 0.0952148f, 0, 0.140137f, -0.491699f, 0.121094f, -0.494141f, 0.111816f,
--0.503906f, 0.102539f, -0.513672f, 0.102539f, -0.52832f, 0.102539f, -0.560547f, 0.131348f,
--0.581055f, 0.146484f, -0.592285f, 0.181641f, -0.592285f, 0.31543f, -0.591797f, 0.349121f,
--0.591797f, 0.36084f, -0.581543f, 0.372559f, -0.571289f, 0.372559f, -0.552246f, 0.372559f,
--0.522461f, 0.344238f, -0.502441f, 0.329102f, -0.491699f, 0.293945f, -0.491699f,
-0.241699f, -0.491699f, 0.215332f, -0.211914f, 0.343262f, -0.444824f, 0.447754f, -0.444824f,
-0.476074f, -0.211914f, 0.568848f, -0.491699f, 0.516602f, -0.491699f, 0.48291f, -0.491699f,
-0.470947f, -0.502197f, 0.458984f, -0.512695f, 0.458984f, -0.531738f, 0.458984f, -0.561523f,
-0.487793f, -0.581543f, 0.50293f, -0.592285f, 0.537598f, -0.592285f, 0.670898f, -0.591797f,
-0.704102f, -0.591797f, 0.716064f, -0.581543f, 0.728027f, -0.571289f, 0.728027f, -0.552246f,
-0.728027f, -0.53125f, 0.712158f, -0.513672f, 0.696289f, -0.496094f, 0.668945f, -0.491699f,
-0.506836f, 0, 0.395996f, 0, 0.40332f, -0.248535f, 0.37207f, -0.100098f, 0.438965f,
--0.100098f, 0.472656f, -0.100098f, 0.484619f, -0.0898438f, 0.496582f, -0.0795898f,
-0.496582f, -0.0605469f, 0.496582f, -0.0302734f, 0.467285f, -0.0102539f, 0.452148f,
-0, 0.417969f, 0, 0.183105f, 0, 0.149902f, 0, 0.137939f, -0.010498f, 0.125977f, -0.0209961f,
-0.125977f, -0.0395508f, 0.125977f, -0.0698242f, 0.154297f, -0.0893555f, 0.169922f,
--0.100098f, 0.20459f, -0.100098f, 0.271973f, -0.100098f, 0.303223f, -0.248535f, 0.189453f,
--0.491699f, 0.158691f, -0.491699f, 0.146729f, -0.502441f, 0.134766f, -0.513184f,
-0.134766f, -0.531738f, 0.134766f, -0.561523f, 0.163574f, -0.581543f, 0.178711f, -0.592285f,
-0.213379f, -0.592285f, 0.304688f, -0.591797f, 0.338379f, -0.591797f, 0.350098f, -0.581543f,
-0.361816f, -0.571289f, 0.361816f, -0.552246f, 0.361816f, -0.53418f, 0.349854f, -0.518311f,
-0.337891f, -0.502441f, 0.310547f, -0.491699f, 0.375488f, -0.352051f, 0.498047f, -0.491699f,
-0.467285f, -0.504883f, 0.467285f, -0.531738f, 0.467285f, -0.561523f, 0.495605f, -0.581543f,
-0.510742f, -0.591797f, 0.545898f, -0.591797f, 0.639648f, -0.591797f, 0.67334f, -0.591797f,
-0.685059f, -0.581543f, 0.696777f, -0.571289f, 0.696777f, -0.552246f, 0.696777f, -0.522949f,
-0.669434f, -0.50293f, 0.65332f, -0.491699f, 0.619141f, -0.491699f, 0.389648f, 0,
-0.394531f, -0.0234375f, 0.311035f, 0.0161133f, 0.217773f, 0.0161133f, 0.148438f,
-0.0161133f, 0.107422f, -0.019043f, 0.0664062f, -0.0541992f, 0.0664062f, -0.0991211f,
-0.0664062f, -0.135742f, 0.0947266f, -0.17627f, 0.132812f, -0.230957f, 0.199463f,
--0.26123f, 0.266113f, -0.291504f, 0.347168f, -0.291504f, 0.39209f, -0.291504f, 0.449707f,
--0.281738f, 0.45459f, -0.305664f, 0.455566f, -0.310547f, 0.455566f, -0.31543f, 0.455566f,
--0.333496f, 0.441406f, -0.343262f, 0.422852f, -0.356445f, 0.372559f, -0.356445f,
-0.32666f, -0.356445f, 0.253906f, -0.338867f, 0.226562f, -0.33252f, 0.210938f, -0.33252f,
-0.194824f, -0.33252f, 0.184082f, -0.343262f, 0.17334f, -0.354004f, 0.17334f, -0.371582f,
-0.17334f, -0.395996f, 0.188965f, -0.411865f, 0.20459f, -0.427734f, 0.274658f, -0.442139f,
-0.344727f, -0.456543f, 0.39502f, -0.456543f, 0.477051f, -0.456543f, 0.517822f, -0.422607f,
-0.558594f, -0.388672f, 0.558594f, -0.339844f, 0.558594f, -0.324219f, 0.555176f, -0.306152f,
-0.51123f, -0.100098f, 0.52832f, -0.100098f, 0.562012f, -0.100098f, 0.57373f, -0.0898438f,
-0.585449f, -0.0795898f, 0.585449f, -0.0605469f, 0.585449f, -0.0302734f, 0.556641f,
--0.0102539f, 0.541504f, 0, 0.507324f, 0, 0.427734f, -0.179199f, 0.370605f, -0.190918f,
-0.319336f, -0.190918f, 0.25293f, -0.190918f, 0.199219f, -0.155273f, 0.168457f, -0.135254f,
-0.168457f, -0.117188f, 0.168457f, -0.102539f, 0.189697f, -0.0930176f, 0.210938f,
--0.0834961f, 0.244141f, -0.0834961f, 0.278809f, -0.0834961f, 0.327881f, -0.0974121f,
-0.376953f, -0.111328f, 0.418457f, -0.13623f, 0.308594f, -0.633301f, 0.26123f, -0.408691f,
-0.344238f, -0.456543f, 0.422852f, -0.456543f, 0.511719f, -0.456543f, 0.567871f, -0.401611f,
-0.624023f, -0.34668f, 0.624023f, -0.265625f, 0.624023f, -0.195801f, 0.58667f, -0.12915f,
-0.549316f, -0.0625f, 0.475342f, -0.0231934f, 0.401367f, 0.0161133f, 0.319336f, 0.0161133f,
-0.239258f, 0.0161133f, 0.179199f, -0.0244141f, 0.173828f, 0, 0.0566406f, 0, 0.0234375f,
-0, 0.0114746f, -0.010498f, -0.000488281f, -0.0209961f, -0.000488281f, -0.0395508f,
--0.000488281f, -0.0693359f, 0.027832f, -0.0893555f, 0.043457f, -0.100098f, 0.078125f,
--0.100098f, 0.0952148f, -0.100098f, 0.187012f, -0.533203f, 0.169922f, -0.533203f,
-0.136719f, -0.533203f, 0.124756f, -0.543701f, 0.112793f, -0.554199f, 0.112793f, -0.572754f,
-0.112793f, -0.602539f, 0.141113f, -0.622559f, 0.156738f, -0.633301f, 0.191406f, -0.633301f,
-0.34082f, -0.0839844f, 0.422852f, -0.0839844f, 0.471924f, -0.129395f, 0.520996f,
--0.174805f, 0.520996f, -0.242676f, 0.520996f, -0.291016f, 0.487305f, -0.32373f, 0.453613f,
--0.356445f, 0.399414f, -0.356445f, 0.327148f, -0.356445f, 0.271484f, -0.302246f,
-0.21582f, -0.248047f, 0.21582f, -0.181641f, 0.21582f, -0.138672f, 0.24707f, -0.111328f,
-0.27832f, -0.0839844f, 0.34082f, -0.0839844f, 0.587891f, -0.170898f, 0.177246f, -0.170898f,
-0.184082f, -0.132324f, 0.218262f, -0.108154f, 0.252441f, -0.0839844f, 0.320801f,
--0.0839844f, 0.377441f, -0.0839844f, 0.474609f, -0.10791f, 0.515137f, -0.117676f,
-0.530273f, -0.117676f, 0.546387f, -0.117676f, 0.557129f, -0.107178f, 0.567871f, -0.0966797f,
-0.567871f, -0.0795898f, 0.567871f, -0.0546875f, 0.545654f, -0.0354004f, 0.523438f,
--0.0161133f, 0.440918f, 0, 0.358398f, 0.0161133f, 0.291992f, 0.0161133f, 0.1875f,
-0.0161133f, 0.130615f, -0.036377f, 0.0737305f, -0.0888672f, 0.0737305f, -0.17041f,
-0.0737305f, -0.238281f, 0.11499f, -0.306641f, 0.15625f, -0.375f, 0.232666f, -0.415771f,
-0.309082f, -0.456543f, 0.389648f, -0.456543f, 0.484375f, -0.456543f, 0.543213f, -0.404297f,
-0.602051f, -0.352051f, 0.602051f, -0.258301f, 0.602051f, -0.238281f, 0.597168f, -0.213379f,
-0.498047f, -0.270996f, 0.484863f, -0.312012f, 0.452148f, -0.334229f, 0.419434f, -0.356445f,
-0.368164f, -0.356445f, 0.316895f, -0.356445f, 0.275391f, -0.335205f, 0.233887f, -0.313965f,
-0.20166f, -0.270996f, 0.37207f, -0.343262f, 0.320801f, -0.100098f, 0.462891f, -0.100098f,
-0.496582f, -0.100098f, 0.508301f, -0.0898438f, 0.52002f, -0.0795898f, 0.52002f, -0.0605469f,
-0.52002f, -0.0302734f, 0.491211f, -0.0102539f, 0.476074f, 0, 0.441895f, 0, 0.13916f,
-0, 0.105957f, 0, 0.0939941f, -0.010498f, 0.0820312f, -0.0209961f, 0.0820312f, -0.0395508f,
-0.0820312f, -0.0698242f, 0.110352f, -0.0893555f, 0.125977f, -0.100098f, 0.160645f,
--0.100098f, 0.220703f, -0.100098f, 0.271973f, -0.343262f, 0.224121f, -0.343262f,
-0.190918f, -0.343262f, 0.178711f, -0.35376f, 0.166504f, -0.364258f, 0.166504f, -0.382812f,
-0.166504f, -0.412109f, 0.194336f, -0.432129f, 0.209961f, -0.443359f, 0.245117f, -0.443359f,
-0.293457f, -0.443359f, 0.301758f, -0.481445f, 0.31543f, -0.547852f, 0.373779f, -0.590576f,
-0.432129f, -0.633301f, 0.524902f, -0.633301f, 0.561035f, -0.633301f, 0.61377f, -0.626465f,
-0.666504f, -0.619629f, 0.680176f, -0.608398f, 0.693848f, -0.597168f, 0.693848f, -0.57959f,
-0.693848f, -0.555176f, 0.675537f, -0.536377f, 0.657227f, -0.517578f, 0.634277f, -0.517578f,
-0.625488f, -0.517578f, 0.606934f, -0.520996f, 0.547363f, -0.533203f, 0.499512f, -0.533203f,
-0.450195f, -0.533203f, 0.428223f, -0.518311f, 0.40625f, -0.503418f, 0.401855f, -0.481445f,
-0.393555f, -0.443359f, 0.547852f, -0.443359f, 0.581055f, -0.443359f, 0.593018f, -0.432861f,
-0.60498f, -0.422363f, 0.60498f, -0.403809f, 0.60498f, -0.374023f, 0.57666f, -0.354004f,
-0.561523f, -0.343262f, 0.526367f, -0.343262f, 0.486328f, -0.423828f, 0.504395f, -0.443359f,
-0.621582f, -0.443359f, 0.655273f, -0.443359f, 0.667236f, -0.432861f, 0.679199f, -0.422363f,
-0.679199f, -0.40332f, 0.679199f, -0.374512f, 0.651367f, -0.354492f, 0.635742f, -0.343262f,
-0.600586f, -0.343262f, 0.583496f, -0.343262f, 0.505859f, 0.0209961f, 0.494629f, 0.0727539f,
-0.4646f, 0.112061f, 0.43457f, 0.151367f, 0.381836f, 0.180176f, 0.329102f, 0.208984f,
-0.271973f, 0.208984f, 0.158691f, 0.208984f, 0.125488f, 0.208984f, 0.113525f, 0.19873f,
-0.101562f, 0.188477f, 0.101562f, 0.169434f, 0.101562f, 0.13916f, 0.130371f, 0.119141f,
-0.145508f, 0.108887f, 0.179688f, 0.108887f, 0.290039f, 0.108887f, 0.335938f, 0.108887f,
-0.366699f, 0.0842285f, 0.397461f, 0.0595703f, 0.405762f, 0.0209961f, 0.416016f, -0.027832f,
-0.378418f, -0.00634766f, 0.341553f, 0.00439453f, 0.304688f, 0.0151367f, 0.268555f,
-0.0151367f, 0.180664f, 0.0151367f, 0.127197f, -0.0368652f, 0.0737305f, -0.0888672f,
-0.0737305f, -0.167969f, 0.0737305f, -0.23877f, 0.112549f, -0.307129f, 0.151367f,
--0.375488f, 0.222412f, -0.416748f, 0.293457f, -0.458008f, 0.370117f, -0.458008f,
-0.401855f, -0.458008f, 0.42749f, -0.450439f, 0.453125f, -0.442871f, 0.486328f, -0.423828f,
-0.288086f, -0.0854492f, 0.355469f, -0.0854492f, 0.407715f, -0.135986f, 0.459961f,
--0.186523f, 0.459961f, -0.25f, 0.459961f, -0.29541f, 0.428223f, -0.32666f, 0.396484f,
--0.35791f, 0.348633f, -0.35791f, 0.28125f, -0.35791f, 0.229004f, -0.306885f, 0.176758f,
--0.255859f, 0.176758f, -0.194336f, 0.176758f, -0.147461f, 0.208252f, -0.116455f,
-0.239746f, -0.0854492f, 0.288086f, -0.0854492f, 0.231934f, -0.443359f, 0.228516f,
--0.413574f, 0.260254f, -0.437988f, 0.282471f, -0.447266f, 0.304688f, -0.456543f,
-0.328125f, -0.456543f, 0.375977f, -0.456543f, 0.408691f, -0.414062f, 0.438965f, -0.435547f,
-0.468018f, -0.446045f, 0.49707f, -0.456543f, 0.525391f, -0.456543f, 0.57666f, -0.456543f,
-0.606201f, -0.428223f, 0.635742f, -0.399902f, 0.635742f, -0.353516f, 0.635742f, -0.339844f,
-0.632324f, -0.324219f, 0.584961f, -0.100098f, 0.61377f, -0.100098f, 0.625488f, -0.0895996f,
-0.637207f, -0.0791016f, 0.637207f, -0.0605469f, 0.637207f, -0.0302734f, 0.608398f,
--0.0102539f, 0.593262f, 0, 0.558594f, 0, 0.463379f, 0, 0.530762f, -0.315918f, 0.532715f,
--0.32666f, 0.532715f, -0.334961f, 0.532715f, -0.344727f, 0.526123f, -0.350586f, 0.519531f,
--0.356445f, 0.505859f, -0.356445f, 0.489258f, -0.356445f, 0.474121f, -0.347656f,
-0.452637f, -0.335938f, 0.419434f, -0.301758f, 0.376465f, -0.100098f, 0.405273f, -0.100098f,
-0.416992f, -0.0895996f, 0.428711f, -0.0791016f, 0.428711f, -0.0605469f, 0.428711f,
--0.0302734f, 0.399902f, -0.0102539f, 0.384766f, 0, 0.350098f, 0, 0.254883f, 0, 0.322266f,
--0.315918f, 0.324219f, -0.326172f, 0.324219f, -0.334473f, 0.324219f, -0.344238f,
-0.317383f, -0.350342f, 0.310547f, -0.356445f, 0.297363f, -0.356445f, 0.279297f, -0.356445f,
-0.262695f, -0.347168f, 0.240723f, -0.334961f, 0.209473f, -0.301758f, 0.166504f, -0.100098f,
-0.195312f, -0.100098f, 0.207031f, -0.0895996f, 0.21875f, -0.0791016f, 0.21875f, -0.0605469f,
-0.21875f, -0.0302734f, 0.189941f, -0.0102539f, 0.174805f, 0, 0.140137f, 0, 0.0498047f,
-0, 0.0166016f, 0, 0.00463867f, -0.010498f, -0.00732422f, -0.0209961f, -0.00732422f,
--0.0395508f, -0.00732422f, -0.0639648f, 0.0124512f, -0.0822754f, 0.0322266f, -0.100586f,
-0.0664062f, -0.100098f, 0.118164f, -0.343262f, 0.0888672f, -0.343262f, 0.0771484f,
--0.354004f, 0.0654297f, -0.364746f, 0.0654297f, -0.382812f, 0.0654297f, -0.412109f,
-0.0932617f, -0.432129f, 0.108887f, -0.443359f, 0.144043f, -0.443359f, 0.29248f, -0.443359f,
-0.288086f, -0.409668f, 0.321777f, -0.435059f, 0.352051f, -0.445801f, 0.382324f, -0.456543f,
-0.421875f, -0.456543f, 0.498535f, -0.456543f, 0.538086f, -0.421631f, 0.577637f, -0.386719f,
-0.577637f, -0.330566f, 0.577637f, -0.310059f, 0.572754f, -0.286133f, 0.533203f, -0.100098f,
-0.562012f, -0.100098f, 0.57373f, -0.0895996f, 0.585449f, -0.0791016f, 0.585449f,
--0.0605469f, 0.585449f, -0.0302734f, 0.556641f, -0.0102539f, 0.541504f, 0, 0.506836f,
-0, 0.416504f, 0, 0.383301f, 0, 0.371338f, -0.010498f, 0.359375f, -0.0209961f, 0.359375f,
--0.0395508f, 0.359375f, -0.0639648f, 0.37915f, -0.0822754f, 0.398926f, -0.100586f,
-0.433105f, -0.100098f, 0.473145f, -0.289062f, 0.475586f, -0.300781f, 0.475586f, -0.311035f,
-0.475586f, -0.330078f, 0.460938f, -0.341309f, 0.440918f, -0.356445f, 0.401367f, -0.356445f,
-0.367188f, -0.356445f, 0.338135f, -0.343262f, 0.309082f, -0.330078f, 0.259277f, -0.286133f,
-0.219727f, -0.100098f, 0.259277f, -0.100098f, 0.269531f, -0.0917969f, 0.283691f,
--0.0800781f, 0.283691f, -0.0605469f, 0.283691f, -0.0302734f, 0.254883f, -0.0102539f,
-0.239746f, 0, 0.205078f, 0, 0.0913086f, 0, 0.0581055f, 0, 0.0461426f, -0.010498f,
-0.0341797f, -0.0209961f, 0.0341797f, -0.0395508f, 0.0341797f, -0.0708008f, 0.0644531f,
--0.0908203f, 0.0791016f, -0.100098f, 0.119629f, -0.100098f, 0.171387f, -0.343262f,
-0.142578f, -0.343262f, 0.130615f, -0.354004f, 0.118652f, -0.364746f, 0.118652f, -0.382812f,
-0.118652f, -0.412109f, 0.146484f, -0.432129f, 0.162109f, -0.443359f, 0.197266f, -0.443359f,
-0.29834f, 0.0161133f, 0.236328f, 0.0161133f, 0.185303f, -0.0090332f, 0.134277f, -0.0341797f,
-0.108643f, -0.0771484f, 0.0830078f, -0.120117f, 0.0830078f, -0.170898f, 0.0830078f,
--0.233887f, 0.125977f, -0.304199f, 0.168945f, -0.374512f, 0.245605f, -0.415527f,
-0.322266f, -0.456543f, 0.401855f, -0.456543f, 0.458984f, -0.456543f, 0.509277f, -0.430176f,
-0.55957f, -0.403809f, 0.584961f, -0.359619f, 0.610352f, -0.31543f, 0.610352f, -0.262695f,
-0.610352f, -0.194336f, 0.570068f, -0.12915f, 0.529785f, -0.0639648f, 0.452881f, -0.0239258f,
-0.375977f, 0.0161133f, 0.29834f, 0.0161133f, 0.318848f, -0.0839844f, 0.395508f, -0.0839844f,
-0.45166f, -0.133057f, 0.507812f, -0.182129f, 0.507812f, -0.23584f, 0.507812f, -0.288086f,
-0.472168f, -0.322266f, 0.436523f, -0.356445f, 0.377441f, -0.356445f, 0.293457f, -0.356445f,
-0.233398f, -0.293945f, 0.185547f, -0.243652f, 0.185547f, -0.193359f, 0.185547f, -0.150879f,
-0.222412f, -0.117432f, 0.259277f, -0.0839844f, 0.318848f, -0.0839844f, 0.187988f,
--0.0551758f, 0.152832f, 0.108887f, 0.212891f, 0.108887f, 0.246094f, 0.108887f, 0.258057f,
-0.119385f, 0.27002f, 0.129883f, 0.27002f, 0.148438f, 0.27002f, 0.179199f, 0.241211f,
-0.19873f, 0.226074f, 0.208984f, 0.191406f, 0.208984f, 0.0141602f, 0.208984f, -0.019043f,
-0.208984f, -0.0310059f, 0.19873f, -0.0429688f, 0.188477f, -0.0429688f, 0.169434f,
--0.0429688f, 0.139648f, -0.0146484f, 0.119629f, 0.000976562f, 0.108887f, 0.0356445f,
-0.108887f, 0.0527344f, 0.108887f, 0.148926f, -0.343262f, 0.131836f, -0.343262f, 0.0981445f,
--0.343262f, 0.0861816f, -0.35376f, 0.0742188f, -0.364258f, 0.0742188f, -0.382812f,
-0.0742188f, -0.412109f, 0.102051f, -0.432129f, 0.117676f, -0.443359f, 0.152832f,
--0.443359f, 0.27002f, -0.443359f, 0.263184f, -0.40918f, 0.343262f, -0.456543f, 0.42334f,
--0.456543f, 0.512695f, -0.456543f, 0.569336f, -0.401855f, 0.625977f, -0.347168f,
-0.625977f, -0.269043f, 0.625977f, -0.208008f, 0.587158f, -0.146973f, 0.54834f, -0.0859375f,
-0.473877f, -0.0480957f, 0.399414f, -0.0102539f, 0.32959f, -0.0102539f, 0.251953f,
--0.0102539f, 0.187988f, -0.0551758f, 0.347656f, -0.110352f, 0.418945f, -0.110352f,
-0.470947f, -0.154541f, 0.522949f, -0.19873f, 0.522949f, -0.241699f, 0.522949f, -0.291016f,
-0.489258f, -0.32373f, 0.455566f, -0.356445f, 0.400879f, -0.356445f, 0.330566f, -0.356445f,
-0.276611f, -0.306641f, 0.222656f, -0.256836f, 0.222656f, -0.211426f, 0.222656f, -0.172852f,
-0.25708f, -0.141602f, 0.291504f, -0.110352f, 0.347656f, -0.110352f, 0.374023f, -0.443359f,
-0.36084f, -0.380859f, 0.434082f, -0.426758f, 0.473389f, -0.44165f, 0.512695f, -0.456543f,
-0.544434f, -0.456543f, 0.587402f, -0.456543f, 0.620117f, -0.429932f, 0.652832f, -0.40332f,
-0.652832f, -0.381348f, 0.652832f, -0.357422f, 0.633545f, -0.338379f, 0.614258f, -0.319336f,
-0.590332f, -0.319336f, 0.571777f, -0.319336f, 0.555176f, -0.337891f, 0.538574f, -0.356445f,
-0.522461f, -0.356445f, 0.504395f, -0.356445f, 0.463867f, -0.335938f, 0.42334f, -0.31543f,
-0.333008f, -0.250977f, 0.30127f, -0.100098f, 0.443359f, -0.100098f, 0.477051f, -0.100098f,
-0.48877f, -0.0898438f, 0.500488f, -0.0795898f, 0.500488f, -0.0605469f, 0.500488f,
--0.0302734f, 0.47168f, -0.0102539f, 0.456543f, 0, 0.422363f, 0, 0.119629f, 0, 0.0864258f,
-0, 0.0744629f, -0.010498f, 0.0625f, -0.0209961f, 0.0625f, -0.0395508f, 0.0625f, -0.0698242f,
-0.0908203f, -0.0893555f, 0.106445f, -0.100098f, 0.141113f, -0.100098f, 0.201172f,
--0.100098f, 0.252441f, -0.343262f, 0.216309f, -0.343262f, 0.183105f, -0.343262f,
-0.170898f, -0.35376f, 0.158691f, -0.364258f, 0.158691f, -0.382812f, 0.158691f, -0.412109f,
-0.186523f, -0.432129f, 0.202148f, -0.443359f, 0.237793f, -0.443359f, 0.477051f, -0.326172f,
-0.456055f, -0.341309f, 0.430908f, -0.348877f, 0.405762f, -0.356445f, 0.375977f, -0.356445f,
-0.328125f, -0.356445f, 0.294434f, -0.343506f, 0.260742f, -0.330566f, 0.260742f, -0.317383f,
-0.260742f, -0.308594f, 0.271973f, -0.300781f, 0.287109f, -0.290039f, 0.343262f, -0.282227f,
-0.430176f, -0.27002f, 0.470459f, -0.256836f, 0.510742f, -0.243652f, 0.534668f, -0.214355f,
-0.558594f, -0.185059f, 0.558594f, -0.149414f, 0.558594f, -0.0776367f, 0.481445f,
--0.0307617f, 0.404297f, 0.0161133f, 0.302246f, 0.0161133f, 0.258789f, 0.0161133f,
-0.223145f, 0.00854492f, 0.1875f, 0.000976562f, 0.160156f, -0.0136719f, 0.14209f,
--0.000488281f, 0.125488f, -0.000488281f, 0.106445f, -0.000488281f, 0.0949707f, -0.0114746f,
-0.0834961f, -0.0224609f, 0.0834961f, -0.0375977f, 0.0834961f, -0.0473633f, 0.0878906f,
--0.0673828f, 0.0952148f, -0.101074f, 0.102539f, -0.137695f, 0.119873f, -0.152832f,
-0.137207f, -0.167969f, 0.159668f, -0.167969f, 0.177734f, -0.167969f, 0.1875f, -0.157959f,
-0.197266f, -0.147949f, 0.199219f, -0.123535f, 0.217773f, -0.104004f, 0.248047f, -0.0939941f,
-0.27832f, -0.0839844f, 0.320312f, -0.0839844f, 0.394043f, -0.0839844f, 0.436523f,
--0.10791f, 0.455566f, -0.118652f, 0.455566f, -0.132324f, 0.455566f, -0.151367f, 0.432129f,
--0.162598f, 0.408691f, -0.17334f, 0.333496f, -0.181641f, 0.225586f, -0.193359f, 0.191895f,
--0.22168f, 0.158203f, -0.25f, 0.158203f, -0.294434f, 0.158203f, -0.333008f, 0.183105f,
--0.367676f, 0.208008f, -0.402344f, 0.257812f, -0.42627f, 0.322266f, -0.456543f, 0.396484f,
--0.456543f, 0.431152f, -0.456543f, 0.461914f, -0.449951f, 0.492676f, -0.443359f,
-0.519043f, -0.429688f, 0.540039f, -0.443359f, 0.553711f, -0.443359f, 0.569336f, -0.443359f,
-0.580566f, -0.432373f, 0.591797f, -0.421387f, 0.591797f, -0.406738f, 0.591797f, -0.396484f,
-0.587891f, -0.376465f, 0.58252f, -0.352051f, 0.574707f, -0.315918f, 0.557373f, -0.300537f,
-0.540039f, -0.285156f, 0.517578f, -0.285156f, 0.499512f, -0.285156f, 0.488281f, -0.296387f,
-0.477051f, -0.307617f, 0.477051f, -0.326172f, 0.606445f, -0.443359f, 0.533691f, -0.100098f,
-0.5625f, -0.100098f, 0.574219f, -0.0895996f, 0.585938f, -0.0791016f, 0.585938f, -0.0605469f,
-0.585938f, -0.0307617f, 0.557617f, -0.0107422f, 0.54248f, 0, 0.507324f, 0, 0.412109f,
-0, 0.416992f, -0.0229492f, 0.322754f, 0.0161133f, 0.25f, 0.0161133f, 0.192383f, 0.0161133f,
-0.157227f, -0.0163574f, 0.12207f, -0.0488281f, 0.12207f, -0.0976562f, 0.12207f, -0.111328f,
-0.125488f, -0.12793f, 0.170898f, -0.343262f, 0.153809f, -0.343262f, 0.120605f, -0.343262f,
-0.108643f, -0.35376f, 0.0966797f, -0.364258f, 0.0966797f, -0.382812f, 0.0966797f,
--0.412598f, 0.125f, -0.432617f, 0.140137f, -0.443359f, 0.175293f, -0.443359f, 0.29248f,
--0.443359f, 0.229004f, -0.145508f, 0.226074f, -0.130371f, 0.226074f, -0.121094f,
-0.226074f, -0.105957f, 0.239014f, -0.0949707f, 0.251953f, -0.0839844f, 0.277832f,
--0.0839844f, 0.308594f, -0.0839844f, 0.345703f, -0.0957031f, 0.382812f, -0.107422f,
-0.441895f, -0.13916f, 0.485352f, -0.343262f, 0.44873f, -0.343262f, 0.415527f, -0.343262f,
-0.403564f, -0.35376f, 0.391602f, -0.364258f, 0.391602f, -0.382812f, 0.391602f, -0.412598f,
-0.419922f, -0.432617f, 0.435059f, -0.443359f, 0.470215f, -0.443359f, 0.244629f, -0.00341797f,
-0.143555f, -0.343262f, 0.122559f, -0.345703f, 0.112793f, -0.355957f, 0.103027f, -0.366211f,
-0.103027f, -0.382812f, 0.103027f, -0.412598f, 0.131348f, -0.432617f, 0.146484f, -0.443359f,
-0.181641f, -0.443359f, 0.272949f, -0.443359f, 0.306641f, -0.443359f, 0.318604f, -0.432861f,
-0.330566f, -0.422363f, 0.330566f, -0.403809f, 0.330566f, -0.379395f, 0.311035f, -0.361328f,
-0.291504f, -0.343262f, 0.254883f, -0.343262f, 0.32373f, -0.113281f, 0.489746f, -0.343262f,
-0.460449f, -0.343262f, 0.44873f, -0.354004f, 0.437012f, -0.364746f, 0.437012f, -0.382812f,
-0.437012f, -0.412109f, 0.464355f, -0.432129f, 0.47998f, -0.443359f, 0.515625f, -0.443359f,
-0.609375f, -0.443359f, 0.642578f, -0.443359f, 0.654541f, -0.432861f, 0.666504f, -0.422363f,
-0.666504f, -0.403809f, 0.666504f, -0.381348f, 0.649414f, -0.363525f, 0.632324f, -0.345703f,
-0.602539f, -0.343262f, 0.276855f, 0.108887f, 0.315918f, 0.108887f, 0.326172f, 0.117676f,
-0.340332f, 0.129395f, 0.340332f, 0.148438f, 0.340332f, 0.179199f, 0.311035f, 0.19873f,
-0.295898f, 0.208984f, 0.261719f, 0.208984f, 0.0429688f, 0.208984f, 0.00976562f, 0.208984f,
--0.00219727f, 0.19873f, -0.0141602f, 0.188477f, -0.0141602f, 0.169434f, -0.0141602f,
-0.139648f, 0.0141602f, 0.119629f, 0.0297852f, 0.108887f, 0.0644531f, 0.108887f, 0.164062f,
-0.108887f
-};
-
-const unsigned char CourierNewkBoldItalicVerbs[] = {
-6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 5, 0, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6,
-0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6
-};
-
-const unsigned CourierNewkBoldItalicCharCodes[] = {
-32,
-65, 72, 84, 87, 89, 97, 98, 101, 102, 103, 109, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed CourierNewkBoldItalicWidths[] = {
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0,
-0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0, 0x000099a0
-};
-
-const int CourierNewkBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(CourierNewkBoldItalicCharCodes);
-
-const SkPaint::FontMetrics CourierNewkBoldItalicMetrics = {
-0x2e302d23, -1.00391f, -0.83252f, 0.300293f, 0.376953f, 0, 0.941895f, 4.24199e-08f,
--0.102539f, 0.839355f, 0.458008f, 1.53766e-13f, 0.100098f, 0.23291f
-};
-
-const SkScalar LiberationSanskNormalPoints[] = {
-0.175293f, -0.193848f, 0.103027f, -0.193848f, 0.0913086f, -0.687988f, 0.187012f, -0.687988f,
-0.090332f, 0, 0.090332f, -0.0981445f, 0.185059f, -0.0981445f, 0.185059f, 0, 0.4375f,
--0.432129f, 0.399414f, -0.251953f, 0.526367f, -0.251953f, 0.526367f, -0.199219f,
-0.388184f, -0.199219f, 0.345215f, 0, 0.291504f, 0, 0.333496f, -0.199219f, 0.15625f,
--0.199219f, 0.115234f, 0, 0.0615234f, 0, 0.102539f, -0.199219f, 0.00439453f, -0.199219f,
-0.00439453f, -0.251953f, 0.114258f, -0.251953f, 0.152344f, -0.432129f, 0.0292969f,
--0.432129f, 0.0292969f, -0.484863f, 0.163086f, -0.484863f, 0.206543f, -0.684082f,
-0.260254f, -0.684082f, 0.217285f, -0.484863f, 0.394531f, -0.484863f, 0.4375f, -0.684082f,
-0.491211f, -0.684082f, 0.448242f, -0.484863f, 0.55127f, -0.484863f, 0.55127f, -0.432129f,
-0.20752f, -0.432129f, 0.168457f, -0.251953f, 0.345215f, -0.251953f, 0.383301f, -0.432129f,
-0.853516f, -0.211914f, 0.853516f, -0.150879f, 0.841064f, -0.109131f, 0.828613f, -0.0673828f,
-0.807373f, -0.041748f, 0.786133f, -0.0161133f, 0.757812f, -0.00512695f, 0.729492f,
-0.00585938f, 0.697266f, 0.00585938f, 0.665039f, 0.00585938f, 0.636963f, -0.00512695f,
-0.608887f, -0.0161133f, 0.588135f, -0.0415039f, 0.567383f, -0.0668945f, 0.55542f,
--0.108643f, 0.543457f, -0.150391f, 0.543457f, -0.211914f, 0.543457f, -0.276855f,
-0.555176f, -0.319336f, 0.566895f, -0.361816f, 0.587891f, -0.386963f, 0.608887f, -0.412109f,
-0.637451f, -0.422119f, 0.666016f, -0.432129f, 0.699219f, -0.432129f, 0.731445f, -0.432129f,
-0.759521f, -0.422119f, 0.787598f, -0.412109f, 0.80835f, -0.386963f, 0.829102f, -0.361816f,
-0.841309f, -0.319336f, 0.853516f, -0.276855f, 0.853516f, -0.211914f, 0.257324f, 0,
-0.181641f, 0, 0.631836f, -0.687988f, 0.708496f, -0.687988f, 0.192383f, -0.693848f,
-0.223633f, -0.693848f, 0.251465f, -0.683838f, 0.279297f, -0.673828f, 0.300293f, -0.648926f,
-0.321289f, -0.624023f, 0.333252f, -0.582031f, 0.345215f, -0.540039f, 0.345215f, -0.476074f,
-0.345215f, -0.414551f, 0.333008f, -0.372559f, 0.320801f, -0.330566f, 0.300049f, -0.304443f,
-0.279297f, -0.27832f, 0.250977f, -0.26709f, 0.222656f, -0.255859f, 0.19043f, -0.255859f,
-0.157715f, -0.255859f, 0.129395f, -0.26709f, 0.101074f, -0.27832f, 0.0803223f, -0.304199f,
-0.0595703f, -0.330078f, 0.0476074f, -0.37207f, 0.0356445f, -0.414062f, 0.0356445f,
--0.476074f, 0.0356445f, -0.540039f, 0.0476074f, -0.582031f, 0.0595703f, -0.624023f,
-0.0805664f, -0.648926f, 0.101562f, -0.673828f, 0.130371f, -0.683838f, 0.15918f, -0.693848f,
-0.192383f, -0.693848f, 0.78125f, -0.211914f, 0.78125f, -0.260254f, 0.775879f, -0.292236f,
-0.770508f, -0.324219f, 0.76001f, -0.343262f, 0.749512f, -0.362305f, 0.734131f, -0.370117f,
-0.71875f, -0.37793f, 0.699219f, -0.37793f, 0.678711f, -0.37793f, 0.663086f, -0.369873f,
-0.647461f, -0.361816f, 0.636719f, -0.342773f, 0.625977f, -0.32373f, 0.620605f, -0.291748f,
-0.615234f, -0.259766f, 0.615234f, -0.211914f, 0.615234f, -0.165527f, 0.62085f, -0.134277f,
-0.626465f, -0.103027f, 0.636963f, -0.0837402f, 0.647461f, -0.0644531f, 0.662842f,
--0.0561523f, 0.678223f, -0.0478516f, 0.698242f, -0.0478516f, 0.717285f, -0.0478516f,
-0.732666f, -0.0561523f, 0.748047f, -0.0644531f, 0.758789f, -0.0837402f, 0.769531f,
--0.103027f, 0.775391f, -0.134277f, 0.78125f, -0.165527f, 0.78125f, -0.211914f, 0.273438f,
--0.476074f, 0.273438f, -0.523926f, 0.268066f, -0.555664f, 0.262695f, -0.587402f,
-0.252441f, -0.606445f, 0.242188f, -0.625488f, 0.227051f, -0.633301f, 0.211914f, -0.641113f,
-0.192383f, -0.641113f, 0.171387f, -0.641113f, 0.155518f, -0.633057f, 0.139648f, -0.625f,
-0.128906f, -0.605957f, 0.118164f, -0.586914f, 0.112793f, -0.555176f, 0.107422f, -0.523438f,
-0.107422f, -0.476074f, 0.107422f, -0.429688f, 0.113037f, -0.397949f, 0.118652f, -0.366211f,
-0.12915f, -0.346924f, 0.139648f, -0.327637f, 0.155273f, -0.319336f, 0.170898f, -0.311035f,
-0.191406f, -0.311035f, 0.209961f, -0.311035f, 0.225098f, -0.319336f, 0.240234f, -0.327637f,
-0.250977f, -0.346924f, 0.261719f, -0.366211f, 0.267578f, -0.397949f, 0.273438f, -0.429688f,
-0.273438f, -0.476074f, 0.58252f, 0.00585938f, 0.535645f, 0.00585938f, 0.500488f,
--0.0102539f, 0.465332f, -0.0263672f, 0.437012f, -0.0561523f, 0.422363f, -0.043457f,
-0.403809f, -0.0317383f, 0.385254f, -0.0200195f, 0.362549f, -0.0107422f, 0.339844f,
--0.00146484f, 0.313232f, 0.00415039f, 0.286621f, 0.00976562f, 0.255371f, 0.00976562f,
-0.198242f, 0.00976562f, 0.156494f, -0.00488281f, 0.114746f, -0.0195312f, 0.0878906f,
--0.045166f, 0.0610352f, -0.0708008f, 0.0480957f, -0.105713f, 0.0351562f, -0.140625f,
-0.0351562f, -0.181152f, 0.0351562f, -0.219727f, 0.0476074f, -0.251221f, 0.0600586f,
--0.282715f, 0.0822754f, -0.30835f, 0.104492f, -0.333984f, 0.135254f, -0.354248f,
-0.166016f, -0.374512f, 0.202637f, -0.390625f, 0.193848f, -0.407227f, 0.186768f, -0.426025f,
-0.179688f, -0.444824f, 0.174316f, -0.463867f, 0.168945f, -0.48291f, 0.166016f, -0.501953f,
-0.163086f, -0.520996f, 0.163086f, -0.538086f, 0.163086f, -0.570312f, 0.172852f, -0.598389f,
-0.182617f, -0.626465f, 0.203369f, -0.647217f, 0.224121f, -0.667969f, 0.256592f, -0.679932f,
-0.289062f, -0.691895f, 0.334473f, -0.691895f, 0.370117f, -0.691895f, 0.400146f, -0.682617f,
-0.430176f, -0.67334f, 0.452148f, -0.655762f, 0.474121f, -0.638184f, 0.486328f, -0.612305f,
-0.498535f, -0.586426f, 0.498535f, -0.553223f, 0.498535f, -0.516602f, 0.482422f, -0.488037f,
-0.466309f, -0.459473f, 0.438965f, -0.437012f, 0.411621f, -0.414551f, 0.375488f, -0.39624f,
-0.339355f, -0.37793f, 0.298828f, -0.361816f, 0.329102f, -0.306152f, 0.364746f, -0.25708f,
-0.400391f, -0.208008f, 0.441895f, -0.160645f, 0.47168f, -0.20459f, 0.491455f, -0.253174f,
-0.51123f, -0.301758f, 0.525391f, -0.36084f, 0.596191f, -0.339844f, 0.579102f, -0.271973f,
-0.552979f, -0.216553f, 0.526855f, -0.161133f, 0.492676f, -0.11084f, 0.518555f, -0.0844727f,
-0.544434f, -0.0737305f, 0.570312f, -0.0629883f, 0.594238f, -0.0629883f, 0.609863f,
--0.0629883f, 0.624268f, -0.0646973f, 0.638672f, -0.0664062f, 0.651367f, -0.0708008f,
-0.651367f, -0.00488281f, 0.637695f, 0.000488281f, 0.619385f, 0.00317383f, 0.601074f,
-0.00585938f, 0.58252f, 0.00585938f, 0.424316f, -0.553223f, 0.424316f, -0.571289f,
-0.417725f, -0.585938f, 0.411133f, -0.600586f, 0.399414f, -0.611084f, 0.387695f, -0.621582f,
-0.37085f, -0.627197f, 0.354004f, -0.632812f, 0.333496f, -0.632812f, 0.286621f, -0.632812f,
-0.262207f, -0.607666f, 0.237793f, -0.58252f, 0.237793f, -0.538086f, 0.237793f, -0.509277f,
-0.246826f, -0.477783f, 0.255859f, -0.446289f, 0.269531f, -0.418945f, 0.30127f, -0.431641f,
-0.32959f, -0.445068f, 0.35791f, -0.458496f, 0.378906f, -0.474365f, 0.399902f, -0.490234f,
-0.412109f, -0.509521f, 0.424316f, -0.528809f, 0.424316f, -0.553223f, 0.388184f, -0.105957f,
-0.344727f, -0.157227f, 0.304688f, -0.213379f, 0.264648f, -0.269531f, 0.232422f, -0.329102f,
-0.177246f, -0.305664f, 0.147217f, -0.269531f, 0.117188f, -0.233398f, 0.117188f, -0.182129f,
-0.117188f, -0.155273f, 0.125732f, -0.13208f, 0.134277f, -0.108887f, 0.151855f, -0.0915527f,
-0.169434f, -0.0742188f, 0.196045f, -0.064209f, 0.222656f, -0.0541992f, 0.258301f,
--0.0541992f, 0.279785f, -0.0541992f, 0.299072f, -0.0588379f, 0.318359f, -0.0634766f,
-0.334961f, -0.0708008f, 0.351562f, -0.078125f, 0.36499f, -0.0874023f, 0.378418f,
--0.0966797f, 0.388184f, -0.105957f, 0.129883f, -0.47168f, 0.0610352f, -0.47168f,
-0.0507812f, -0.687988f, 0.140625f, -0.687988f, 0.270996f, -0.257812f, 0.270996f,
--0.189453f, 0.260742f, -0.127686f, 0.250488f, -0.065918f, 0.228516f, -0.00878906f,
-0.206543f, 0.0483398f, 0.172363f, 0.102051f, 0.138184f, 0.155762f, 0.0908203f, 0.207031f,
-0.00585938f, 0.207031f, 0.0517578f, 0.155762f, 0.0852051f, 0.102051f, 0.118652f,
-0.0483398f, 0.140137f, -0.00927734f, 0.161621f, -0.0668945f, 0.172119f, -0.128906f,
-0.182617f, -0.190918f, 0.182617f, -0.258789f, 0.182617f, -0.32666f, 0.172119f, -0.388672f,
-0.161621f, -0.450684f, 0.140137f, -0.508057f, 0.118652f, -0.56543f, 0.0852051f, -0.619385f,
-0.0517578f, -0.67334f, 0.00585938f, -0.724609f, 0.0908203f, -0.724609f, 0.138184f,
--0.67334f, 0.172363f, -0.619629f, 0.206543f, -0.565918f, 0.228516f, -0.508789f, 0.250488f,
--0.45166f, 0.260742f, -0.389648f, 0.270996f, -0.327637f, 0.270996f, -0.259766f, 0.222656f,
--0.543945f, 0.351562f, -0.594238f, 0.373535f, -0.529785f, 0.23584f, -0.494141f, 0.326172f,
--0.37207f, 0.268066f, -0.336914f, 0.194824f, -0.462891f, 0.118652f, -0.337891f, 0.0605469f,
--0.373047f, 0.152832f, -0.494141f, 0.0161133f, -0.529785f, 0.0380859f, -0.595215f,
-0.168457f, -0.542969f, 0.162598f, -0.687988f, 0.229004f, -0.687988f, 0.327637f, -0.296875f,
-0.327637f, -0.0878906f, 0.255859f, -0.0878906f, 0.255859f, -0.296875f, 0.0488281f,
--0.296875f, 0.0488281f, -0.368164f, 0.255859f, -0.368164f, 0.255859f, -0.577148f,
-0.327637f, -0.577148f, 0.327637f, -0.368164f, 0.534668f, -0.368164f, 0.534668f, -0.296875f,
-0.0444336f, -0.226562f, 0.0444336f, -0.304688f, 0.288574f, -0.304688f, 0.288574f,
--0.226562f, 0.0913086f, 0, 0.0913086f, -0.106934f, 0.186523f, -0.106934f, 0.186523f,
-0, 0, 0.00976562f, 0.200684f, -0.724609f, 0.277832f, -0.724609f, 0.0791016f, 0.00976562f,
-0.0761719f, 0, 0.0761719f, -0.074707f, 0.251465f, -0.074707f, 0.251465f, -0.604004f,
-0.0961914f, -0.493164f, 0.0961914f, -0.576172f, 0.258789f, -0.687988f, 0.339844f,
--0.687988f, 0.339844f, -0.074707f, 0.507324f, -0.074707f, 0.507324f, 0, 0.050293f,
-0, 0.050293f, -0.0620117f, 0.0751953f, -0.119141f, 0.111084f, -0.162842f, 0.146973f,
--0.206543f, 0.186523f, -0.241943f, 0.226074f, -0.277344f, 0.264893f, -0.307617f,
-0.303711f, -0.337891f, 0.334961f, -0.368164f, 0.366211f, -0.398438f, 0.385498f, -0.431641f,
-0.404785f, -0.464844f, 0.404785f, -0.506836f, 0.404785f, -0.536133f, 0.395996f, -0.55835f,
-0.387207f, -0.580566f, 0.370605f, -0.595703f, 0.354004f, -0.61084f, 0.330811f, -0.618408f,
-0.307617f, -0.625977f, 0.279297f, -0.625977f, 0.25293f, -0.625977f, 0.229736f, -0.618652f,
-0.206543f, -0.611328f, 0.188477f, -0.59668f, 0.17041f, -0.582031f, 0.158936f, -0.560303f,
-0.147461f, -0.538574f, 0.144043f, -0.509766f, 0.0541992f, -0.518066f, 0.0585938f,
--0.555176f, 0.074707f, -0.587891f, 0.0908203f, -0.620605f, 0.119141f, -0.645264f,
-0.147461f, -0.669922f, 0.187256f, -0.684082f, 0.227051f, -0.698242f, 0.279297f, -0.698242f,
-0.330566f, -0.698242f, 0.370605f, -0.686035f, 0.410645f, -0.673828f, 0.438232f, -0.649902f,
-0.46582f, -0.625977f, 0.480469f, -0.59082f, 0.495117f, -0.555664f, 0.495117f, -0.509766f,
-0.495117f, -0.475098f, 0.482666f, -0.443848f, 0.470215f, -0.412598f, 0.449463f, -0.384277f,
-0.428711f, -0.355957f, 0.401367f, -0.32959f, 0.374023f, -0.303223f, 0.344238f, -0.278076f,
-0.314453f, -0.25293f, 0.28418f, -0.228271f, 0.253906f, -0.203613f, 0.227295f, -0.178711f,
-0.200684f, -0.153809f, 0.179688f, -0.128174f, 0.158691f, -0.102539f, 0.146973f, -0.074707f,
-0.505859f, -0.074707f, 0.505859f, 0, 0.430176f, -0.155762f, 0.430176f, 0, 0.347168f,
-0, 0.347168f, -0.155762f, 0.0229492f, -0.155762f, 0.0229492f, -0.224121f, 0.337891f,
--0.687988f, 0.430176f, -0.687988f, 0.430176f, -0.225098f, 0.526855f, -0.225098f,
-0.526855f, -0.155762f, 0.347168f, -0.588867f, 0.346191f, -0.586426f, 0.342285f, -0.579346f,
-0.338379f, -0.572266f, 0.333496f, -0.563477f, 0.328613f, -0.554688f, 0.323486f, -0.545654f,
-0.318359f, -0.536621f, 0.314453f, -0.530762f, 0.138184f, -0.270996f, 0.135742f, -0.26709f,
-0.131104f, -0.260742f, 0.126465f, -0.254395f, 0.121582f, -0.247803f, 0.116699f, -0.241211f,
-0.111816f, -0.234863f, 0.106934f, -0.228516f, 0.104004f, -0.225098f, 0.347168f, -0.225098f,
-0.51416f, -0.224121f, 0.51416f, -0.172363f, 0.498535f, -0.129395f, 0.48291f, -0.0864258f,
-0.452148f, -0.0554199f, 0.421387f, -0.0244141f, 0.375732f, -0.00732422f, 0.330078f,
-0.00976562f, 0.27002f, 0.00976562f, 0.21582f, 0.00976562f, 0.175537f, -0.00292969f,
-0.135254f, -0.015625f, 0.107422f, -0.0378418f, 0.0795898f, -0.0600586f, 0.0632324f,
--0.0898438f, 0.046875f, -0.119629f, 0.0400391f, -0.153809f, 0.128906f, -0.164062f,
-0.134277f, -0.144531f, 0.144043f, -0.126221f, 0.153809f, -0.10791f, 0.170654f, -0.0935059f,
-0.1875f, -0.0791016f, 0.212158f, -0.0705566f, 0.236816f, -0.0620117f, 0.271973f,
--0.0620117f, 0.306152f, -0.0620117f, 0.333984f, -0.0725098f, 0.361816f, -0.0830078f,
-0.381592f, -0.103516f, 0.401367f, -0.124023f, 0.412109f, -0.153809f, 0.422852f, -0.183594f,
-0.422852f, -0.222168f, 0.422852f, -0.253906f, 0.412598f, -0.280518f, 0.402344f, -0.307129f,
-0.383301f, -0.326416f, 0.364258f, -0.345703f, 0.33667f, -0.356445f, 0.309082f, -0.367188f,
-0.273926f, -0.367188f, 0.251953f, -0.367188f, 0.233398f, -0.363281f, 0.214844f, -0.359375f,
-0.198975f, -0.352539f, 0.183105f, -0.345703f, 0.170166f, -0.33667f, 0.157227f, -0.327637f,
-0.145996f, -0.317871f, 0.0600586f, -0.317871f, 0.0830078f, -0.687988f, 0.474121f,
--0.687988f, 0.474121f, -0.613281f, 0.163086f, -0.613281f, 0.149902f, -0.39502f, 0.17334f,
--0.413086f, 0.208496f, -0.426025f, 0.243652f, -0.438965f, 0.291992f, -0.438965f,
-0.343262f, -0.438965f, 0.384277f, -0.42334f, 0.425293f, -0.407715f, 0.454102f, -0.37915f,
-0.48291f, -0.350586f, 0.498535f, -0.311035f, 0.51416f, -0.271484f, 0.51416f, -0.224121f,
-0.512207f, -0.225098f, 0.512207f, -0.17334f, 0.497803f, -0.130127f, 0.483398f, -0.0869141f,
-0.455322f, -0.0559082f, 0.427246f, -0.0249023f, 0.385742f, -0.00756836f, 0.344238f,
-0.00976562f, 0.290039f, 0.00976562f, 0.22998f, 0.00976562f, 0.185059f, -0.0131836f,
-0.140137f, -0.0361328f, 0.110352f, -0.0793457f, 0.0805664f, -0.122559f, 0.0656738f,
--0.185303f, 0.0507812f, -0.248047f, 0.0507812f, -0.328125f, 0.0507812f, -0.419922f,
-0.067627f, -0.489258f, 0.0844727f, -0.558594f, 0.116211f, -0.60498f, 0.147949f, -0.651367f,
-0.193604f, -0.674805f, 0.239258f, -0.698242f, 0.296875f, -0.698242f, 0.332031f, -0.698242f,
-0.362793f, -0.690918f, 0.393555f, -0.683594f, 0.418701f, -0.667236f, 0.443848f, -0.650879f,
-0.462891f, -0.624023f, 0.481934f, -0.597168f, 0.493164f, -0.558105f, 0.40918f, -0.542969f,
-0.395508f, -0.587402f, 0.365479f, -0.607178f, 0.335449f, -0.626953f, 0.295898f, -0.626953f,
-0.259766f, -0.626953f, 0.230469f, -0.609863f, 0.201172f, -0.592773f, 0.180664f, -0.558838f,
-0.160156f, -0.524902f, 0.14917f, -0.473633f, 0.138184f, -0.422363f, 0.138184f, -0.354004f,
-0.162109f, -0.398438f, 0.205566f, -0.421631f, 0.249023f, -0.444824f, 0.305176f, -0.444824f,
-0.352051f, -0.444824f, 0.390137f, -0.429688f, 0.428223f, -0.414551f, 0.455322f, -0.385986f,
-0.482422f, -0.357422f, 0.497314f, -0.31665f, 0.512207f, -0.275879f, 0.512207f, -0.225098f,
-0.422852f, -0.221191f, 0.422852f, -0.256836f, 0.414062f, -0.285645f, 0.405273f, -0.314453f,
-0.387695f, -0.334717f, 0.370117f, -0.35498f, 0.344238f, -0.365967f, 0.318359f, -0.376953f,
-0.28418f, -0.376953f, 0.260254f, -0.376953f, 0.23584f, -0.369873f, 0.211426f, -0.362793f,
-0.19165f, -0.346924f, 0.171875f, -0.331055f, 0.159424f, -0.305176f, 0.146973f, -0.279297f,
-0.146973f, -0.242188f, 0.146973f, -0.204102f, 0.156738f, -0.171143f, 0.166504f, -0.138184f,
-0.184814f, -0.11377f, 0.203125f, -0.0893555f, 0.229004f, -0.0751953f, 0.254883f,
--0.0610352f, 0.287109f, -0.0610352f, 0.318848f, -0.0610352f, 0.343994f, -0.0720215f,
-0.369141f, -0.0830078f, 0.386719f, -0.10376f, 0.404297f, -0.124512f, 0.413574f, -0.154297f,
-0.422852f, -0.184082f, 0.422852f, -0.221191f, 0.505859f, -0.616699f, 0.454102f, -0.537598f,
-0.410645f, -0.4646f, 0.367188f, -0.391602f, 0.335938f, -0.317627f, 0.304688f, -0.243652f,
-0.287354f, -0.165771f, 0.27002f, -0.0878906f, 0.27002f, 0, 0.178223f, 0, 0.178223f,
--0.0825195f, 0.197754f, -0.161865f, 0.217285f, -0.241211f, 0.250488f, -0.317627f,
-0.283691f, -0.394043f, 0.327637f, -0.467773f, 0.371582f, -0.541504f, 0.420898f, -0.613281f,
-0.0512695f, -0.613281f, 0.0512695f, -0.687988f, 0.505859f, -0.687988f, 0.508789f,
--0.35791f, 0.508789f, -0.266113f, 0.491455f, -0.197021f, 0.474121f, -0.12793f, 0.441895f,
--0.0820312f, 0.409668f, -0.0361328f, 0.363525f, -0.0131836f, 0.317383f, 0.00976562f,
-0.259766f, 0.00976562f, 0.220215f, 0.00976562f, 0.188477f, 0.00170898f, 0.156738f,
--0.00634766f, 0.131836f, -0.0234375f, 0.106934f, -0.0405273f, 0.0893555f, -0.0678711f,
-0.0717773f, -0.0952148f, 0.0610352f, -0.133789f, 0.14502f, -0.146973f, 0.158691f,
--0.102539f, 0.187744f, -0.0817871f, 0.216797f, -0.0610352f, 0.26123f, -0.0610352f,
-0.296875f, -0.0610352f, 0.326416f, -0.0778809f, 0.355957f, -0.0947266f, 0.376709f,
--0.128418f, 0.397461f, -0.162109f, 0.40918f, -0.212891f, 0.420898f, -0.263672f, 0.421875f,
--0.332031f, 0.411621f, -0.309082f, 0.393799f, -0.291016f, 0.375977f, -0.272949f,
-0.353271f, -0.260498f, 0.330566f, -0.248047f, 0.304199f, -0.241455f, 0.277832f, -0.234863f,
-0.250977f, -0.234863f, 0.204102f, -0.234863f, 0.16626f, -0.251709f, 0.128418f, -0.268555f,
-0.102051f, -0.298828f, 0.0756836f, -0.329102f, 0.0612793f, -0.371826f, 0.046875f,
--0.414551f, 0.046875f, -0.466797f, 0.046875f, -0.52002f, 0.0622559f, -0.562988f,
-0.0776367f, -0.605957f, 0.106934f, -0.635986f, 0.13623f, -0.666016f, 0.178955f, -0.682129f,
-0.22168f, -0.698242f, 0.275879f, -0.698242f, 0.390625f, -0.698242f, 0.449707f, -0.613281f,
-0.508789f, -0.52832f, 0.508789f, -0.35791f, 0.413086f, -0.442871f, 0.413086f, -0.480957f,
-0.404053f, -0.514648f, 0.39502f, -0.54834f, 0.377197f, -0.573242f, 0.359375f, -0.598145f,
-0.333252f, -0.612549f, 0.307129f, -0.626953f, 0.272949f, -0.626953f, 0.241211f, -0.626953f,
-0.21582f, -0.615723f, 0.19043f, -0.604492f, 0.172852f, -0.58374f, 0.155273f, -0.562988f,
-0.145752f, -0.533203f, 0.13623f, -0.503418f, 0.13623f, -0.466797f, 0.13623f, -0.432129f,
-0.144775f, -0.402344f, 0.15332f, -0.372559f, 0.17041f, -0.35083f, 0.1875f, -0.329102f,
-0.212891f, -0.31665f, 0.238281f, -0.304199f, 0.271973f, -0.304199f, 0.296387f, -0.304199f,
-0.321533f, -0.3125f, 0.34668f, -0.320801f, 0.366943f, -0.337891f, 0.387207f, -0.35498f,
-0.400146f, -0.381104f, 0.413086f, -0.407227f, 0.413086f, -0.442871f, 0.0913086f,
--0.427246f, 0.0913086f, -0.52832f, 0.186523f, -0.52832f, 0.186523f, -0.427246f, 0.0913086f,
-0, 0.0913086f, -0.101074f, 0.186523f, -0.101074f, 0.186523f, 0, 0.187988f, -0.101074f,
-0.187988f, -0.0249023f, 0.187988f, 0.000976562f, 0.185791f, 0.0222168f, 0.183594f,
-0.043457f, 0.178711f, 0.0617676f, 0.173828f, 0.0800781f, 0.166748f, 0.0961914f, 0.159668f,
-0.112305f, 0.149902f, 0.12793f, 0.0898438f, 0.12793f, 0.111816f, 0.0961914f, 0.123779f,
-0.0639648f, 0.135742f, 0.0317383f, 0.135742f, 0, 0.0927734f, 0, 0.0927734f, -0.101074f,
-0.0927734f, -0.427246f, 0.0927734f, -0.52832f, 0.187988f, -0.52832f, 0.187988f, -0.427246f,
-0.0493164f, -0.278809f, 0.0493164f, -0.378906f, 0.535156f, -0.583008f, 0.535156f,
--0.507812f, 0.116211f, -0.329102f, 0.535156f, -0.149902f, 0.535156f, -0.0751953f,
-0.0488281f, -0.417969f, 0.0488281f, -0.490234f, 0.534668f, -0.490234f, 0.534668f,
--0.417969f, 0.0488281f, -0.167969f, 0.0488281f, -0.240234f, 0.534668f, -0.240234f,
-0.534668f, -0.167969f, 0.0493164f, -0.0751953f, 0.0493164f, -0.149902f, 0.468262f,
--0.329102f, 0.0493164f, -0.507812f, 0.0493164f, -0.583008f, 0.535156f, -0.378906f,
-0.535156f, -0.278809f, 0.519043f, -0.503906f, 0.519043f, -0.469238f, 0.51001f, -0.442871f,
-0.500977f, -0.416504f, 0.48584f, -0.395752f, 0.470703f, -0.375f, 0.451416f, -0.358643f,
-0.432129f, -0.342285f, 0.412109f, -0.327637f, 0.39209f, -0.312988f, 0.372803f, -0.298828f,
-0.353516f, -0.284668f, 0.338135f, -0.268066f, 0.322754f, -0.251465f, 0.313232f, -0.231201f,
-0.303711f, -0.210938f, 0.303223f, -0.184082f, 0.217773f, -0.184082f, 0.21875f, -0.217773f,
-0.228271f, -0.243164f, 0.237793f, -0.268555f, 0.25293f, -0.288086f, 0.268066f, -0.307617f,
-0.287109f, -0.322998f, 0.306152f, -0.338379f, 0.325684f, -0.352295f, 0.345215f, -0.366211f,
-0.364014f, -0.380127f, 0.382812f, -0.394043f, 0.397461f, -0.411133f, 0.412109f, -0.428223f,
-0.421143f, -0.449707f, 0.430176f, -0.471191f, 0.430176f, -0.5f, 0.430176f, -0.528809f,
-0.419922f, -0.55127f, 0.409668f, -0.57373f, 0.390869f, -0.589111f, 0.37207f, -0.604492f,
-0.345459f, -0.612305f, 0.318848f, -0.620117f, 0.286133f, -0.620117f, 0.217773f, -0.620117f,
-0.177734f, -0.585938f, 0.137695f, -0.551758f, 0.130859f, -0.492188f, 0.0410156f,
--0.498047f, 0.0463867f, -0.539062f, 0.0627441f, -0.575439f, 0.0791016f, -0.611816f,
-0.108643f, -0.63916f, 0.138184f, -0.666504f, 0.181885f, -0.682373f, 0.225586f, -0.698242f,
-0.285156f, -0.698242f, 0.34082f, -0.698242f, 0.384277f, -0.68457f, 0.427734f, -0.670898f,
-0.457764f, -0.645752f, 0.487793f, -0.620605f, 0.503418f, -0.584473f, 0.519043f, -0.54834f,
-0.519043f, -0.503906f, 0.213867f, 0, 0.213867f, -0.0981445f, 0.309082f, -0.0981445f,
-0.309082f, 0, 0.928711f, -0.368652f, 0.928711f, -0.29834f, 0.912354f, -0.23999f,
-0.895996f, -0.181641f, 0.867188f, -0.139648f, 0.838379f, -0.0976562f, 0.798096f,
--0.0742188f, 0.757812f, -0.0507812f, 0.710449f, -0.0507812f, 0.683105f, -0.0507812f,
-0.663818f, -0.057373f, 0.644531f, -0.0639648f, 0.632324f, -0.0754395f, 0.620117f,
--0.0869141f, 0.614746f, -0.102539f, 0.609375f, -0.118164f, 0.609375f, -0.136719f,
-0.609375f, -0.144043f, 0.609863f, -0.154541f, 0.610352f, -0.165039f, 0.61084f, -0.170898f,
-0.60791f, -0.170898f, 0.596191f, -0.148926f, 0.579346f, -0.127197f, 0.5625f, -0.105469f,
-0.539795f, -0.088623f, 0.51709f, -0.0717773f, 0.488525f, -0.0612793f, 0.459961f,
--0.0507812f, 0.425293f, -0.0507812f, 0.384277f, -0.0507812f, 0.35376f, -0.0649414f,
-0.323242f, -0.0791016f, 0.303467f, -0.104248f, 0.283691f, -0.129395f, 0.273926f,
--0.163818f, 0.26416f, -0.198242f, 0.26416f, -0.23877f, 0.26416f, -0.297363f, 0.281494f,
--0.351318f, 0.298828f, -0.405273f, 0.331055f, -0.446533f, 0.363281f, -0.487793f,
-0.408447f, -0.512695f, 0.453613f, -0.537598f, 0.509277f, -0.537598f, 0.538574f, -0.537598f,
-0.562012f, -0.531006f, 0.585449f, -0.524414f, 0.603271f, -0.512695f, 0.621094f, -0.500977f,
-0.634277f, -0.484619f, 0.647461f, -0.468262f, 0.65625f, -0.44873f, 0.65918f, -0.44873f,
-0.678223f, -0.526855f, 0.754395f, -0.526855f, 0.697754f, -0.279785f, 0.688477f, -0.23877f,
-0.684082f, -0.209473f, 0.679688f, -0.180176f, 0.679688f, -0.15625f, 0.679688f, -0.132812f,
-0.690186f, -0.121582f, 0.700684f, -0.110352f, 0.719238f, -0.110352f, 0.749512f, -0.110352f,
-0.775635f, -0.130127f, 0.801758f, -0.149902f, 0.821045f, -0.18457f, 0.840332f, -0.219238f,
-0.851318f, -0.266113f, 0.862305f, -0.312988f, 0.862305f, -0.367676f, 0.862305f, -0.430664f,
-0.842041f, -0.484863f, 0.821777f, -0.539062f, 0.782471f, -0.578613f, 0.743164f, -0.618164f,
-0.685059f, -0.640625f, 0.626953f, -0.663086f, 0.550781f, -0.663086f, 0.485352f, -0.663086f,
-0.429932f, -0.647461f, 0.374512f, -0.631836f, 0.32959f, -0.603516f, 0.284668f, -0.575195f,
-0.250732f, -0.535889f, 0.216797f, -0.496582f, 0.193848f, -0.449707f, 0.170898f, -0.402832f,
-0.15918f, -0.349365f, 0.147461f, -0.295898f, 0.147461f, -0.239746f, 0.147461f, -0.170898f,
-0.168457f, -0.112793f, 0.189453f, -0.0546875f, 0.229736f, -0.0129395f, 0.27002f,
-0.0288086f, 0.329346f, 0.0522461f, 0.388672f, 0.0756836f, 0.46582f, 0.0756836f, 0.51709f,
-0.0756836f, 0.561523f, 0.067627f, 0.605957f, 0.0595703f, 0.643066f, 0.0478516f, 0.680176f,
-0.0361328f, 0.709473f, 0.0222168f, 0.73877f, 0.00830078f, 0.760254f, -0.00341797f,
-0.787109f, 0.0512695f, 0.762695f, 0.065918f, 0.729736f, 0.0812988f, 0.696777f, 0.0966797f,
-0.65625f, 0.109375f, 0.615723f, 0.12207f, 0.567871f, 0.130127f, 0.52002f, 0.138184f,
-0.46582f, 0.138184f, 0.373047f, 0.138184f, 0.301025f, 0.110107f, 0.229004f, 0.0820312f,
-0.179443f, 0.0317383f, 0.129883f, -0.0185547f, 0.104248f, -0.0878906f, 0.0786133f,
--0.157227f, 0.0786133f, -0.239746f, 0.0786133f, -0.307617f, 0.0939941f, -0.370117f,
-0.109375f, -0.432617f, 0.138184f, -0.486328f, 0.166992f, -0.540039f, 0.208496f, -0.583984f,
-0.25f, -0.62793f, 0.30249f, -0.65918f, 0.35498f, -0.69043f, 0.417236f, -0.70752f,
-0.479492f, -0.724609f, 0.549805f, -0.724609f, 0.647949f, -0.724609f, 0.719238f, -0.695801f,
-0.790527f, -0.666992f, 0.837158f, -0.618164f, 0.883789f, -0.569336f, 0.90625f, -0.504883f,
-0.928711f, -0.44043f, 0.928711f, -0.368652f, 0.632812f, -0.364746f, 0.632812f, -0.38916f,
-0.624512f, -0.409668f, 0.616211f, -0.430176f, 0.60083f, -0.444824f, 0.585449f, -0.459473f,
-0.563721f, -0.467529f, 0.541992f, -0.475586f, 0.514648f, -0.475586f, 0.472656f, -0.475586f,
-0.440918f, -0.454834f, 0.40918f, -0.434082f, 0.387939f, -0.400391f, 0.366699f, -0.366699f,
-0.355713f, -0.324463f, 0.344727f, -0.282227f, 0.344727f, -0.239746f, 0.344727f, -0.181152f,
-0.36792f, -0.147949f, 0.391113f, -0.114746f, 0.439453f, -0.114746f, 0.473145f, -0.114746f,
-0.502441f, -0.129883f, 0.531738f, -0.14502f, 0.555176f, -0.169922f, 0.578613f, -0.194824f,
-0.595703f, -0.227051f, 0.612793f, -0.259277f, 0.621582f, -0.293945f, 0.625977f, -0.311523f,
-0.629395f, -0.331055f, 0.632812f, -0.350586f, 0.632812f, -0.364746f, 0.569824f, 0,
-0.491211f, -0.201172f, 0.177734f, -0.201172f, 0.0986328f, 0, 0.00195312f, 0, 0.282715f,
--0.687988f, 0.388672f, -0.687988f, 0.665039f, 0, 0.375f, -0.500977f, 0.367188f, -0.520508f,
-0.360107f, -0.540527f, 0.353027f, -0.560547f, 0.347656f, -0.576904f, 0.342285f, -0.593262f,
-0.338623f, -0.604248f, 0.334961f, -0.615234f, 0.334473f, -0.617676f, 0.333496f, -0.615234f,
-0.330078f, -0.604004f, 0.32666f, -0.592773f, 0.321045f, -0.576172f, 0.31543f, -0.55957f,
-0.30835f, -0.539551f, 0.30127f, -0.519531f, 0.293945f, -0.5f, 0.206055f, -0.273926f,
-0.463379f, -0.273926f, 0.614258f, -0.193848f, 0.614258f, -0.141602f, 0.59375f, -0.104736f,
-0.573242f, -0.0678711f, 0.538574f, -0.0446777f, 0.503906f, -0.0214844f, 0.458008f,
--0.0107422f, 0.412109f, 0, 0.361328f, 0, 0.0820312f, 0, 0.0820312f, -0.687988f, 0.332031f,
--0.687988f, 0.38916f, -0.687988f, 0.434082f, -0.678467f, 0.479004f, -0.668945f, 0.510254f,
--0.648438f, 0.541504f, -0.62793f, 0.557861f, -0.596436f, 0.574219f, -0.564941f, 0.574219f,
--0.520996f, 0.574219f, -0.492188f, 0.566162f, -0.466797f, 0.558105f, -0.441406f,
-0.541748f, -0.420654f, 0.525391f, -0.399902f, 0.500732f, -0.38501f, 0.476074f, -0.370117f,
-0.443359f, -0.362793f, 0.484863f, -0.35791f, 0.516846f, -0.34375f, 0.548828f, -0.32959f,
-0.570312f, -0.307617f, 0.591797f, -0.285645f, 0.603027f, -0.256592f, 0.614258f, -0.227539f,
-0.614258f, -0.193848f, 0.480469f, -0.509766f, 0.480469f, -0.56543f, 0.442383f, -0.589355f,
-0.404297f, -0.613281f, 0.332031f, -0.613281f, 0.175293f, -0.613281f, 0.175293f, -0.395508f,
-0.332031f, -0.395508f, 0.373047f, -0.395508f, 0.401367f, -0.403564f, 0.429688f, -0.411621f,
-0.447266f, -0.426514f, 0.464844f, -0.441406f, 0.472656f, -0.462402f, 0.480469f, -0.483398f,
-0.480469f, -0.509766f, 0.52002f, -0.201172f, 0.52002f, -0.233887f, 0.508057f, -0.256836f,
-0.496094f, -0.279785f, 0.473633f, -0.294434f, 0.451172f, -0.309082f, 0.419678f, -0.315918f,
-0.388184f, -0.322754f, 0.349121f, -0.322754f, 0.175293f, -0.322754f, 0.175293f, -0.074707f,
-0.356445f, -0.074707f, 0.39209f, -0.074707f, 0.422119f, -0.0805664f, 0.452148f, -0.0864258f,
-0.473877f, -0.101074f, 0.495605f, -0.115723f, 0.507812f, -0.140137f, 0.52002f, -0.164551f,
-0.52002f, -0.201172f, 0.386719f, -0.62207f, 0.328125f, -0.62207f, 0.282959f, -0.602539f,
-0.237793f, -0.583008f, 0.207275f, -0.546875f, 0.176758f, -0.510742f, 0.161133f, -0.459961f,
-0.145508f, -0.40918f, 0.145508f, -0.347168f, 0.145508f, -0.285156f, 0.162354f, -0.233643f,
-0.179199f, -0.182129f, 0.210693f, -0.14502f, 0.242188f, -0.10791f, 0.287842f, -0.0874023f,
-0.333496f, -0.0668945f, 0.390625f, -0.0668945f, 0.430664f, -0.0668945f, 0.463623f,
--0.0773926f, 0.496582f, -0.0878906f, 0.523193f, -0.106934f, 0.549805f, -0.125977f,
-0.570801f, -0.1521f, 0.591797f, -0.178223f, 0.60791f, -0.209961f, 0.684082f, -0.171875f,
-0.665527f, -0.133301f, 0.638184f, -0.100098f, 0.61084f, -0.0668945f, 0.573975f, -0.0424805f,
-0.537109f, -0.0180664f, 0.490479f, -0.00415039f, 0.443848f, 0.00976562f, 0.38623f,
-0.00976562f, 0.302734f, 0.00976562f, 0.23999f, -0.0168457f, 0.177246f, -0.043457f,
-0.13501f, -0.0910645f, 0.0927734f, -0.138672f, 0.0717773f, -0.204102f, 0.0507812f,
--0.269531f, 0.0507812f, -0.347168f, 0.0507812f, -0.427734f, 0.072998f, -0.492676f,
-0.0952148f, -0.557617f, 0.137939f, -0.603271f, 0.180664f, -0.648926f, 0.243164f,
--0.673584f, 0.305664f, -0.698242f, 0.385742f, -0.698242f, 0.495605f, -0.698242f,
-0.569336f, -0.655273f, 0.643066f, -0.612305f, 0.677734f, -0.527832f, 0.589355f, -0.498535f,
-0.57959f, -0.522949f, 0.562988f, -0.545166f, 0.546387f, -0.567383f, 0.521484f, -0.584473f,
-0.496582f, -0.601562f, 0.463135f, -0.611816f, 0.429688f, -0.62207f, 0.386719f, -0.62207f,
-0.674316f, -0.351074f, 0.674316f, -0.265137f, 0.648438f, -0.199463f, 0.622559f, -0.133789f,
-0.577637f, -0.0895996f, 0.532715f, -0.0454102f, 0.471436f, -0.0227051f, 0.410156f,
-0, 0.339355f, 0, 0.0820312f, 0, 0.0820312f, -0.687988f, 0.30957f, -0.687988f, 0.38916f,
--0.687988f, 0.456299f, -0.668213f, 0.523438f, -0.648438f, 0.571777f, -0.607178f,
-0.620117f, -0.565918f, 0.647217f, -0.502441f, 0.674316f, -0.438965f, 0.674316f, -0.351074f,
-0.580566f, -0.351074f, 0.580566f, -0.420898f, 0.560547f, -0.470459f, 0.540527f, -0.52002f,
-0.504395f, -0.551758f, 0.468262f, -0.583496f, 0.417969f, -0.598389f, 0.367676f, -0.613281f,
-0.307617f, -0.613281f, 0.175293f, -0.613281f, 0.175293f, -0.074707f, 0.328613f, -0.074707f,
-0.382812f, -0.074707f, 0.428955f, -0.0922852f, 0.475098f, -0.109863f, 0.508789f,
--0.144531f, 0.54248f, -0.179199f, 0.561523f, -0.230957f, 0.580566f, -0.282715f, 0.580566f,
--0.351074f, 0.0820312f, 0, 0.0820312f, -0.687988f, 0.604004f, -0.687988f, 0.604004f,
--0.611816f, 0.175293f, -0.611816f, 0.175293f, -0.391113f, 0.574707f, -0.391113f,
-0.574707f, -0.315918f, 0.175293f, -0.315918f, 0.175293f, -0.0761719f, 0.624023f,
--0.0761719f, 0.624023f, 0, 0.175293f, -0.611816f, 0.175293f, -0.355957f, 0.559082f,
--0.355957f, 0.559082f, -0.278809f, 0.175293f, -0.278809f, 0.175293f, 0, 0.0820312f,
-0, 0.0820312f, -0.687988f, 0.570801f, -0.687988f, 0.570801f, -0.611816f, 0.547363f,
-0, 0.547363f, -0.318848f, 0.175293f, -0.318848f, 0.175293f, 0, 0.0820312f, 0, 0.0820312f,
--0.687988f, 0.175293f, -0.687988f, 0.175293f, -0.396973f, 0.547363f, -0.396973f,
-0.547363f, -0.687988f, 0.640625f, -0.687988f, 0.640625f, 0, 0.0922852f, 0, 0.0922852f,
--0.687988f, 0.185547f, -0.687988f, 0.185547f, 0, 0.223145f, 0.00976562f, 0.139648f,
-0.00976562f, 0.0861816f, -0.0336914f, 0.0327148f, -0.0771484f, 0.015625f, -0.170898f,
-0.106934f, -0.186035f, 0.111816f, -0.154297f, 0.123047f, -0.131592f, 0.134277f, -0.108887f,
-0.149902f, -0.0942383f, 0.165527f, -0.0795898f, 0.18457f, -0.0727539f, 0.203613f,
--0.065918f, 0.223633f, -0.065918f, 0.274414f, -0.065918f, 0.303711f, -0.10083f, 0.333008f,
--0.135742f, 0.333008f, -0.203125f, 0.333008f, -0.611816f, 0.200684f, -0.611816f,
-0.200684f, -0.687988f, 0.425781f, -0.687988f, 0.425781f, -0.205078f, 0.425781f, -0.155762f,
-0.412109f, -0.116211f, 0.398438f, -0.0766602f, 0.372314f, -0.048584f, 0.346191f,
--0.0205078f, 0.308594f, -0.00537109f, 0.270996f, 0.00976562f, 0.223145f, 0.00976562f,
-0.540039f, 0, 0.265137f, -0.332031f, 0.175293f, -0.263672f, 0.175293f, 0, 0.0820312f,
-0, 0.0820312f, -0.687988f, 0.175293f, -0.687988f, 0.175293f, -0.343262f, 0.506836f,
--0.687988f, 0.616699f, -0.687988f, 0.32373f, -0.38916f, 0.655762f, 0, 0.0820312f,
-0, 0.0820312f, -0.687988f, 0.175293f, -0.687988f, 0.175293f, -0.0761719f, 0.522949f,
--0.0761719f, 0.522949f, 0, 0.666992f, 0, 0.666992f, -0.458984f, 0.666992f, -0.483887f,
-0.66748f, -0.509766f, 0.667969f, -0.535645f, 0.668945f, -0.557129f, 0.669922f, -0.582031f,
-0.671387f, -0.605469f, 0.664551f, -0.580566f, 0.657227f, -0.556152f, 0.650879f, -0.535156f,
-0.643311f, -0.511475f, 0.635742f, -0.487793f, 0.628418f, -0.46875f, 0.450684f, 0,
-0.385254f, 0, 0.205078f, -0.46875f, 0.202148f, -0.476074f, 0.198975f, -0.48584f,
-0.195801f, -0.495605f, 0.192139f, -0.506592f, 0.188477f, -0.517578f, 0.184814f, -0.529053f,
-0.181152f, -0.540527f, 0.177734f, -0.551758f, 0.169434f, -0.577637f, 0.161621f, -0.605469f,
-0.162109f, -0.578125f, 0.163086f, -0.55127f, 0.164062f, -0.52832f, 0.164551f, -0.503174f,
-0.165039f, -0.478027f, 0.165039f, -0.458984f, 0.165039f, 0, 0.0820312f, 0, 0.0820312f,
--0.687988f, 0.20459f, -0.687988f, 0.387695f, -0.210938f, 0.391113f, -0.201172f, 0.395996f,
--0.185791f, 0.400879f, -0.17041f, 0.405273f, -0.154297f, 0.409668f, -0.138184f, 0.41333f,
--0.123779f, 0.416992f, -0.109375f, 0.418457f, -0.101562f, 0.419922f, -0.109375f,
-0.423828f, -0.124023f, 0.427734f, -0.138672f, 0.432861f, -0.154785f, 0.437988f, -0.170898f,
-0.442871f, -0.186035f, 0.447754f, -0.201172f, 0.45166f, -0.210938f, 0.631348f, -0.687988f,
-0.750977f, -0.687988f, 0.750977f, 0, 0.52832f, 0, 0.160156f, -0.585938f, 0.161133f,
--0.562012f, 0.162598f, -0.538574f, 0.163574f, -0.518555f, 0.164307f, -0.496338f,
-0.165039f, -0.474121f, 0.165039f, -0.457031f, 0.165039f, 0, 0.0820312f, 0, 0.0820312f,
--0.687988f, 0.19043f, -0.687988f, 0.5625f, -0.0981445f, 0.561035f, -0.12207f, 0.55957f,
--0.145996f, 0.558594f, -0.166504f, 0.557617f, -0.190674f, 0.556641f, -0.214844f,
-0.556641f, -0.236816f, 0.556641f, -0.687988f, 0.640625f, -0.687988f, 0.640625f, 0,
-0.72998f, -0.347168f, 0.72998f, -0.266602f, 0.706787f, -0.200684f, 0.683594f, -0.134766f,
-0.639648f, -0.0878906f, 0.595703f, -0.0410156f, 0.532227f, -0.015625f, 0.46875f,
-0.00976562f, 0.388184f, 0.00976562f, 0.303223f, 0.00976562f, 0.239258f, -0.0168457f,
-0.175293f, -0.043457f, 0.132812f, -0.0910645f, 0.090332f, -0.138672f, 0.0688477f,
--0.204102f, 0.0473633f, -0.269531f, 0.0473633f, -0.347168f, 0.0473633f, -0.427734f,
-0.0698242f, -0.492676f, 0.0922852f, -0.557617f, 0.135742f, -0.603271f, 0.179199f,
--0.648926f, 0.24292f, -0.673584f, 0.306641f, -0.698242f, 0.38916f, -0.698242f, 0.471191f,
--0.698242f, 0.534912f, -0.67334f, 0.598633f, -0.648438f, 0.641846f, -0.602539f, 0.685059f,
--0.556641f, 0.70752f, -0.491699f, 0.72998f, -0.426758f, 0.72998f, -0.347168f, 0.634766f,
--0.347168f, 0.634766f, -0.40918f, 0.618896f, -0.459961f, 0.603027f, -0.510742f, 0.572021f,
--0.546875f, 0.541016f, -0.583008f, 0.495117f, -0.602539f, 0.449219f, -0.62207f, 0.38916f,
--0.62207f, 0.327637f, -0.62207f, 0.28125f, -0.602539f, 0.234863f, -0.583008f, 0.203857f,
--0.546875f, 0.172852f, -0.510742f, 0.157471f, -0.459961f, 0.14209f, -0.40918f, 0.14209f,
--0.347168f, 0.14209f, -0.285156f, 0.157959f, -0.233643f, 0.173828f, -0.182129f, 0.204834f,
--0.144775f, 0.23584f, -0.107422f, 0.281982f, -0.0866699f, 0.328125f, -0.065918f,
-0.388184f, -0.065918f, 0.452637f, -0.065918f, 0.499268f, -0.0869141f, 0.545898f,
--0.10791f, 0.575928f, -0.145264f, 0.605957f, -0.182617f, 0.620361f, -0.234375f, 0.634766f,
--0.286133f, 0.634766f, -0.347168f, 0.614258f, -0.480957f, 0.614258f, -0.436035f,
-0.599365f, -0.397217f, 0.584473f, -0.358398f, 0.554932f, -0.329834f, 0.525391f, -0.30127f,
-0.480957f, -0.284668f, 0.436523f, -0.268066f, 0.377441f, -0.268066f, 0.175293f, -0.268066f,
-0.175293f, 0, 0.0820312f, 0, 0.0820312f, -0.687988f, 0.371582f, -0.687988f, 0.432617f,
--0.687988f, 0.478027f, -0.673096f, 0.523438f, -0.658203f, 0.553711f, -0.631104f,
-0.583984f, -0.604004f, 0.599121f, -0.565674f, 0.614258f, -0.527344f, 0.614258f, -0.480957f,
-0.520508f, -0.47998f, 0.520508f, -0.54541f, 0.480469f, -0.579346f, 0.44043f, -0.613281f,
-0.360352f, -0.613281f, 0.175293f, -0.613281f, 0.175293f, -0.341797f, 0.364258f, -0.341797f,
-0.444824f, -0.341797f, 0.482666f, -0.377441f, 0.520508f, -0.413086f, 0.520508f, -0.47998f,
-0.72998f, -0.347168f, 0.72998f, -0.274414f, 0.711182f, -0.214111f, 0.692383f, -0.153809f,
-0.656982f, -0.108398f, 0.621582f, -0.0629883f, 0.570068f, -0.0344238f, 0.518555f,
--0.00585938f, 0.453125f, 0.00292969f, 0.463379f, 0.0341797f, 0.476318f, 0.0561523f,
-0.489258f, 0.078125f, 0.505859f, 0.092041f, 0.522461f, 0.105957f, 0.542725f, 0.112549f,
-0.562988f, 0.119141f, 0.587891f, 0.119141f, 0.601562f, 0.119141f, 0.617188f, 0.117188f,
-0.632812f, 0.115234f, 0.644043f, 0.112793f, 0.644043f, 0.178223f, 0.625488f, 0.182617f,
-0.603271f, 0.185791f, 0.581055f, 0.188965f, 0.557129f, 0.188965f, 0.515137f, 0.188965f,
-0.483887f, 0.176514f, 0.452637f, 0.164062f, 0.428955f, 0.140869f, 0.405273f, 0.117676f,
-0.388184f, 0.0839844f, 0.371094f, 0.050293f, 0.35791f, 0.0078125f, 0.280762f, 0.00390625f,
-0.222412f, -0.0241699f, 0.164062f, -0.0522461f, 0.125244f, -0.0993652f, 0.0864258f,
--0.146484f, 0.0668945f, -0.209717f, 0.0473633f, -0.272949f, 0.0473633f, -0.347168f,
-0.0473633f, -0.427734f, 0.0698242f, -0.492676f, 0.0922852f, -0.557617f, 0.135742f,
--0.603271f, 0.179199f, -0.648926f, 0.24292f, -0.673584f, 0.306641f, -0.698242f, 0.38916f,
--0.698242f, 0.471191f, -0.698242f, 0.534912f, -0.67334f, 0.598633f, -0.648438f, 0.641846f,
--0.602539f, 0.685059f, -0.556641f, 0.70752f, -0.491699f, 0.72998f, -0.426758f, 0.72998f,
--0.347168f, 0.634766f, -0.347168f, 0.634766f, -0.40918f, 0.618896f, -0.459961f, 0.603027f,
--0.510742f, 0.572021f, -0.546875f, 0.541016f, -0.583008f, 0.495117f, -0.602539f,
-0.449219f, -0.62207f, 0.38916f, -0.62207f, 0.327637f, -0.62207f, 0.28125f, -0.602539f,
-0.234863f, -0.583008f, 0.203857f, -0.546875f, 0.172852f, -0.510742f, 0.157471f, -0.459961f,
-0.14209f, -0.40918f, 0.14209f, -0.347168f, 0.14209f, -0.285156f, 0.157959f, -0.233643f,
-0.173828f, -0.182129f, 0.204834f, -0.144775f, 0.23584f, -0.107422f, 0.281982f, -0.0866699f,
-0.328125f, -0.065918f, 0.388184f, -0.065918f, 0.452637f, -0.065918f, 0.499268f, -0.0869141f,
-0.545898f, -0.10791f, 0.575928f, -0.145264f, 0.605957f, -0.182617f, 0.620361f, -0.234375f,
-0.634766f, -0.286133f, 0.634766f, -0.347168f, 0.568359f, 0, 0.389648f, -0.285645f,
-0.175293f, -0.285645f, 0.175293f, 0, 0.0820312f, 0, 0.0820312f, -0.687988f, 0.405762f,
--0.687988f, 0.464355f, -0.687988f, 0.509521f, -0.674561f, 0.554688f, -0.661133f,
-0.585449f, -0.635742f, 0.616211f, -0.610352f, 0.632324f, -0.57373f, 0.648438f, -0.537109f,
-0.648438f, -0.491211f, 0.648438f, -0.458496f, 0.638916f, -0.426758f, 0.629395f, -0.39502f,
-0.608887f, -0.368652f, 0.588379f, -0.342285f, 0.556641f, -0.323242f, 0.524902f, -0.304199f,
-0.480469f, -0.296387f, 0.675781f, 0, 0.554688f, -0.490234f, 0.554688f, -0.521484f,
-0.543945f, -0.544434f, 0.533203f, -0.567383f, 0.512695f, -0.582764f, 0.492188f, -0.598145f,
-0.462891f, -0.605713f, 0.433594f, -0.613281f, 0.396484f, -0.613281f, 0.175293f, -0.613281f,
-0.175293f, -0.359375f, 0.400391f, -0.359375f, 0.44043f, -0.359375f, 0.469727f, -0.369385f,
-0.499023f, -0.379395f, 0.517822f, -0.396973f, 0.536621f, -0.414551f, 0.545654f, -0.438477f,
-0.554688f, -0.462402f, 0.554688f, -0.490234f, 0.621094f, -0.189941f, 0.621094f, -0.146484f,
-0.604248f, -0.109863f, 0.587402f, -0.0732422f, 0.552246f, -0.0466309f, 0.51709f,
--0.0200195f, 0.463623f, -0.00512695f, 0.410156f, 0.00976562f, 0.336914f, 0.00976562f,
-0.208496f, 0.00976562f, 0.136719f, -0.0351562f, 0.0649414f, -0.0800781f, 0.0454102f,
--0.165039f, 0.135742f, -0.183105f, 0.142578f, -0.15625f, 0.156738f, -0.134277f, 0.170898f,
--0.112305f, 0.195068f, -0.0964355f, 0.219238f, -0.0805664f, 0.254883f, -0.0717773f,
-0.290527f, -0.0629883f, 0.340332f, -0.0629883f, 0.381836f, -0.0629883f, 0.416504f,
--0.0700684f, 0.451172f, -0.0771484f, 0.476074f, -0.0917969f, 0.500977f, -0.106445f,
-0.514893f, -0.129639f, 0.528809f, -0.152832f, 0.528809f, -0.185059f, 0.528809f, -0.21875f,
-0.513428f, -0.239746f, 0.498047f, -0.260742f, 0.470215f, -0.274414f, 0.442383f, -0.288086f,
-0.403809f, -0.297363f, 0.365234f, -0.306641f, 0.318359f, -0.317383f, 0.289551f, -0.32373f,
-0.260498f, -0.331299f, 0.231445f, -0.338867f, 0.204834f, -0.349365f, 0.178223f, -0.359863f,
-0.154785f, -0.374023f, 0.131348f, -0.388184f, 0.114258f, -0.407959f, 0.097168f, -0.427734f,
-0.0874023f, -0.453857f, 0.0776367f, -0.47998f, 0.0776367f, -0.51416f, 0.0776367f,
--0.562988f, 0.0974121f, -0.5979f, 0.117188f, -0.632812f, 0.152344f, -0.655273f, 0.1875f,
--0.677734f, 0.235352f, -0.687988f, 0.283203f, -0.698242f, 0.338867f, -0.698242f,
-0.402832f, -0.698242f, 0.448242f, -0.688232f, 0.493652f, -0.678223f, 0.524902f, -0.658203f,
-0.556152f, -0.638184f, 0.574951f, -0.608643f, 0.59375f, -0.579102f, 0.60498f, -0.540039f,
-0.513184f, -0.523926f, 0.506348f, -0.548828f, 0.493408f, -0.568359f, 0.480469f, -0.587891f,
-0.459473f, -0.601074f, 0.438477f, -0.614258f, 0.408447f, -0.621094f, 0.378418f, -0.62793f,
-0.337891f, -0.62793f, 0.290039f, -0.62793f, 0.257568f, -0.619385f, 0.225098f, -0.61084f,
-0.205322f, -0.596191f, 0.185547f, -0.581543f, 0.177002f, -0.561768f, 0.168457f, -0.541992f,
-0.168457f, -0.519043f, 0.168457f, -0.488281f, 0.183838f, -0.468506f, 0.199219f, -0.44873f,
-0.225586f, -0.435547f, 0.251953f, -0.422363f, 0.286621f, -0.413574f, 0.321289f, -0.404785f,
-0.360352f, -0.395996f, 0.39209f, -0.388672f, 0.423584f, -0.381104f, 0.455078f, -0.373535f,
-0.483887f, -0.363037f, 0.512695f, -0.352539f, 0.537842f, -0.338379f, 0.562988f, -0.324219f,
-0.581543f, -0.303711f, 0.600098f, -0.283203f, 0.610596f, -0.255371f, 0.621094f, -0.227539f,
-0.621094f, -0.189941f, 0.351562f, -0.611816f, 0.351562f, 0, 0.258789f, 0, 0.258789f,
--0.611816f, 0.0224609f, -0.611816f, 0.0224609f, -0.687988f, 0.587891f, -0.687988f,
-0.587891f, -0.611816f, 0.381836f, 0, 0.285156f, 0, 0.00439453f, -0.687988f, 0.102539f,
--0.687988f, 0.292969f, -0.203613f, 0.300293f, -0.181641f, 0.307617f, -0.159912f,
-0.314941f, -0.138184f, 0.320801f, -0.121094f, 0.327637f, -0.101074f, 0.333984f, -0.0820312f,
-0.339844f, -0.100098f, 0.34668f, -0.120117f, 0.352539f, -0.137207f, 0.359619f, -0.158691f,
-0.366699f, -0.180176f, 0.375f, -0.203613f, 0.564453f, -0.687988f, 0.662598f, -0.687988f,
-0.737793f, 0, 0.626465f, 0, 0.507324f, -0.437012f, 0.501953f, -0.455566f, 0.49585f,
--0.480957f, 0.489746f, -0.506348f, 0.484863f, -0.529297f, 0.479004f, -0.556152f,
-0.473145f, -0.583984f, 0.466797f, -0.555664f, 0.460938f, -0.528809f, 0.455566f, -0.505371f,
-0.449707f, -0.480469f, 0.443848f, -0.455566f, 0.438477f, -0.437012f, 0.318359f, 0,
-0.207031f, 0, 0.00439453f, -0.687988f, 0.101562f, -0.687988f, 0.225098f, -0.250977f,
-0.233398f, -0.220215f, 0.240967f, -0.189941f, 0.248535f, -0.159668f, 0.253906f, -0.135742f,
-0.260254f, -0.107422f, 0.265625f, -0.0820312f, 0.272949f, -0.115723f, 0.280762f,
--0.148438f, 0.28418f, -0.162109f, 0.287598f, -0.177246f, 0.291016f, -0.192383f, 0.294678f,
--0.207031f, 0.29834f, -0.22168f, 0.302002f, -0.235107f, 0.305664f, -0.248535f, 0.308594f,
--0.259766f, 0.428223f, -0.687988f, 0.517578f, -0.687988f, 0.637207f, -0.259766f,
-0.640137f, -0.248535f, 0.643799f, -0.235107f, 0.647461f, -0.22168f, 0.651123f, -0.207275f,
-0.654785f, -0.192871f, 0.658203f, -0.177734f, 0.661621f, -0.162598f, 0.665039f, -0.148926f,
-0.672852f, -0.116211f, 0.680176f, -0.0820312f, 0.680664f, -0.0820312f, 0.68457f,
--0.098877f, 0.688477f, -0.115723f, 0.694336f, -0.141113f, 0.700195f, -0.166504f,
-0.707275f, -0.196045f, 0.714355f, -0.225586f, 0.72168f, -0.250977f, 0.843262f, -0.687988f,
-0.94043f, -0.687988f, 0.542969f, 0, 0.336426f, -0.300781f, 0.125488f, 0, 0.0224609f,
-0, 0.28418f, -0.357422f, 0.0424805f, -0.687988f, 0.145508f, -0.687988f, 0.336914f,
--0.417969f, 0.522949f, -0.687988f, 0.625977f, -0.687988f, 0.390625f, -0.36084f, 0.645996f,
-0, 0.379395f, -0.285156f, 0.379395f, 0, 0.286621f, 0, 0.286621f, -0.285156f, 0.0219727f,
--0.687988f, 0.124512f, -0.687988f, 0.333984f, -0.360352f, 0.54248f, -0.687988f, 0.64502f,
--0.687988f, 0.57959f, 0, 0.0317383f, 0, 0.0317383f, -0.0698242f, 0.450684f, -0.611816f,
-0.0673828f, -0.611816f, 0.0673828f, -0.687988f, 0.556641f, -0.687988f, 0.556641f,
--0.620117f, 0.137695f, -0.0761719f, 0.57959f, -0.0761719f, 0.0712891f, 0.20752f,
-0.0712891f, -0.724609f, 0.27002f, -0.724609f, 0.27002f, -0.661621f, 0.15625f, -0.661621f,
-0.15625f, 0.144531f, 0.27002f, 0.144531f, 0.27002f, 0.20752f, 0.19873f, 0.00976562f,
-0, -0.724609f, 0.0771484f, -0.724609f, 0.277832f, 0.00976562f, 0.0078125f, 0.20752f,
-0.0078125f, 0.144531f, 0.121582f, 0.144531f, 0.121582f, -0.661621f, 0.0078125f, -0.661621f,
-0.0078125f, -0.724609f, 0.206543f, -0.724609f, 0.206543f, 0.20752f, 0.384277f, -0.328613f,
-0.233398f, -0.637695f, 0.0839844f, -0.328613f, 0.00488281f, -0.328613f, 0.18457f,
--0.687988f, 0.283691f, -0.687988f, 0.464355f, -0.328613f, 0.212891f, -0.586426f,
-0.0517578f, -0.722168f, 0.0517578f, -0.736328f, 0.152832f, -0.736328f, 0.258789f,
--0.596191f, 0.258789f, -0.586426f, 0.202148f, 0.00976562f, 0.122559f, 0.00976562f,
-0.0825195f, -0.0322266f, 0.0424805f, -0.0742188f, 0.0424805f, -0.147461f, 0.0424805f,
--0.199707f, 0.0622559f, -0.233154f, 0.0820312f, -0.266602f, 0.114014f, -0.285645f,
-0.145996f, -0.304688f, 0.187012f, -0.312012f, 0.228027f, -0.319336f, 0.270508f, -0.320312f,
-0.38916f, -0.322266f, 0.38916f, -0.351074f, 0.38916f, -0.383789f, 0.382324f, -0.406738f,
-0.375488f, -0.429688f, 0.361328f, -0.443848f, 0.347168f, -0.458008f, 0.325928f, -0.4646f,
-0.304688f, -0.471191f, 0.275879f, -0.471191f, 0.250488f, -0.471191f, 0.22998f, -0.467529f,
-0.209473f, -0.463867f, 0.194336f, -0.454346f, 0.179199f, -0.444824f, 0.169922f, -0.428467f,
-0.160645f, -0.412109f, 0.157715f, -0.387207f, 0.065918f, -0.395508f, 0.0708008f,
--0.426758f, 0.0844727f, -0.452881f, 0.0981445f, -0.479004f, 0.123291f, -0.498047f,
-0.148438f, -0.51709f, 0.186279f, -0.527588f, 0.224121f, -0.538086f, 0.277832f, -0.538086f,
-0.377441f, -0.538086f, 0.427734f, -0.492432f, 0.478027f, -0.446777f, 0.478027f, -0.360352f,
-0.478027f, -0.132812f, 0.478027f, -0.09375f, 0.488281f, -0.0739746f, 0.498535f, -0.0541992f,
-0.527344f, -0.0541992f, 0.534668f, -0.0541992f, 0.541992f, -0.0551758f, 0.549316f,
--0.0561523f, 0.556152f, -0.0576172f, 0.556152f, -0.00292969f, 0.539551f, 0.000976562f,
-0.523193f, 0.00292969f, 0.506836f, 0.00488281f, 0.488281f, 0.00488281f, 0.463379f,
-0.00488281f, 0.445557f, -0.00170898f, 0.427734f, -0.00830078f, 0.416504f, -0.0217285f,
-0.405273f, -0.0351562f, 0.399414f, -0.0549316f, 0.393555f, -0.074707f, 0.39209f,
--0.101074f, 0.38916f, -0.101074f, 0.375f, -0.0756836f, 0.358154f, -0.0551758f, 0.341309f,
--0.034668f, 0.318848f, -0.0202637f, 0.296387f, -0.00585938f, 0.267822f, 0.00195312f,
-0.239258f, 0.00976562f, 0.202148f, 0.00976562f, 0.222168f, -0.0561523f, 0.26416f,
--0.0561523f, 0.295654f, -0.0715332f, 0.327148f, -0.0869141f, 0.3479f, -0.11084f,
-0.368652f, -0.134766f, 0.378906f, -0.163086f, 0.38916f, -0.191406f, 0.38916f, -0.217285f,
-0.38916f, -0.260742f, 0.292969f, -0.258789f, 0.260742f, -0.258301f, 0.231689f, -0.25415f,
-0.202637f, -0.25f, 0.180664f, -0.237793f, 0.158691f, -0.225586f, 0.145752f, -0.203613f,
-0.132812f, -0.181641f, 0.132812f, -0.145996f, 0.132812f, -0.103027f, 0.156006f, -0.0795898f,
-0.179199f, -0.0561523f, 0.222168f, -0.0561523f, 0.51416f, -0.266602f, 0.51416f, 0.00976562f,
-0.319824f, 0.00976562f, 0.259766f, 0.00976562f, 0.219971f, -0.0119629f, 0.180176f,
--0.0336914f, 0.155273f, -0.0820312f, 0.154297f, -0.0820312f, 0.154297f, -0.0693359f,
-0.153564f, -0.0556641f, 0.152832f, -0.0419922f, 0.1521f, -0.0302734f, 0.151367f,
--0.0185547f, 0.150635f, -0.0102539f, 0.149902f, -0.00195312f, 0.149414f, 0, 0.0644531f,
-0, 0.0649414f, -0.00439453f, 0.0654297f, -0.0148926f, 0.065918f, -0.0253906f, 0.0664062f,
--0.0400391f, 0.0668945f, -0.0546875f, 0.0671387f, -0.0722656f, 0.0673828f, -0.0898438f,
-0.0673828f, -0.108887f, 0.0673828f, -0.724609f, 0.155273f, -0.724609f, 0.155273f,
--0.518066f, 0.155273f, -0.503418f, 0.155029f, -0.48999f, 0.154785f, -0.476562f, 0.154297f,
--0.466309f, 0.153809f, -0.454102f, 0.15332f, -0.443359f, 0.155273f, -0.443359f, 0.179688f,
--0.494141f, 0.219971f, -0.516113f, 0.260254f, -0.538086f, 0.319824f, -0.538086f,
-0.419922f, -0.538086f, 0.467041f, -0.470703f, 0.51416f, -0.40332f, 0.51416f, -0.266602f,
-0.421875f, -0.263672f, 0.421875f, -0.318359f, 0.415039f, -0.357422f, 0.408203f, -0.396484f,
-0.393066f, -0.421631f, 0.37793f, -0.446777f, 0.354492f, -0.458496f, 0.331055f, -0.470215f,
-0.297363f, -0.470215f, 0.262695f, -0.470215f, 0.236084f, -0.458984f, 0.209473f, -0.447754f,
-0.19165f, -0.422852f, 0.173828f, -0.397949f, 0.164551f, -0.357422f, 0.155273f, -0.316895f,
-0.155273f, -0.258301f, 0.155273f, -0.20166f, 0.164551f, -0.163086f, 0.173828f, -0.124512f,
-0.19165f, -0.100342f, 0.209473f, -0.0761719f, 0.23584f, -0.0656738f, 0.262207f, -0.0551758f,
-0.296387f, -0.0551758f, 0.328613f, -0.0551758f, 0.352051f, -0.0664062f, 0.375488f,
--0.0776367f, 0.391113f, -0.102539f, 0.406738f, -0.127441f, 0.414307f, -0.167236f,
-0.421875f, -0.207031f, 0.421875f, -0.263672f, 0.134277f, -0.266602f, 0.134277f, -0.221191f,
-0.140869f, -0.183105f, 0.147461f, -0.14502f, 0.163086f, -0.117432f, 0.178711f, -0.0898438f,
-0.204346f, -0.074707f, 0.22998f, -0.0595703f, 0.267578f, -0.0595703f, 0.314453f,
--0.0595703f, 0.345947f, -0.0849609f, 0.377441f, -0.110352f, 0.384766f, -0.163086f,
-0.473633f, -0.157227f, 0.469238f, -0.124512f, 0.45459f, -0.0942383f, 0.439941f, -0.0639648f,
-0.414795f, -0.0410156f, 0.389648f, -0.0180664f, 0.353516f, -0.00415039f, 0.317383f,
-0.00976562f, 0.27002f, 0.00976562f, 0.208008f, 0.00976562f, 0.164551f, -0.0112305f,
-0.121094f, -0.0322266f, 0.0939941f, -0.0690918f, 0.0668945f, -0.105957f, 0.0546875f,
--0.156006f, 0.0424805f, -0.206055f, 0.0424805f, -0.264648f, 0.0424805f, -0.317871f,
-0.0512695f, -0.358643f, 0.0600586f, -0.399414f, 0.0759277f, -0.429932f, 0.0917969f,
--0.460449f, 0.113281f, -0.481201f, 0.134766f, -0.501953f, 0.159912f, -0.514404f,
-0.185059f, -0.526855f, 0.212891f, -0.532471f, 0.240723f, -0.538086f, 0.269043f, -0.538086f,
-0.313477f, -0.538086f, 0.348145f, -0.525879f, 0.382812f, -0.513672f, 0.407959f, -0.492432f,
-0.433105f, -0.471191f, 0.44873f, -0.442383f, 0.464355f, -0.413574f, 0.470703f, -0.380371f,
-0.380371f, -0.373535f, 0.373535f, -0.41748f, 0.345703f, -0.443359f, 0.317871f, -0.469238f,
-0.266602f, -0.469238f, 0.229004f, -0.469238f, 0.203857f, -0.456787f, 0.178711f, -0.444336f,
-0.163086f, -0.419189f, 0.147461f, -0.394043f, 0.140869f, -0.355957f, 0.134277f, -0.317871f,
-0.134277f, -0.266602f, 0.400879f, -0.0849609f, 0.376465f, -0.0341797f, 0.336182f,
--0.012207f, 0.295898f, 0.00976562f, 0.236328f, 0.00976562f, 0.13623f, 0.00976562f,
-0.0891113f, -0.0576172f, 0.0419922f, -0.125f, 0.0419922f, -0.261719f, 0.0419922f,
--0.538086f, 0.236328f, -0.538086f, 0.296387f, -0.538086f, 0.336426f, -0.516113f,
-0.376465f, -0.494141f, 0.400879f, -0.446289f, 0.401855f, -0.446289f, 0.401855f, -0.451172f,
-0.401611f, -0.46167f, 0.401367f, -0.472168f, 0.401123f, -0.483643f, 0.400879f, -0.495117f,
-0.400879f, -0.505371f, 0.400879f, -0.515625f, 0.400879f, -0.52002f, 0.400879f, -0.724609f,
-0.48877f, -0.724609f, 0.48877f, -0.108887f, 0.48877f, -0.0898438f, 0.489014f, -0.0722656f,
-0.489258f, -0.0546875f, 0.489746f, -0.0400391f, 0.490234f, -0.0253906f, 0.490723f,
--0.0148926f, 0.491211f, -0.00439453f, 0.491699f, 0, 0.407715f, 0, 0.406738f, -0.00488281f,
-0.406006f, -0.013916f, 0.405273f, -0.0229492f, 0.404541f, -0.034668f, 0.403809f,
--0.0463867f, 0.40332f, -0.0593262f, 0.402832f, -0.0722656f, 0.402832f, -0.0849609f,
-0.134277f, -0.264648f, 0.134277f, -0.209961f, 0.141113f, -0.170898f, 0.147949f, -0.131836f,
-0.163086f, -0.106689f, 0.178223f, -0.081543f, 0.20166f, -0.0698242f, 0.225098f, -0.0581055f,
-0.258789f, -0.0581055f, 0.293457f, -0.0581055f, 0.320068f, -0.0693359f, 0.34668f,
--0.0805664f, 0.364502f, -0.105713f, 0.382324f, -0.130859f, 0.391602f, -0.171387f,
-0.400879f, -0.211914f, 0.400879f, -0.270508f, 0.400879f, -0.32666f, 0.391602f, -0.365479f,
-0.382324f, -0.404297f, 0.364258f, -0.428223f, 0.346191f, -0.452148f, 0.320068f, -0.462646f,
-0.293945f, -0.473145f, 0.259766f, -0.473145f, 0.227539f, -0.473145f, 0.204102f, -0.461914f,
-0.180664f, -0.450684f, 0.165039f, -0.425781f, 0.149414f, -0.400879f, 0.141846f, -0.361084f,
-0.134277f, -0.321289f, 0.134277f, -0.264648f, 0.134766f, -0.245605f, 0.134766f, -0.204102f,
-0.143311f, -0.169189f, 0.151855f, -0.134277f, 0.169678f, -0.109131f, 0.1875f, -0.0839844f,
-0.215332f, -0.0700684f, 0.243164f, -0.0561523f, 0.282227f, -0.0561523f, 0.339355f,
--0.0561523f, 0.373779f, -0.0791016f, 0.408203f, -0.102051f, 0.42041f, -0.137207f,
-0.497559f, -0.115234f, 0.489258f, -0.0932617f, 0.474365f, -0.0710449f, 0.459473f,
--0.0488281f, 0.43457f, -0.0310059f, 0.409668f, -0.0131836f, 0.372314f, -0.00170898f,
-0.334961f, 0.00976562f, 0.282227f, 0.00976562f, 0.165039f, 0.00976562f, 0.10376f,
--0.0600586f, 0.0424805f, -0.129883f, 0.0424805f, -0.267578f, 0.0424805f, -0.341797f,
-0.0610352f, -0.393311f, 0.0795898f, -0.444824f, 0.111816f, -0.477051f, 0.144043f,
--0.509277f, 0.187012f, -0.523682f, 0.22998f, -0.538086f, 0.278809f, -0.538086f, 0.345215f,
--0.538086f, 0.389893f, -0.516602f, 0.43457f, -0.495117f, 0.46167f, -0.457275f, 0.48877f,
--0.419434f, 0.500244f, -0.368164f, 0.511719f, -0.316895f, 0.511719f, -0.257324f,
-0.511719f, -0.245605f, 0.420898f, -0.312988f, 0.413574f, -0.396484f, 0.378418f, -0.434814f,
-0.343262f, -0.473145f, 0.277344f, -0.473145f, 0.255371f, -0.473145f, 0.231201f, -0.466064f,
-0.207031f, -0.458984f, 0.186523f, -0.440918f, 0.166016f, -0.422852f, 0.151855f, -0.391846f,
-0.137695f, -0.36084f, 0.135742f, -0.312988f, 0.17627f, -0.464355f, 0.17627f, 0, 0.0883789f,
-0, 0.0883789f, -0.464355f, 0.0141602f, -0.464355f, 0.0141602f, -0.52832f, 0.0883789f,
--0.52832f, 0.0883789f, -0.587891f, 0.0883789f, -0.616699f, 0.09375f, -0.641357f,
-0.0991211f, -0.666016f, 0.113525f, -0.684326f, 0.12793f, -0.702637f, 0.152832f, -0.713135f,
-0.177734f, -0.723633f, 0.217285f, -0.723633f, 0.23291f, -0.723633f, 0.249756f, -0.722168f,
-0.266602f, -0.720703f, 0.279297f, -0.717773f, 0.279297f, -0.650879f, 0.270996f, -0.652344f,
-0.26001f, -0.653564f, 0.249023f, -0.654785f, 0.240234f, -0.654785f, 0.220703f, -0.654785f,
-0.208252f, -0.649414f, 0.195801f, -0.644043f, 0.188721f, -0.634033f, 0.181641f, -0.624023f,
-0.178955f, -0.609375f, 0.17627f, -0.594727f, 0.17627f, -0.575684f, 0.17627f, -0.52832f,
-0.279297f, -0.52832f, 0.279297f, -0.464355f, 0.267578f, 0.20752f, 0.222168f, 0.20752f,
-0.187012f, 0.198242f, 0.151855f, 0.188965f, 0.126953f, 0.171631f, 0.102051f, 0.154297f,
-0.0864258f, 0.130371f, 0.0708008f, 0.106445f, 0.0639648f, 0.0771484f, 0.152344f,
-0.0644531f, 0.161133f, 0.101074f, 0.191162f, 0.12085f, 0.221191f, 0.140625f, 0.27002f,
-0.140625f, 0.299805f, 0.140625f, 0.324219f, 0.132324f, 0.348633f, 0.124023f, 0.365723f,
-0.105713f, 0.382812f, 0.0874023f, 0.39209f, 0.0581055f, 0.401367f, 0.0288086f, 0.401367f,
--0.0131836f, 0.401367f, -0.0981445f, 0.400391f, -0.0981445f, 0.390625f, -0.078125f,
-0.376221f, -0.0598145f, 0.361816f, -0.0415039f, 0.341064f, -0.0273438f, 0.320312f,
--0.0131836f, 0.292969f, -0.00463867f, 0.265625f, 0.00390625f, 0.230469f, 0.00390625f,
-0.180176f, 0.00390625f, 0.144287f, -0.0129395f, 0.108398f, -0.0297852f, 0.0856934f,
--0.0634766f, 0.0629883f, -0.097168f, 0.0524902f, -0.147217f, 0.0419922f, -0.197266f,
-0.0419922f, -0.263184f, 0.0419922f, -0.32666f, 0.0524902f, -0.377441f, 0.0629883f,
--0.428223f, 0.0866699f, -0.463623f, 0.110352f, -0.499023f, 0.148193f, -0.517822f,
-0.186035f, -0.536621f, 0.240234f, -0.536621f, 0.296387f, -0.536621f, 0.337646f, -0.510986f,
-0.378906f, -0.485352f, 0.401367f, -0.437988f, 0.402344f, -0.437988f, 0.402344f, -0.450195f,
-0.403076f, -0.465332f, 0.403809f, -0.480469f, 0.404541f, -0.493896f, 0.405273f, -0.507324f,
-0.40625f, -0.51709f, 0.407227f, -0.526855f, 0.408203f, -0.52832f, 0.491699f, -0.52832f,
-0.491211f, -0.523926f, 0.490723f, -0.513428f, 0.490234f, -0.50293f, 0.489746f, -0.488281f,
-0.489258f, -0.473633f, 0.489014f, -0.455811f, 0.48877f, -0.437988f, 0.48877f, -0.418945f,
-0.48877f, -0.0151367f, 0.48877f, 0.0957031f, 0.434326f, 0.151611f, 0.379883f, 0.20752f,
-0.267578f, 0.20752f, 0.401367f, -0.26416f, 0.401367f, -0.319336f, 0.389404f, -0.358643f,
-0.377441f, -0.397949f, 0.35791f, -0.422852f, 0.338379f, -0.447754f, 0.313232f, -0.459473f,
-0.288086f, -0.471191f, 0.261719f, -0.471191f, 0.228027f, -0.471191f, 0.203857f, -0.459473f,
-0.179688f, -0.447754f, 0.163818f, -0.422607f, 0.147949f, -0.397461f, 0.140381f, -0.358154f,
-0.132812f, -0.318848f, 0.132812f, -0.26416f, 0.132812f, -0.207031f, 0.140381f, -0.168213f,
-0.147949f, -0.129395f, 0.163574f, -0.105469f, 0.179199f, -0.081543f, 0.203125f, -0.0712891f,
-0.227051f, -0.0610352f, 0.260254f, -0.0610352f, 0.286621f, -0.0610352f, 0.311768f,
--0.0722656f, 0.336914f, -0.0834961f, 0.356934f, -0.10791f, 0.376953f, -0.132324f,
-0.38916f, -0.170898f, 0.401367f, -0.209473f, 0.401367f, -0.26416f, 0.0668945f, -0.640625f,
-0.0668945f, -0.724609f, 0.154785f, -0.724609f, 0.154785f, -0.640625f, 0.0668945f,
-0, 0.0668945f, -0.52832f, 0.154785f, -0.52832f, 0.154785f, 0, 0.0673828f, 0, 0.0673828f,
--0.724609f, 0.155273f, -0.724609f, 0.155273f, 0, 0.375f, 0, 0.375f, -0.334961f, 0.375f,
--0.373535f, 0.370117f, -0.399414f, 0.365234f, -0.425293f, 0.35376f, -0.441162f, 0.342285f,
--0.457031f, 0.32373f, -0.463623f, 0.305176f, -0.470215f, 0.27832f, -0.470215f, 0.250488f,
--0.470215f, 0.228027f, -0.459229f, 0.205566f, -0.448242f, 0.189697f, -0.42749f, 0.173828f,
--0.406738f, 0.165283f, -0.376221f, 0.156738f, -0.345703f, 0.156738f, -0.306152f,
-0.156738f, 0, 0.0693359f, 0, 0.0693359f, -0.415527f, 0.0693359f, -0.432129f, 0.0690918f,
--0.450439f, 0.0688477f, -0.46875f, 0.0683594f, -0.485107f, 0.0678711f, -0.501465f,
-0.0673828f, -0.513184f, 0.0668945f, -0.524902f, 0.0664062f, -0.52832f, 0.149414f,
--0.52832f, 0.149902f, -0.525879f, 0.150391f, -0.515137f, 0.150879f, -0.504395f, 0.151611f,
--0.490479f, 0.152344f, -0.476562f, 0.152832f, -0.462158f, 0.15332f, -0.447754f, 0.15332f,
--0.437988f, 0.154785f, -0.437988f, 0.166504f, -0.460938f, 0.180176f, -0.479492f,
-0.193848f, -0.498047f, 0.212158f, -0.510986f, 0.230469f, -0.523926f, 0.25415f, -0.531006f,
-0.277832f, -0.538086f, 0.309082f, -0.538086f, 0.369141f, -0.538086f, 0.404053f, -0.51416f,
-0.438965f, -0.490234f, 0.452637f, -0.437988f, 0.454102f, -0.437988f, 0.46582f, -0.460938f,
-0.480469f, -0.479492f, 0.495117f, -0.498047f, 0.514648f, -0.510986f, 0.53418f, -0.523926f,
-0.558594f, -0.531006f, 0.583008f, -0.538086f, 0.614258f, -0.538086f, 0.654297f, -0.538086f,
-0.68335f, -0.527344f, 0.712402f, -0.516602f, 0.730957f, -0.494141f, 0.749512f, -0.47168f,
-0.758301f, -0.436279f, 0.76709f, -0.400879f, 0.76709f, -0.352051f, 0.76709f, 0, 0.680176f,
-0, 0.680176f, -0.334961f, 0.680176f, -0.373535f, 0.675293f, -0.399414f, 0.67041f,
--0.425293f, 0.658936f, -0.441162f, 0.647461f, -0.457031f, 0.628906f, -0.463623f,
-0.610352f, -0.470215f, 0.583496f, -0.470215f, 0.555664f, -0.470215f, 0.533203f, -0.459717f,
-0.510742f, -0.449219f, 0.494873f, -0.428711f, 0.479004f, -0.408203f, 0.470459f, -0.377441f,
-0.461914f, -0.34668f, 0.461914f, -0.306152f, 0.461914f, 0, 0.402832f, 0, 0.402832f,
--0.334961f, 0.402832f, -0.373535f, 0.397217f, -0.399414f, 0.391602f, -0.425293f,
-0.378906f, -0.441162f, 0.366211f, -0.457031f, 0.345459f, -0.463623f, 0.324707f, -0.470215f,
-0.293945f, -0.470215f, 0.262695f, -0.470215f, 0.237549f, -0.459229f, 0.212402f, -0.448242f,
-0.19458f, -0.42749f, 0.176758f, -0.406738f, 0.166992f, -0.376221f, 0.157227f, -0.345703f,
-0.157227f, -0.306152f, 0.157227f, 0, 0.0693359f, 0, 0.0693359f, -0.415527f, 0.0693359f,
--0.432129f, 0.0690918f, -0.450439f, 0.0688477f, -0.46875f, 0.0683594f, -0.485107f,
-0.0678711f, -0.501465f, 0.0673828f, -0.513184f, 0.0668945f, -0.524902f, 0.0664062f,
--0.52832f, 0.149414f, -0.52832f, 0.149902f, -0.525879f, 0.150391f, -0.515137f, 0.150879f,
--0.504395f, 0.151611f, -0.490479f, 0.152344f, -0.476562f, 0.152832f, -0.462158f,
-0.15332f, -0.447754f, 0.15332f, -0.437988f, 0.154785f, -0.437988f, 0.16748f, -0.460938f,
-0.182617f, -0.479492f, 0.197754f, -0.498047f, 0.217773f, -0.510986f, 0.237793f, -0.523926f,
-0.263672f, -0.531006f, 0.289551f, -0.538086f, 0.32373f, -0.538086f, 0.367676f, -0.538086f,
-0.399414f, -0.527344f, 0.431152f, -0.516602f, 0.45166f, -0.494141f, 0.472168f, -0.47168f,
-0.481689f, -0.436279f, 0.491211f, -0.400879f, 0.491211f, -0.352051f, 0.491211f, 0,
-0.51416f, -0.264648f, 0.51416f, -0.125977f, 0.453125f, -0.0581055f, 0.39209f, 0.00976562f,
-0.275879f, 0.00976562f, 0.220703f, 0.00976562f, 0.177246f, -0.00683594f, 0.133789f,
--0.0234375f, 0.10376f, -0.0576172f, 0.0737305f, -0.0917969f, 0.0578613f, -0.143311f,
-0.0419922f, -0.194824f, 0.0419922f, -0.264648f, 0.0419922f, -0.538086f, 0.278809f,
--0.538086f, 0.340332f, -0.538086f, 0.38501f, -0.520996f, 0.429688f, -0.503906f, 0.458252f,
--0.469727f, 0.486816f, -0.435547f, 0.500488f, -0.384277f, 0.51416f, -0.333008f, 0.51416f,
--0.264648f, 0.421875f, -0.264648f, 0.421875f, -0.326172f, 0.412354f, -0.366211f,
-0.402832f, -0.40625f, 0.384521f, -0.430176f, 0.366211f, -0.454102f, 0.339844f, -0.463623f,
-0.313477f, -0.473145f, 0.280273f, -0.473145f, 0.246582f, -0.473145f, 0.219482f, -0.463135f,
-0.192383f, -0.453125f, 0.17334f, -0.428955f, 0.154297f, -0.404785f, 0.144287f, -0.364746f,
-0.134277f, -0.324707f, 0.134277f, -0.264648f, 0.134277f, -0.203125f, 0.14502f, -0.162842f,
-0.155762f, -0.122559f, 0.174561f, -0.0986328f, 0.193359f, -0.074707f, 0.218994f,
--0.0649414f, 0.244629f, -0.0551758f, 0.274902f, -0.0551758f, 0.308594f, -0.0551758f,
-0.335938f, -0.0646973f, 0.363281f, -0.0742188f, 0.382324f, -0.0981445f, 0.401367f,
--0.12207f, 0.411621f, -0.162598f, 0.421875f, -0.203125f, 0.421875f, -0.264648f, 0.51416f,
--0.266602f, 0.51416f, -0.206543f, 0.504395f, -0.155762f, 0.494629f, -0.10498f, 0.471924f,
--0.0683594f, 0.449219f, -0.0317383f, 0.411865f, -0.0109863f, 0.374512f, 0.00976562f,
-0.319824f, 0.00976562f, 0.263184f, 0.00976562f, 0.220703f, -0.0117188f, 0.178223f,
--0.0332031f, 0.155762f, -0.0820312f, 0.15332f, -0.0820312f, 0.153809f, -0.0810547f,
-0.154053f, -0.0732422f, 0.154297f, -0.0654297f, 0.154541f, -0.0537109f, 0.154785f,
--0.0419922f, 0.155029f, -0.0275879f, 0.155273f, -0.0131836f, 0.155273f, 0.000976562f,
-0.155273f, 0.20752f, 0.0673828f, 0.20752f, 0.0673828f, -0.42041f, 0.0673828f, -0.439453f,
-0.0671387f, -0.457031f, 0.0668945f, -0.474609f, 0.0664062f, -0.489014f, 0.065918f,
--0.503418f, 0.0654297f, -0.513672f, 0.0649414f, -0.523926f, 0.0644531f, -0.52832f,
-0.149414f, -0.52832f, 0.149902f, -0.526855f, 0.150635f, -0.518066f, 0.151367f, -0.509277f,
-0.1521f, -0.496826f, 0.152832f, -0.484375f, 0.153564f, -0.470215f, 0.154297f, -0.456055f,
-0.154297f, -0.443359f, 0.15625f, -0.443359f, 0.168457f, -0.46875f, 0.184082f, -0.486572f,
-0.199707f, -0.504395f, 0.219727f, -0.515869f, 0.239746f, -0.527344f, 0.264404f, -0.532471f,
-0.289062f, -0.537598f, 0.319824f, -0.537598f, 0.374512f, -0.537598f, 0.411865f, -0.518066f,
-0.449219f, -0.498535f, 0.471924f, -0.463135f, 0.494629f, -0.427734f, 0.504395f, -0.377686f,
-0.51416f, -0.327637f, 0.51416f, -0.266602f, 0.421875f, -0.264648f, 0.421875f, -0.313477f,
-0.416016f, -0.351562f, 0.410156f, -0.389648f, 0.395752f, -0.416016f, 0.381348f, -0.442383f,
-0.357422f, -0.456055f, 0.333496f, -0.469727f, 0.297363f, -0.469727f, 0.268066f, -0.469727f,
-0.242188f, -0.461426f, 0.216309f, -0.453125f, 0.197021f, -0.429688f, 0.177734f, -0.40625f,
-0.166504f, -0.36499f, 0.155273f, -0.32373f, 0.155273f, -0.257812f, 0.155273f, -0.20166f,
-0.164551f, -0.162842f, 0.173828f, -0.124023f, 0.19165f, -0.100098f, 0.209473f, -0.0761719f,
-0.23584f, -0.0656738f, 0.262207f, -0.0551758f, 0.296387f, -0.0551758f, 0.333008f,
--0.0551758f, 0.357178f, -0.0693359f, 0.381348f, -0.0834961f, 0.395752f, -0.110352f,
-0.410156f, -0.137207f, 0.416016f, -0.176025f, 0.421875f, -0.214844f, 0.421875f, -0.264648f,
-0.236328f, 0.00976562f, 0.135742f, 0.00976562f, 0.0888672f, -0.0581055f, 0.0419922f,
--0.125977f, 0.0419922f, -0.261719f, 0.0419922f, -0.399414f, 0.0900879f, -0.46875f,
-0.138184f, -0.538086f, 0.236328f, -0.538086f, 0.269043f, -0.538086f, 0.294189f, -0.532227f,
-0.319336f, -0.526367f, 0.339111f, -0.514893f, 0.358887f, -0.503418f, 0.373779f, -0.486328f,
-0.388672f, -0.469238f, 0.400879f, -0.446289f, 0.401855f, -0.446289f, 0.401855f, -0.458496f,
-0.402588f, -0.473389f, 0.40332f, -0.488281f, 0.404053f, -0.501465f, 0.404785f, -0.514648f,
-0.405762f, -0.52417f, 0.406738f, -0.533691f, 0.407715f, -0.535156f, 0.492188f, -0.535156f,
-0.491211f, -0.526855f, 0.48999f, -0.491699f, 0.48877f, -0.456543f, 0.48877f, -0.391113f,
-0.48877f, 0.20752f, 0.400879f, 0.20752f, 0.400879f, -0.00683594f, 0.400879f, -0.0195312f,
-0.401123f, -0.0332031f, 0.401367f, -0.046875f, 0.401855f, -0.059082f, 0.402344f,
--0.0727539f, 0.402832f, -0.0869141f, 0.401855f, -0.0869141f, 0.38916f, -0.0620117f,
-0.373779f, -0.0437012f, 0.358398f, -0.0253906f, 0.338379f, -0.0134277f, 0.318359f,
--0.00146484f, 0.293213f, 0.00415039f, 0.268066f, 0.00976562f, 0.236328f, 0.00976562f,
-0.400879f, -0.270508f, 0.400879f, -0.328125f, 0.390869f, -0.367188f, 0.380859f, -0.40625f,
-0.362549f, -0.429688f, 0.344238f, -0.453125f, 0.318115f, -0.463135f, 0.291992f, -0.473145f,
-0.259766f, -0.473145f, 0.226074f, -0.473145f, 0.202148f, -0.460693f, 0.178223f, -0.448242f,
-0.16333f, -0.422607f, 0.148438f, -0.396973f, 0.141357f, -0.357666f, 0.134277f, -0.318359f,
-0.134277f, -0.264648f, 0.134277f, -0.211914f, 0.140869f, -0.172852f, 0.147461f, -0.133789f,
-0.162354f, -0.108398f, 0.177246f, -0.0830078f, 0.200928f, -0.0705566f, 0.224609f,
--0.0581055f, 0.258789f, -0.0581055f, 0.288086f, -0.0581055f, 0.313965f, -0.0671387f,
-0.339844f, -0.0761719f, 0.359131f, -0.0998535f, 0.378418f, -0.123535f, 0.389648f,
--0.164795f, 0.400879f, -0.206055f, 0.400879f, -0.270508f, 0.0693359f, 0, 0.0693359f,
--0.405273f, 0.0693359f, -0.421875f, 0.0690918f, -0.439209f, 0.0688477f, -0.456543f,
-0.0683594f, -0.472656f, 0.0678711f, -0.48877f, 0.0673828f, -0.50293f, 0.0668945f,
--0.51709f, 0.0664062f, -0.52832f, 0.149414f, -0.52832f, 0.149902f, -0.51709f, 0.150635f,
--0.502686f, 0.151367f, -0.488281f, 0.1521f, -0.473145f, 0.152832f, -0.458008f, 0.153076f,
--0.444092f, 0.15332f, -0.430176f, 0.15332f, -0.42041f, 0.155273f, -0.42041f, 0.164551f,
--0.450684f, 0.175049f, -0.4729f, 0.185547f, -0.495117f, 0.199707f, -0.509521f, 0.213867f,
--0.523926f, 0.233398f, -0.531006f, 0.25293f, -0.538086f, 0.280762f, -0.538086f, 0.291504f,
--0.538086f, 0.30127f, -0.536377f, 0.311035f, -0.534668f, 0.316406f, -0.533203f, 0.316406f,
--0.452637f, 0.307617f, -0.455078f, 0.295898f, -0.456299f, 0.28418f, -0.45752f, 0.269531f,
--0.45752f, 0.239258f, -0.45752f, 0.218018f, -0.443848f, 0.196777f, -0.430176f, 0.18335f,
--0.406006f, 0.169922f, -0.381836f, 0.163574f, -0.348389f, 0.157227f, -0.314941f,
-0.157227f, -0.275391f, 0.157227f, 0, 0.463867f, -0.145996f, 0.463867f, -0.108887f,
-0.449463f, -0.079834f, 0.435059f, -0.0507812f, 0.407715f, -0.0310059f, 0.380371f,
--0.0112305f, 0.340576f, -0.000732422f, 0.300781f, 0.00976562f, 0.249512f, 0.00976562f,
-0.203613f, 0.00976562f, 0.166748f, 0.00268555f, 0.129883f, -0.00439453f, 0.102051f,
--0.0200195f, 0.0742188f, -0.0356445f, 0.0554199f, -0.0612793f, 0.0366211f, -0.0869141f,
-0.027832f, -0.124023f, 0.105469f, -0.13916f, 0.116699f, -0.0966797f, 0.151855f, -0.0769043f,
-0.187012f, -0.0571289f, 0.249512f, -0.0571289f, 0.277832f, -0.0571289f, 0.301514f,
--0.0610352f, 0.325195f, -0.0649414f, 0.342285f, -0.0744629f, 0.359375f, -0.0839844f,
-0.368896f, -0.0998535f, 0.378418f, -0.115723f, 0.378418f, -0.13916f, 0.378418f, -0.163086f,
-0.367188f, -0.178467f, 0.355957f, -0.193848f, 0.335938f, -0.204102f, 0.315918f, -0.214355f,
-0.287354f, -0.221924f, 0.258789f, -0.229492f, 0.224609f, -0.23877f, 0.192871f, -0.24707f,
-0.161621f, -0.257324f, 0.130371f, -0.267578f, 0.105225f, -0.284424f, 0.0800781f,
--0.30127f, 0.0644531f, -0.326172f, 0.0488281f, -0.351074f, 0.0488281f, -0.388672f,
-0.0488281f, -0.460938f, 0.100342f, -0.498779f, 0.151855f, -0.536621f, 0.250488f,
--0.536621f, 0.337891f, -0.536621f, 0.389404f, -0.505859f, 0.440918f, -0.475098f,
-0.45459f, -0.407227f, 0.375488f, -0.397461f, 0.371094f, -0.417969f, 0.359375f, -0.431885f,
-0.347656f, -0.445801f, 0.331055f, -0.454346f, 0.314453f, -0.462891f, 0.293701f, -0.466553f,
-0.272949f, -0.470215f, 0.250488f, -0.470215f, 0.190918f, -0.470215f, 0.162598f, -0.452148f,
-0.134277f, -0.434082f, 0.134277f, -0.397461f, 0.134277f, -0.375977f, 0.144775f, -0.362061f,
-0.155273f, -0.348145f, 0.174072f, -0.338623f, 0.192871f, -0.329102f, 0.219238f, -0.322021f,
-0.245605f, -0.314941f, 0.277344f, -0.307129f, 0.29834f, -0.301758f, 0.320312f, -0.295654f,
-0.342285f, -0.289551f, 0.363037f, -0.281006f, 0.383789f, -0.272461f, 0.4021f, -0.260986f,
-0.42041f, -0.249512f, 0.434082f, -0.233398f, 0.447754f, -0.217285f, 0.455811f, -0.195801f,
-0.463867f, -0.174316f, 0.463867f, -0.145996f, 0.270508f, -0.00390625f, 0.250488f,
-0.00146484f, 0.229736f, 0.00463867f, 0.208984f, 0.0078125f, 0.181641f, 0.0078125f,
-0.0761719f, 0.0078125f, 0.0761719f, -0.111816f, 0.0761719f, -0.464355f, 0.0151367f,
--0.464355f, 0.0151367f, -0.52832f, 0.0795898f, -0.52832f, 0.105469f, -0.646484f,
-0.164062f, -0.646484f, 0.164062f, -0.52832f, 0.261719f, -0.52832f, 0.261719f, -0.464355f,
-0.164062f, -0.464355f, 0.164062f, -0.130859f, 0.164062f, -0.0927734f, 0.176514f,
--0.0773926f, 0.188965f, -0.0620117f, 0.219727f, -0.0620117f, 0.232422f, -0.0620117f,
-0.244385f, -0.0639648f, 0.256348f, -0.065918f, 0.270508f, -0.0688477f, 0.15332f,
--0.52832f, 0.15332f, -0.193359f, 0.15332f, -0.154785f, 0.158936f, -0.128906f, 0.164551f,
--0.103027f, 0.177246f, -0.0871582f, 0.189941f, -0.0712891f, 0.210693f, -0.0646973f,
-0.231445f, -0.0581055f, 0.262207f, -0.0581055f, 0.293457f, -0.0581055f, 0.318604f,
--0.0690918f, 0.34375f, -0.0800781f, 0.361572f, -0.10083f, 0.379395f, -0.121582f,
-0.38916f, -0.1521f, 0.398926f, -0.182617f, 0.398926f, -0.222168f, 0.398926f, -0.52832f,
-0.486816f, -0.52832f, 0.486816f, -0.112793f, 0.486816f, -0.0961914f, 0.487061f, -0.0778809f,
-0.487305f, -0.0595703f, 0.487793f, -0.0432129f, 0.488281f, -0.0268555f, 0.48877f,
--0.0151367f, 0.489258f, -0.00341797f, 0.489746f, 0, 0.406738f, 0, 0.40625f, -0.00244141f,
-0.405762f, -0.0131836f, 0.405273f, -0.0239258f, 0.404541f, -0.0378418f, 0.403809f,
--0.0517578f, 0.40332f, -0.0661621f, 0.402832f, -0.0805664f, 0.402832f, -0.090332f,
-0.401367f, -0.090332f, 0.388672f, -0.0673828f, 0.373535f, -0.0488281f, 0.358398f,
--0.0302734f, 0.338379f, -0.017334f, 0.318359f, -0.00439453f, 0.29248f, 0.00268555f,
-0.266602f, 0.00976562f, 0.232422f, 0.00976562f, 0.188477f, 0.00976562f, 0.156738f,
--0.000976562f, 0.125f, -0.0117188f, 0.104492f, -0.0341797f, 0.0839844f, -0.0566406f,
-0.0744629f, -0.0917969f, 0.0649414f, -0.126953f, 0.0649414f, -0.17627f, 0.0649414f,
--0.52832f, 0.299316f, 0, 0.195312f, 0, 0.00341797f, -0.52832f, 0.097168f, -0.52832f,
-0.213379f, -0.18457f, 0.216797f, -0.173828f, 0.221436f, -0.158447f, 0.226074f, -0.143066f,
-0.230957f, -0.126465f, 0.23584f, -0.109863f, 0.23999f, -0.0944824f, 0.244141f, -0.0791016f,
-0.24707f, -0.0688477f, 0.25f, -0.0791016f, 0.254639f, -0.0944824f, 0.259277f, -0.109863f,
-0.26416f, -0.125977f, 0.269043f, -0.14209f, 0.27417f, -0.157471f, 0.279297f, -0.172852f,
-0.283203f, -0.183594f, 0.40332f, -0.52832f, 0.496582f, -0.52832f, 0.573242f, 0, 0.471191f,
-0, 0.386719f, -0.34082f, 0.382812f, -0.354004f, 0.378662f, -0.373535f, 0.374512f,
--0.393066f, 0.370605f, -0.411621f, 0.365723f, -0.433105f, 0.361328f, -0.456055f,
-0.356934f, -0.434082f, 0.352051f, -0.412598f, 0.348145f, -0.394043f, 0.343506f, -0.374023f,
-0.338867f, -0.354004f, 0.334961f, -0.338867f, 0.248047f, 0, 0.146484f, 0, -0.00146484f,
--0.52832f, 0.0854492f, -0.52832f, 0.174805f, -0.169434f, 0.178223f, -0.158203f, 0.181641f,
--0.141846f, 0.185059f, -0.125488f, 0.188477f, -0.109863f, 0.191895f, -0.0917969f,
-0.195801f, -0.0727539f, 0.199707f, -0.0913086f, 0.204102f, -0.108887f, 0.208008f,
--0.124023f, 0.211914f, -0.139648f, 0.21582f, -0.155273f, 0.21875f, -0.165527f, 0.314453f,
--0.52832f, 0.408691f, -0.52832f, 0.500977f, -0.165527f, 0.504395f, -0.152832f, 0.508301f,
--0.136719f, 0.512207f, -0.120605f, 0.515625f, -0.106445f, 0.519531f, -0.0898438f,
-0.523438f, -0.0727539f, 0.527344f, -0.0913086f, 0.53125f, -0.108887f, 0.534668f,
--0.124023f, 0.53833f, -0.140381f, 0.541992f, -0.156738f, 0.54541f, -0.169434f, 0.638672f,
--0.52832f, 0.724609f, -0.52832f, 0.391113f, 0, 0.249023f, -0.216797f, 0.105957f,
-0, 0.0112305f, 0, 0.199219f, -0.271484f, 0.0200195f, -0.52832f, 0.117188f, -0.52832f,
-0.249023f, -0.322754f, 0.379883f, -0.52832f, 0.478027f, -0.52832f, 0.298828f, -0.272461f,
-0.489258f, 0, 0.294922f, 0, 0.276367f, 0.0478516f, 0.25708f, 0.0861816f, 0.237793f,
-0.124512f, 0.213867f, 0.151611f, 0.189941f, 0.178711f, 0.160645f, 0.193115f, 0.131348f,
-0.20752f, 0.0932617f, 0.20752f, 0.0766602f, 0.20752f, 0.0625f, 0.206543f, 0.0483398f,
-0.205566f, 0.0327148f, 0.202148f, 0.0327148f, 0.13623f, 0.0419922f, 0.137695f, 0.0537109f,
-0.138428f, 0.0654297f, 0.13916f, 0.0737305f, 0.13916f, 0.112305f, 0.13916f, 0.145508f,
-0.110352f, 0.178711f, 0.081543f, 0.203613f, 0.0185547f, 0.211914f, -0.00244141f,
-0.00244141f, -0.52832f, 0.0961914f, -0.52832f, 0.20752f, -0.236328f, 0.212402f, -0.223145f,
-0.219971f, -0.201172f, 0.227539f, -0.179199f, 0.235107f, -0.157227f, 0.242676f, -0.135254f,
-0.248535f, -0.117676f, 0.254395f, -0.100098f, 0.255371f, -0.0957031f, 0.256836f,
--0.101074f, 0.262451f, -0.116943f, 0.268066f, -0.132812f, 0.275146f, -0.152344f,
-0.282227f, -0.171875f, 0.289551f, -0.191895f, 0.296875f, -0.211914f, 0.301758f, -0.226562f,
-0.405273f, -0.52832f, 0.498047f, -0.52832f, 0.0239258f, 0, 0.0239258f, -0.0668945f,
-0.34668f, -0.460449f, 0.043457f, -0.460449f, 0.043457f, -0.52832f, 0.445801f, -0.52832f,
-0.445801f, -0.461426f, 0.122559f, -0.0678711f, 0.463867f, -0.0678711f, 0.463867f,
-0
-};
-
-const unsigned char LiberationSanskNormalVerbs[] = {
-6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 2, 2, 1, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5,
-6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6,
-0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 0, 1,
-1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1,
-1, 1, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 1, 1, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
-1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1,
-5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
-1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2,
-5, 0, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1,
-2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1,
-1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2,
-1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2,
-2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2,
-2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 5, 6
-};
-
-const unsigned LiberationSanskNormalCharCodes[] = {
-32, 33, 35, 37, 38, 39, 41, 42, 43, 45, 46, 47, 49, 50,
-52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73,
-74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94,
-96, 97, 98, 99, 100, 101, 102, 103, 105, 108, 109, 110, 111, 112, 113, 114, 115,
-116, 117, 118, 119, 120, 121, 122
-};
-
-const SkFixed LiberationSanskNormalWidths[] = {
-0x00004720, 0x00004720, 0x00008e60, 0x0000e3a0, 0x0000aac0, 0x000030e0, 0x00005540,
-0x000063a0, 0x00009580, 0x00005540, 0x00004720, 0x00004720, 0x00008e60, 0x00008e60,
-0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00004720, 0x00004720,
-0x00009580, 0x00009580, 0x00009580, 0x00008e60, 0x000103e0, 0x0000aac0, 0x0000aac0,
-0x0000b8e0, 0x0000b8e0, 0x0000aac0, 0x00009c60, 0x0000b8e0, 0x00004720, 0x00008000,
-0x0000aac0, 0x00008e60, 0x0000d540, 0x0000b8e0, 0x0000c720, 0x0000aac0, 0x0000c720,
-0x0000b8e0, 0x0000aac0, 0x00009c60, 0x0000aac0, 0x0000f1a0, 0x0000aac0, 0x0000aac0,
-0x00009c60, 0x00004720, 0x00004720, 0x00004720, 0x00007820, 0x00005540, 0x00008e60,
-0x00008e60, 0x00008000, 0x00008e60, 0x00008e60, 0x00004720, 0x00008e60, 0x000038e0,
-0x000038e0, 0x0000d540, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00005540,
-0x00008000, 0x00004720, 0x00008e60, 0x00008000, 0x0000b8e0, 0x00008000, 0x00008000,
-0x00008000
-};
-
-const int LiberationSanskNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSanskNormalCharCodes);
-
-const SkPaint::FontMetrics LiberationSanskNormalMetrics = {
-0x00000003, -0.910156f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.25342f, 0,
--0.203125f, 1.05029f, 0.538086f, 0, 0.0732422f, 0.105957f
-};
-
-const SkScalar LiberationSanskBoldPoints[] = {
-0.222168f, -0.208008f, 0.109863f, -0.208008f, 0.0942383f, -0.687988f, 0.237793f, -0.687988f,
-0.0942383f, 0, 0.0942383f, -0.131836f, 0.234863f, -0.131836f, 0.234863f, 0, 0.394043f,
--0.438477f, 0.287109f, -0.438477f, 0.273926f, -0.687988f, 0.408203f, -0.687988f,
-0.186035f, -0.438477f, 0.0791016f, -0.438477f, 0.065918f, -0.687988f, 0.199219f,
--0.687988f, 0.443848f, -0.420898f, 0.410156f, -0.258789f, 0.515137f, -0.258789f,
-0.515137f, -0.186035f, 0.39502f, -0.186035f, 0.35498f, 0, 0.278809f, 0, 0.317871f,
--0.186035f, 0.167969f, -0.186035f, 0.128906f, 0, 0.0541992f, 0, 0.0927734f, -0.186035f,
-0.0170898f, -0.186035f, 0.0170898f, -0.258789f, 0.108887f, -0.258789f, 0.143066f,
--0.420898f, 0.0419922f, -0.420898f, 0.0419922f, -0.493164f, 0.158203f, -0.493164f,
-0.199219f, -0.681152f, 0.273926f, -0.681152f, 0.233887f, -0.493164f, 0.383789f, -0.493164f,
-0.424805f, -0.681152f, 0.500977f, -0.681152f, 0.459961f, -0.493164f, 0.540039f, -0.493164f,
-0.540039f, -0.420898f, 0.219238f, -0.420898f, 0.184082f, -0.258789f, 0.334961f, -0.258789f,
-0.369141f, -0.420898f, 0.541992f, -0.201172f, 0.541992f, -0.159668f, 0.52832f, -0.125732f,
-0.514648f, -0.0917969f, 0.486084f, -0.0671387f, 0.45752f, -0.0424805f, 0.413086f,
--0.0280762f, 0.368652f, -0.0136719f, 0.307129f, -0.0112305f, 0.307129f, 0.0742188f,
-0.253906f, 0.0742188f, 0.253906f, -0.00976562f, 0.198242f, -0.0117188f, 0.156982f,
--0.0249023f, 0.115723f, -0.0380859f, 0.0866699f, -0.0620117f, 0.0576172f, -0.0859375f,
-0.0397949f, -0.120361f, 0.0219727f, -0.154785f, 0.0131836f, -0.199219f, 0.138184f,
--0.222168f, 0.14209f, -0.19873f, 0.149658f, -0.179443f, 0.157227f, -0.160156f, 0.17041f,
--0.145996f, 0.183594f, -0.131836f, 0.203857f, -0.122803f, 0.224121f, -0.11377f, 0.253906f,
--0.11084f, 0.253906f, -0.301758f, 0.252441f, -0.302734f, 0.246582f, -0.303955f, 0.240723f,
--0.305176f, 0.23877f, -0.305176f, 0.200684f, -0.313965f, 0.164062f, -0.326904f, 0.127441f,
--0.339844f, 0.098877f, -0.362061f, 0.0703125f, -0.384277f, 0.0527344f, -0.418213f,
-0.0351562f, -0.452148f, 0.0351562f, -0.50293f, 0.0351562f, -0.547363f, 0.0512695f,
--0.579346f, 0.0673828f, -0.611328f, 0.0964355f, -0.632324f, 0.125488f, -0.65332f,
-0.165771f, -0.664062f, 0.206055f, -0.674805f, 0.253906f, -0.676758f, 0.253906f, -0.742188f,
-0.307129f, -0.742188f, 0.307129f, -0.676758f, 0.359375f, -0.674805f, 0.395996f, -0.663086f,
-0.432617f, -0.651367f, 0.458008f, -0.630127f, 0.483398f, -0.608887f, 0.499023f, -0.577881f,
-0.514648f, -0.546875f, 0.524902f, -0.505859f, 0.395996f, -0.486816f, 0.388672f, -0.529297f,
-0.367432f, -0.55249f, 0.346191f, -0.575684f, 0.307129f, -0.581055f, 0.307129f, -0.40918f,
-0.30957f, -0.408203f, 0.312256f, -0.408203f, 0.314941f, -0.408203f, 0.317871f, -0.407227f,
-0.359863f, -0.397461f, 0.400146f, -0.384277f, 0.44043f, -0.371094f, 0.471924f, -0.348633f,
-0.503418f, -0.326172f, 0.522705f, -0.290771f, 0.541992f, -0.255371f, 0.541992f, -0.201172f,
-0.253906f, -0.583008f, 0.228027f, -0.581055f, 0.210693f, -0.574219f, 0.193359f, -0.567383f,
-0.182617f, -0.556885f, 0.171875f, -0.546387f, 0.16748f, -0.532959f, 0.163086f, -0.519531f,
-0.163086f, -0.504883f, 0.163086f, -0.483887f, 0.169922f, -0.470459f, 0.176758f, -0.457031f,
-0.188965f, -0.448242f, 0.201172f, -0.439453f, 0.217773f, -0.43335f, 0.234375f, -0.427246f,
-0.253906f, -0.420898f, 0.415039f, -0.199219f, 0.415039f, -0.223145f, 0.406738f, -0.238037f,
-0.398438f, -0.25293f, 0.383789f, -0.262207f, 0.369141f, -0.271484f, 0.349365f, -0.277588f,
-0.32959f, -0.283691f, 0.307129f, -0.290039f, 0.307129f, -0.11084f, 0.358887f, -0.114258f,
-0.386963f, -0.135254f, 0.415039f, -0.15625f, 0.415039f, -0.199219f, 0.862793f, -0.210938f,
-0.862793f, -0.149902f, 0.849121f, -0.10791f, 0.835449f, -0.065918f, 0.812012f, -0.0402832f,
-0.788574f, -0.0146484f, 0.75708f, -0.00341797f, 0.725586f, 0.0078125f, 0.689941f,
-0.0078125f, 0.65332f, 0.0078125f, 0.621826f, -0.00341797f, 0.590332f, -0.0146484f,
-0.567139f, -0.0402832f, 0.543945f, -0.065918f, 0.530518f, -0.10791f, 0.51709f, -0.149902f,
-0.51709f, -0.210938f, 0.51709f, -0.275391f, 0.530518f, -0.317627f, 0.543945f, -0.359863f,
-0.567383f, -0.38501f, 0.59082f, -0.410156f, 0.622803f, -0.420166f, 0.654785f, -0.430176f,
-0.691895f, -0.430176f, 0.727051f, -0.430176f, 0.758301f, -0.420166f, 0.789551f, -0.410156f,
-0.812744f, -0.38501f, 0.835938f, -0.359863f, 0.849365f, -0.317627f, 0.862793f, -0.275391f,
-0.862793f, -0.210938f, 0.269531f, 0, 0.168945f, 0, 0.618164f, -0.687988f, 0.720215f,
--0.687988f, 0.199219f, -0.695801f, 0.234375f, -0.695801f, 0.265625f, -0.685791f,
-0.296875f, -0.675781f, 0.320312f, -0.650879f, 0.34375f, -0.625977f, 0.357422f, -0.58374f,
-0.371094f, -0.541504f, 0.371094f, -0.477051f, 0.371094f, -0.416016f, 0.357422f, -0.374023f,
-0.34375f, -0.332031f, 0.320068f, -0.306152f, 0.296387f, -0.280273f, 0.264648f, -0.269043f,
-0.23291f, -0.257812f, 0.196777f, -0.257812f, 0.161133f, -0.257812f, 0.129639f, -0.269043f,
-0.0981445f, -0.280273f, 0.0749512f, -0.305908f, 0.0517578f, -0.331543f, 0.0383301f,
--0.373535f, 0.0249023f, -0.415527f, 0.0249023f, -0.477051f, 0.0249023f, -0.541504f,
-0.0380859f, -0.58374f, 0.0512695f, -0.625977f, 0.074707f, -0.650879f, 0.0981445f,
--0.675781f, 0.130127f, -0.685791f, 0.162109f, -0.695801f, 0.199219f, -0.695801f,
-0.757812f, -0.210938f, 0.757812f, -0.253418f, 0.753662f, -0.28125f, 0.749512f, -0.309082f,
-0.741211f, -0.325439f, 0.73291f, -0.341797f, 0.720703f, -0.348389f, 0.708496f, -0.35498f,
-0.691895f, -0.35498f, 0.673828f, -0.35498f, 0.660889f, -0.348389f, 0.647949f, -0.341797f,
-0.639648f, -0.325195f, 0.631348f, -0.308594f, 0.627197f, -0.280762f, 0.623047f, -0.25293f,
-0.623047f, -0.210938f, 0.623047f, -0.169922f, 0.626953f, -0.142822f, 0.630859f, -0.115723f,
-0.639404f, -0.0991211f, 0.647949f, -0.0825195f, 0.660645f, -0.0756836f, 0.67334f,
--0.0688477f, 0.690918f, -0.0688477f, 0.707031f, -0.0688477f, 0.719482f, -0.0756836f,
-0.731934f, -0.0825195f, 0.740479f, -0.098877f, 0.749023f, -0.115234f, 0.753418f,
--0.142578f, 0.757812f, -0.169922f, 0.757812f, -0.210938f, 0.265137f, -0.477051f,
-0.265137f, -0.519043f, 0.260986f, -0.546631f, 0.256836f, -0.574219f, 0.248535f, -0.590576f,
-0.240234f, -0.606934f, 0.228027f, -0.613525f, 0.21582f, -0.620117f, 0.199219f, -0.620117f,
-0.181152f, -0.620117f, 0.167969f, -0.613281f, 0.154785f, -0.606445f, 0.146484f, -0.590088f,
-0.138184f, -0.57373f, 0.134033f, -0.546143f, 0.129883f, -0.518555f, 0.129883f, -0.477051f,
-0.129883f, -0.436035f, 0.134033f, -0.408691f, 0.138184f, -0.381348f, 0.146729f, -0.364746f,
-0.155273f, -0.348145f, 0.167969f, -0.341064f, 0.180664f, -0.333984f, 0.198242f, -0.333984f,
-0.214844f, -0.333984f, 0.227295f, -0.34082f, 0.239746f, -0.347656f, 0.248291f, -0.364258f,
-0.256836f, -0.380859f, 0.260986f, -0.408447f, 0.265137f, -0.436035f, 0.265137f, -0.477051f,
-0.0439453f, -0.187988f, 0.0439453f, -0.226562f, 0.0563965f, -0.257812f, 0.0688477f,
--0.289062f, 0.0908203f, -0.314453f, 0.112793f, -0.339844f, 0.143066f, -0.360107f,
-0.17334f, -0.380371f, 0.208984f, -0.396973f, 0.193359f, -0.428711f, 0.183105f, -0.464844f,
-0.172852f, -0.500977f, 0.172852f, -0.533203f, 0.172852f, -0.56543f, 0.182617f, -0.594238f,
-0.192383f, -0.623047f, 0.214355f, -0.644775f, 0.236328f, -0.666504f, 0.271484f, -0.679199f,
-0.306641f, -0.691895f, 0.356934f, -0.691895f, 0.396484f, -0.691895f, 0.428955f, -0.682373f,
-0.461426f, -0.672852f, 0.484863f, -0.654297f, 0.508301f, -0.635742f, 0.52124f, -0.608887f,
-0.53418f, -0.582031f, 0.53418f, -0.546875f, 0.53418f, -0.51123f, 0.518066f, -0.483643f,
-0.501953f, -0.456055f, 0.475342f, -0.433838f, 0.44873f, -0.411621f, 0.414062f, -0.393311f,
-0.379395f, -0.375f, 0.342773f, -0.35791f, 0.367676f, -0.313965f, 0.397461f, -0.273193f,
-0.427246f, -0.232422f, 0.461914f, -0.193848f, 0.489258f, -0.235352f, 0.507812f, -0.279053f,
-0.526367f, -0.322754f, 0.539062f, -0.371094f, 0.641113f, -0.336914f, 0.624512f, -0.279785f,
-0.601562f, -0.229492f, 0.578613f, -0.179199f, 0.546875f, -0.131836f, 0.568848f, -0.113281f,
-0.59082f, -0.104736f, 0.612793f, -0.0961914f, 0.633789f, -0.0961914f, 0.649414f,
--0.0961914f, 0.663818f, -0.0981445f, 0.678223f, -0.100098f, 0.690918f, -0.104004f,
-0.690918f, -0.00488281f, 0.664062f, 0.00585938f, 0.626953f, 0.00585938f, 0.602051f,
-0.00585938f, 0.579102f, 0.000976562f, 0.556152f, -0.00390625f, 0.535645f, -0.0119629f,
-0.515137f, -0.0200195f, 0.497559f, -0.0307617f, 0.47998f, -0.0415039f, 0.46582f,
--0.0532227f, 0.449707f, -0.0410156f, 0.429932f, -0.029541f, 0.410156f, -0.0180664f,
-0.386963f, -0.00927734f, 0.36377f, -0.000488281f, 0.337158f, 0.00463867f, 0.310547f,
-0.00976562f, 0.280762f, 0.00976562f, 0.219238f, 0.00976562f, 0.174316f, -0.00537109f,
-0.129395f, -0.0205078f, 0.100586f, -0.046875f, 0.0717773f, -0.0732422f, 0.0578613f,
--0.109375f, 0.0439453f, -0.145508f, 0.0439453f, -0.187988f, 0.424805f, -0.545898f,
-0.424805f, -0.57373f, 0.40625f, -0.591309f, 0.387695f, -0.608887f, 0.355957f, -0.608887f,
-0.318359f, -0.608887f, 0.298584f, -0.587891f, 0.278809f, -0.566895f, 0.278809f, -0.532227f,
-0.278809f, -0.508789f, 0.286377f, -0.484375f, 0.293945f, -0.459961f, 0.305176f, -0.437988f,
-0.330078f, -0.44873f, 0.352051f, -0.459717f, 0.374023f, -0.470703f, 0.390137f, -0.483643f,
-0.40625f, -0.496582f, 0.415527f, -0.511719f, 0.424805f, -0.526855f, 0.424805f, -0.545898f,
-0.384766f, -0.120117f, 0.347168f, -0.162109f, 0.313477f, -0.208008f, 0.279785f, -0.253906f,
-0.251953f, -0.304199f, 0.211426f, -0.285156f, 0.189697f, -0.257324f, 0.167969f, -0.229492f,
-0.167969f, -0.189941f, 0.167969f, -0.16748f, 0.175537f, -0.147949f, 0.183105f, -0.128418f,
-0.197754f, -0.114014f, 0.212402f, -0.0996094f, 0.234619f, -0.0913086f, 0.256836f,
--0.0830078f, 0.286133f, -0.0830078f, 0.317871f, -0.0830078f, 0.343506f, -0.0947266f,
-0.369141f, -0.106445f, 0.384766f, -0.120117f, 0.172852f, -0.438477f, 0.065918f, -0.438477f,
-0.0532227f, -0.687988f, 0.186035f, -0.687988f, 0.194824f, 0.20752f, 0.157227f, 0.15332f,
-0.129883f, 0.0996094f, 0.102539f, 0.0458984f, 0.0847168f, -0.0107422f, 0.0668945f,
--0.0673828f, 0.0583496f, -0.128662f, 0.0498047f, -0.189941f, 0.0498047f, -0.259277f,
-0.0498047f, -0.329102f, 0.0583496f, -0.389893f, 0.0668945f, -0.450684f, 0.0847168f,
--0.50708f, 0.102539f, -0.563477f, 0.129883f, -0.616943f, 0.157227f, -0.67041f, 0.194824f,
--0.724609f, 0.332031f, -0.724609f, 0.292969f, -0.667969f, 0.265137f, -0.612793f,
-0.237305f, -0.557617f, 0.219482f, -0.500977f, 0.20166f, -0.444336f, 0.193359f, -0.384521f,
-0.185059f, -0.324707f, 0.185059f, -0.258789f, 0.185059f, -0.192383f, 0.193359f, -0.132568f,
-0.20166f, -0.0727539f, 0.219482f, -0.0161133f, 0.237305f, 0.0405273f, 0.265137f,
-0.095459f, 0.292969f, 0.150391f, 0.332031f, 0.20752f, 0.000976562f, 0.20752f, 0.0400391f,
-0.150391f, 0.0678711f, 0.095459f, 0.0957031f, 0.0405273f, 0.113525f, -0.0161133f,
-0.131348f, -0.0727539f, 0.139648f, -0.132568f, 0.147949f, -0.192383f, 0.147949f,
--0.258789f, 0.147949f, -0.324707f, 0.139648f, -0.384521f, 0.131348f, -0.444336f,
-0.113525f, -0.500977f, 0.0957031f, -0.557617f, 0.0678711f, -0.612793f, 0.0400391f,
--0.667969f, 0.000976562f, -0.724609f, 0.138184f, -0.724609f, 0.175781f, -0.67041f,
-0.203125f, -0.616943f, 0.230469f, -0.563477f, 0.248291f, -0.50708f, 0.266113f, -0.450684f,
-0.274658f, -0.389893f, 0.283203f, -0.329102f, 0.283203f, -0.259277f, 0.283203f, -0.189941f,
-0.274658f, -0.128662f, 0.266113f, -0.0673828f, 0.248291f, -0.0107422f, 0.230469f,
-0.0458984f, 0.203125f, 0.0996094f, 0.175781f, 0.15332f, 0.138184f, 0.20752f, 0.240234f,
--0.554199f, 0.35498f, -0.60498f, 0.388184f, -0.508789f, 0.266113f, -0.479004f, 0.356934f,
--0.375f, 0.26709f, -0.315918f, 0.195801f, -0.438965f, 0.123047f, -0.315918f, 0.0322266f,
--0.375977f, 0.125f, -0.479004f, 0.00292969f, -0.508789f, 0.0361328f, -0.60498f, 0.152832f,
--0.554199f, 0.144043f, -0.687988f, 0.249023f, -0.687988f, 0.347168f, -0.277832f,
-0.347168f, -0.0786133f, 0.236816f, -0.0786133f, 0.236816f, -0.277832f, 0.0419922f,
--0.277832f, 0.0419922f, -0.387207f, 0.236816f, -0.387207f, 0.236816f, -0.586426f,
-0.347168f, -0.586426f, 0.347168f, -0.387207f, 0.543457f, -0.387207f, 0.543457f, -0.277832f,
-0.0390625f, -0.199707f, 0.0390625f, -0.318848f, 0.292969f, -0.318848f, 0.292969f,
--0.199707f, 0.0678711f, 0, 0.0678711f, -0.148926f, 0.208984f, -0.148926f, 0.208984f,
-0, 0.00976562f, 0.0200195f, 0.151855f, -0.724609f, 0.268066f, -0.724609f, 0.128418f,
-0.0200195f, 0.515137f, -0.344238f, 0.515137f, -0.245605f, 0.49707f, -0.177979f, 0.479004f,
--0.110352f, 0.447021f, -0.0686035f, 0.415039f, -0.0268555f, 0.371338f, -0.00854492f,
-0.327637f, 0.00976562f, 0.275879f, 0.00976562f, 0.224121f, 0.00976562f, 0.180664f,
--0.00830078f, 0.137207f, -0.0263672f, 0.105957f, -0.0681152f, 0.074707f, -0.109863f,
-0.0571289f, -0.17749f, 0.0395508f, -0.245117f, 0.0395508f, -0.344238f, 0.0395508f,
--0.448242f, 0.0568848f, -0.516357f, 0.0742188f, -0.584473f, 0.105957f, -0.625f, 0.137695f,
--0.665527f, 0.181885f, -0.681885f, 0.226074f, -0.698242f, 0.279785f, -0.698242f,
-0.330078f, -0.698242f, 0.373291f, -0.681885f, 0.416504f, -0.665527f, 0.447998f, -0.625f,
-0.479492f, -0.584473f, 0.497314f, -0.516357f, 0.515137f, -0.448242f, 0.515137f, -0.344238f,
-0.377441f, -0.344238f, 0.377441f, -0.416992f, 0.37207f, -0.4646f, 0.366699f, -0.512207f,
-0.35498f, -0.540283f, 0.343262f, -0.568359f, 0.324463f, -0.57959f, 0.305664f, -0.59082f,
-0.278809f, -0.59082f, 0.25f, -0.59082f, 0.230469f, -0.579346f, 0.210938f, -0.567871f,
-0.198975f, -0.539551f, 0.187012f, -0.51123f, 0.181885f, -0.463623f, 0.176758f, -0.416016f,
-0.176758f, -0.344238f, 0.176758f, -0.273438f, 0.182129f, -0.226074f, 0.1875f, -0.178711f,
-0.199219f, -0.150146f, 0.210938f, -0.121582f, 0.22998f, -0.109863f, 0.249023f, -0.0981445f,
-0.276855f, -0.0981445f, 0.303711f, -0.0981445f, 0.322754f, -0.109863f, 0.341797f,
--0.121582f, 0.354004f, -0.150146f, 0.366211f, -0.178711f, 0.371826f, -0.226074f,
-0.377441f, -0.273438f, 0.377441f, -0.344238f, 0.0629883f, 0, 0.0629883f, -0.102051f,
-0.233398f, -0.102051f, 0.233398f, -0.571289f, 0.0683594f, -0.468262f, 0.0683594f,
--0.576172f, 0.240723f, -0.687988f, 0.370605f, -0.687988f, 0.370605f, -0.102051f,
-0.52832f, -0.102051f, 0.52832f, 0, 0.034668f, 0, 0.034668f, -0.0952148f, 0.0581055f,
--0.146484f, 0.0917969f, -0.187744f, 0.125488f, -0.229004f, 0.162354f, -0.263428f,
-0.199219f, -0.297852f, 0.235596f, -0.327393f, 0.271973f, -0.356934f, 0.301025f, -0.384521f,
-0.330078f, -0.412109f, 0.348145f, -0.439941f, 0.366211f, -0.467773f, 0.366211f, -0.499023f,
-0.366211f, -0.544922f, 0.343262f, -0.566895f, 0.320312f, -0.588867f, 0.275879f, -0.588867f,
-0.231934f, -0.588867f, 0.20874f, -0.565186f, 0.185547f, -0.541504f, 0.178711f, -0.494141f,
-0.0405273f, -0.501953f, 0.0454102f, -0.54248f, 0.0605469f, -0.578125f, 0.0756836f,
--0.61377f, 0.10376f, -0.640625f, 0.131836f, -0.66748f, 0.174072f, -0.682861f, 0.216309f,
--0.698242f, 0.274902f, -0.698242f, 0.330566f, -0.698242f, 0.373535f, -0.685303f,
-0.416504f, -0.672363f, 0.445801f, -0.647461f, 0.475098f, -0.622559f, 0.490234f, -0.58667f,
-0.505371f, -0.550781f, 0.505371f, -0.504883f, 0.505371f, -0.456543f, 0.486328f, -0.41748f,
-0.467285f, -0.378418f, 0.4375f, -0.345459f, 0.407715f, -0.3125f, 0.371338f, -0.283691f,
-0.334961f, -0.254883f, 0.300781f, -0.227539f, 0.266602f, -0.200195f, 0.238525f, -0.172363f,
-0.210449f, -0.144531f, 0.196777f, -0.112793f, 0.516113f, -0.112793f, 0.516113f, 0,
-0.52002f, -0.190918f, 0.52002f, -0.144043f, 0.504639f, -0.106689f, 0.489258f, -0.0693359f,
-0.458496f, -0.0429688f, 0.427734f, -0.0166016f, 0.38208f, -0.00268555f, 0.336426f,
-0.0112305f, 0.275879f, 0.0112305f, 0.208496f, 0.0112305f, 0.162354f, -0.00585938f,
-0.116211f, -0.0229492f, 0.0866699f, -0.0510254f, 0.0571289f, -0.0791016f, 0.0422363f,
--0.114746f, 0.0273438f, -0.150391f, 0.0229492f, -0.187012f, 0.162598f, -0.199219f,
-0.165527f, -0.177246f, 0.173584f, -0.158936f, 0.181641f, -0.140625f, 0.195312f, -0.127441f,
-0.208984f, -0.114258f, 0.22876f, -0.107178f, 0.248535f, -0.100098f, 0.275391f, -0.100098f,
-0.324707f, -0.100098f, 0.352051f, -0.124512f, 0.379395f, -0.148926f, 0.379395f, -0.199219f,
-0.379395f, -0.22998f, 0.366455f, -0.248535f, 0.353516f, -0.26709f, 0.33374f, -0.2771f,
-0.313965f, -0.287109f, 0.291016f, -0.290527f, 0.268066f, -0.293945f, 0.247559f, -0.293945f,
-0.199707f, -0.293945f, 0.199707f, -0.404785f, 0.244629f, -0.404785f, 0.265137f, -0.404785f,
-0.286377f, -0.408691f, 0.307617f, -0.412598f, 0.324707f, -0.422852f, 0.341797f, -0.433105f,
-0.352539f, -0.451416f, 0.363281f, -0.469727f, 0.363281f, -0.498047f, 0.363281f, -0.540527f,
-0.3396f, -0.564697f, 0.315918f, -0.588867f, 0.270508f, -0.588867f, 0.228027f, -0.588867f,
-0.201904f, -0.56543f, 0.175781f, -0.541992f, 0.171875f, -0.499023f, 0.034668f, -0.508789f,
-0.0405273f, -0.557129f, 0.0612793f, -0.592773f, 0.0820312f, -0.628418f, 0.113525f,
--0.651855f, 0.14502f, -0.675293f, 0.186035f, -0.686768f, 0.227051f, -0.698242f, 0.272949f,
--0.698242f, 0.333496f, -0.698242f, 0.376953f, -0.683594f, 0.42041f, -0.668945f, 0.448242f,
--0.644043f, 0.476074f, -0.619141f, 0.489258f, -0.585938f, 0.502441f, -0.552734f,
-0.502441f, -0.515137f, 0.502441f, -0.484863f, 0.493652f, -0.45874f, 0.484863f, -0.432617f,
-0.467041f, -0.411865f, 0.449219f, -0.391113f, 0.421387f, -0.376221f, 0.393555f, -0.361328f,
-0.355469f, -0.354004f, 0.355469f, -0.352051f, 0.397949f, -0.347168f, 0.429199f, -0.332764f,
-0.460449f, -0.318359f, 0.480469f, -0.296875f, 0.500488f, -0.275391f, 0.510254f, -0.248291f,
-0.52002f, -0.221191f, 0.52002f, -0.190918f, 0.52832f, -0.229004f, 0.52832f, -0.177246f,
-0.511963f, -0.133545f, 0.495605f, -0.0898438f, 0.463379f, -0.0578613f, 0.431152f,
--0.0258789f, 0.383545f, -0.00805664f, 0.335938f, 0.00976562f, 0.273438f, 0.00976562f,
-0.21582f, 0.00976562f, 0.172852f, -0.00415039f, 0.129883f, -0.0180664f, 0.100342f,
--0.0427246f, 0.0708008f, -0.0673828f, 0.0539551f, -0.100586f, 0.0371094f, -0.133789f,
-0.0307617f, -0.171875f, 0.167969f, -0.183105f, 0.171875f, -0.166992f, 0.178955f,
--0.151855f, 0.186035f, -0.136719f, 0.19873f, -0.125f, 0.211426f, -0.113281f, 0.22998f,
--0.106201f, 0.248535f, -0.0991211f, 0.274902f, -0.0991211f, 0.326172f, -0.0991211f,
-0.356689f, -0.131836f, 0.387207f, -0.164551f, 0.387207f, -0.226074f, 0.387207f, -0.253418f,
-0.379639f, -0.275391f, 0.37207f, -0.297363f, 0.358154f, -0.312988f, 0.344238f, -0.328613f,
-0.323975f, -0.336914f, 0.303711f, -0.345215f, 0.277832f, -0.345215f, 0.243652f, -0.345215f,
-0.22168f, -0.332275f, 0.199707f, -0.319336f, 0.18457f, -0.300781f, 0.0507812f, -0.300781f,
-0.074707f, -0.687988f, 0.488281f, -0.687988f, 0.488281f, -0.585938f, 0.199219f, -0.585938f,
-0.187988f, -0.412109f, 0.208496f, -0.430176f, 0.239746f, -0.443115f, 0.270996f, -0.456055f,
-0.3125f, -0.456055f, 0.363281f, -0.456055f, 0.40332f, -0.439453f, 0.443359f, -0.422852f,
-0.471191f, -0.393066f, 0.499023f, -0.363281f, 0.513672f, -0.321533f, 0.52832f, -0.279785f,
-0.52832f, -0.229004f, 0.52002f, -0.225098f, 0.52002f, -0.17334f, 0.505371f, -0.130127f,
-0.490723f, -0.0869141f, 0.46167f, -0.0559082f, 0.432617f, -0.0249023f, 0.38916f,
--0.00756836f, 0.345703f, 0.00976562f, 0.288574f, 0.00976562f, 0.166992f, 0.00976562f,
-0.101807f, -0.0754395f, 0.0366211f, -0.160645f, 0.0366211f, -0.328125f, 0.0366211f,
--0.512207f, 0.102783f, -0.605225f, 0.168945f, -0.698242f, 0.291992f, -0.698242f,
-0.333008f, -0.698242f, 0.366699f, -0.689697f, 0.400391f, -0.681152f, 0.426758f, -0.662109f,
-0.453125f, -0.643066f, 0.47168f, -0.613037f, 0.490234f, -0.583008f, 0.501465f, -0.540039f,
-0.37207f, -0.521973f, 0.362305f, -0.558105f, 0.340332f, -0.573975f, 0.318359f, -0.589844f,
-0.289062f, -0.589844f, 0.233887f, -0.589844f, 0.202393f, -0.534668f, 0.170898f, -0.479492f,
-0.170898f, -0.367188f, 0.192871f, -0.403809f, 0.231934f, -0.42334f, 0.270996f, -0.442871f,
-0.320312f, -0.442871f, 0.365723f, -0.442871f, 0.402588f, -0.427979f, 0.439453f, -0.413086f,
-0.465576f, -0.38501f, 0.491699f, -0.356934f, 0.505859f, -0.316406f, 0.52002f, -0.275879f,
-0.52002f, -0.225098f, 0.382324f, -0.221191f, 0.382324f, -0.249023f, 0.375977f, -0.27124f,
-0.369629f, -0.293457f, 0.356689f, -0.309082f, 0.34375f, -0.324707f, 0.324707f, -0.333252f,
-0.305664f, -0.341797f, 0.280762f, -0.341797f, 0.262695f, -0.341797f, 0.244629f, -0.335938f,
-0.226562f, -0.330078f, 0.212402f, -0.317139f, 0.198242f, -0.304199f, 0.189453f, -0.28418f,
-0.180664f, -0.26416f, 0.180664f, -0.23584f, 0.180664f, -0.206543f, 0.187988f, -0.181152f,
-0.195312f, -0.155762f, 0.20874f, -0.136963f, 0.222168f, -0.118164f, 0.241211f, -0.107666f,
-0.260254f, -0.097168f, 0.28418f, -0.097168f, 0.330566f, -0.097168f, 0.356445f, -0.130127f,
-0.382324f, -0.163086f, 0.382324f, -0.221191f, 0.512207f, -0.579102f, 0.46582f, -0.505859f,
-0.424561f, -0.437012f, 0.383301f, -0.368164f, 0.352539f, -0.298584f, 0.321777f, -0.229004f,
-0.303955f, -0.155518f, 0.286133f, -0.0820312f, 0.286133f, 0, 0.143066f, 0, 0.143066f,
--0.081543f, 0.162354f, -0.155029f, 0.181641f, -0.228516f, 0.214844f, -0.29834f, 0.248047f,
--0.368164f, 0.291992f, -0.436279f, 0.335938f, -0.504395f, 0.384766f, -0.575195f,
-0.0429688f, -0.575195f, 0.0429688f, -0.687988f, 0.512207f, -0.687988f, 0.525391f,
--0.193848f, 0.525391f, -0.149414f, 0.510742f, -0.112061f, 0.496094f, -0.074707f,
-0.46582f, -0.0476074f, 0.435547f, -0.0205078f, 0.38916f, -0.00537109f, 0.342773f,
-0.00976562f, 0.278809f, 0.00976562f, 0.215332f, 0.00976562f, 0.168701f, -0.00537109f,
-0.12207f, -0.0205078f, 0.0915527f, -0.0476074f, 0.0610352f, -0.074707f, 0.0463867f,
--0.111816f, 0.0317383f, -0.148926f, 0.0317383f, -0.192871f, 0.0317383f, -0.230469f,
-0.043457f, -0.259521f, 0.0551758f, -0.288574f, 0.074707f, -0.30957f, 0.0942383f,
--0.330566f, 0.119629f, -0.343018f, 0.14502f, -0.355469f, 0.171875f, -0.359863f, 0.171875f,
--0.361816f, 0.143066f, -0.368164f, 0.120117f, -0.382812f, 0.097168f, -0.397461f,
-0.0810547f, -0.417969f, 0.0649414f, -0.438477f, 0.0563965f, -0.463623f, 0.0478516f,
--0.48877f, 0.0478516f, -0.516113f, 0.0478516f, -0.557129f, 0.0627441f, -0.59082f,
-0.0776367f, -0.624512f, 0.106445f, -0.648438f, 0.135254f, -0.672363f, 0.177979f,
--0.685303f, 0.220703f, -0.698242f, 0.276855f, -0.698242f, 0.336914f, -0.698242f,
-0.380615f, -0.684814f, 0.424316f, -0.671387f, 0.452637f, -0.647217f, 0.480957f, -0.623047f,
-0.494629f, -0.589355f, 0.508301f, -0.555664f, 0.508301f, -0.515137f, 0.508301f, -0.488281f,
-0.499756f, -0.463135f, 0.491211f, -0.437988f, 0.475098f, -0.41748f, 0.458984f, -0.396973f,
-0.435791f, -0.382812f, 0.412598f, -0.368652f, 0.383301f, -0.362793f, 0.383301f, -0.36084f,
-0.413574f, -0.355957f, 0.439697f, -0.343018f, 0.46582f, -0.330078f, 0.484863f, -0.309326f,
-0.503906f, -0.288574f, 0.514648f, -0.259521f, 0.525391f, -0.230469f, 0.525391f, -0.193848f,
-0.367188f, -0.507812f, 0.367188f, -0.52832f, 0.362793f, -0.545654f, 0.358398f, -0.562988f,
-0.348145f, -0.575439f, 0.337891f, -0.587891f, 0.320557f, -0.594971f, 0.303223f, -0.602051f,
-0.276855f, -0.602051f, 0.251465f, -0.602051f, 0.234375f, -0.594971f, 0.217285f, -0.587891f,
-0.207031f, -0.575439f, 0.196777f, -0.562988f, 0.192383f, -0.545654f, 0.187988f, -0.52832f,
-0.187988f, -0.507812f, 0.187988f, -0.489746f, 0.19165f, -0.472168f, 0.195312f, -0.45459f,
-0.205078f, -0.440674f, 0.214844f, -0.426758f, 0.232422f, -0.417969f, 0.25f, -0.40918f,
-0.277832f, -0.40918f, 0.307129f, -0.40918f, 0.324951f, -0.417969f, 0.342773f, -0.426758f,
-0.352051f, -0.440918f, 0.361328f, -0.455078f, 0.364258f, -0.472656f, 0.367188f, -0.490234f,
-0.367188f, -0.507812f, 0.383301f, -0.205078f, 0.383301f, -0.226074f, 0.378662f, -0.245605f,
-0.374023f, -0.265137f, 0.362061f, -0.280029f, 0.350098f, -0.294922f, 0.329102f, -0.303955f,
-0.308105f, -0.312988f, 0.275879f, -0.312988f, 0.246582f, -0.312988f, 0.226807f, -0.303955f,
-0.207031f, -0.294922f, 0.195068f, -0.279785f, 0.183105f, -0.264648f, 0.177979f, -0.244873f,
-0.172852f, -0.225098f, 0.172852f, -0.203125f, 0.172852f, -0.177246f, 0.177979f, -0.155762f,
-0.183105f, -0.134277f, 0.195557f, -0.118896f, 0.208008f, -0.103516f, 0.228516f, -0.0952148f,
-0.249023f, -0.0869141f, 0.279785f, -0.0869141f, 0.310547f, -0.0869141f, 0.330566f,
--0.095459f, 0.350586f, -0.104004f, 0.362305f, -0.119629f, 0.374023f, -0.135254f,
-0.378662f, -0.156982f, 0.383301f, -0.178711f, 0.383301f, -0.205078f, 0.519043f, -0.35498f,
-0.519043f, -0.171875f, 0.452148f, -0.0810547f, 0.385254f, 0.00976562f, 0.262207f,
-0.00976562f, 0.217773f, 0.00976562f, 0.182373f, 0.000488281f, 0.146973f, -0.00878906f,
-0.120605f, -0.0283203f, 0.0942383f, -0.0478516f, 0.0759277f, -0.0786133f, 0.0576172f,
--0.109375f, 0.046875f, -0.151855f, 0.175781f, -0.169922f, 0.185547f, -0.133301f,
-0.207764f, -0.115723f, 0.22998f, -0.0981445f, 0.263672f, -0.0981445f, 0.291504f,
--0.0981445f, 0.313477f, -0.111328f, 0.335449f, -0.124512f, 0.351074f, -0.151367f,
-0.366699f, -0.178223f, 0.375244f, -0.219482f, 0.383789f, -0.260742f, 0.384277f, -0.316895f,
-0.374512f, -0.297852f, 0.358398f, -0.283203f, 0.342285f, -0.268555f, 0.322021f, -0.258789f,
-0.301758f, -0.249023f, 0.278809f, -0.243896f, 0.255859f, -0.23877f, 0.232422f, -0.23877f,
-0.1875f, -0.23877f, 0.150879f, -0.254639f, 0.114258f, -0.270508f, 0.0883789f, -0.300293f,
-0.0625f, -0.330078f, 0.048584f, -0.372314f, 0.034668f, -0.414551f, 0.034668f, -0.467773f,
-0.034668f, -0.522461f, 0.0510254f, -0.56543f, 0.0673828f, -0.608398f, 0.0981445f,
--0.637939f, 0.128906f, -0.66748f, 0.173584f, -0.682861f, 0.218262f, -0.698242f, 0.274902f,
--0.698242f, 0.334473f, -0.698242f, 0.380127f, -0.677979f, 0.425781f, -0.657715f,
-0.456543f, -0.615479f, 0.487305f, -0.573242f, 0.503174f, -0.508545f, 0.519043f, -0.443848f,
-0.519043f, -0.35498f, 0.374023f, -0.451172f, 0.374023f, -0.480469f, 0.367432f, -0.506104f,
-0.36084f, -0.531738f, 0.347656f, -0.550537f, 0.334473f, -0.569336f, 0.31543f, -0.580078f,
-0.296387f, -0.59082f, 0.271484f, -0.59082f, 0.248535f, -0.59082f, 0.230469f, -0.582275f,
-0.212402f, -0.57373f, 0.199707f, -0.557617f, 0.187012f, -0.541504f, 0.18042f, -0.518555f,
-0.173828f, -0.495605f, 0.173828f, -0.466797f, 0.173828f, -0.439941f, 0.180176f, -0.416748f,
-0.186523f, -0.393555f, 0.19873f, -0.376709f, 0.210938f, -0.359863f, 0.229492f, -0.350342f,
-0.248047f, -0.34082f, 0.271973f, -0.34082f, 0.291016f, -0.34082f, 0.309326f, -0.347656f,
-0.327637f, -0.354492f, 0.342041f, -0.368164f, 0.356445f, -0.381836f, 0.365234f, -0.402588f,
-0.374023f, -0.42334f, 0.374023f, -0.451172f, 0.0961914f, -0.367188f, 0.0961914f,
--0.504883f, 0.236816f, -0.504883f, 0.236816f, -0.367188f, 0.0961914f, 0, 0.0961914f,
--0.137207f, 0.236816f, -0.137207f, 0.236816f, 0, 0.097168f, -0.367188f, 0.097168f,
--0.504883f, 0.237793f, -0.504883f, 0.237793f, -0.367188f, 0.237793f, -0.0322266f,
-0.237793f, 0.000488281f, 0.234131f, 0.0273438f, 0.230469f, 0.0541992f, 0.223633f,
-0.0769043f, 0.216797f, 0.0996094f, 0.207031f, 0.118652f, 0.197266f, 0.137695f, 0.185059f,
-0.154785f, 0.0952148f, 0.154785f, 0.108887f, 0.137695f, 0.12085f, 0.118652f, 0.132812f,
-0.0996094f, 0.141602f, 0.0795898f, 0.150391f, 0.0595703f, 0.155273f, 0.0395508f,
-0.160156f, 0.0195312f, 0.160156f, 0, 0.097168f, 0, 0.097168f, -0.137207f, 0.237793f,
--0.137207f, 0.0415039f, -0.411133f, 0.0415039f, -0.52002f, 0.542969f, -0.52002f,
-0.542969f, -0.411133f, 0.0415039f, -0.14209f, 0.0415039f, -0.25f, 0.542969f, -0.25f,
-0.542969f, -0.14209f, 0.0419922f, -0.0610352f, 0.0419922f, -0.171875f, 0.448242f,
--0.330078f, 0.0419922f, -0.48877f, 0.0419922f, -0.600098f, 0.543457f, -0.40918f,
-0.543457f, -0.251953f, 0.553223f, -0.500977f, 0.553223f, -0.46875f, 0.544678f, -0.444336f,
-0.536133f, -0.419922f, 0.521973f, -0.400635f, 0.507812f, -0.381348f, 0.489746f, -0.365967f,
-0.47168f, -0.350586f, 0.452637f, -0.336914f, 0.433594f, -0.323242f, 0.415283f, -0.310059f,
-0.396973f, -0.296875f, 0.382324f, -0.281982f, 0.367676f, -0.26709f, 0.358398f, -0.249268f,
-0.349121f, -0.231445f, 0.348145f, -0.208008f, 0.217773f, -0.208008f, 0.220215f, -0.249512f,
-0.235596f, -0.279053f, 0.250977f, -0.308594f, 0.272949f, -0.330566f, 0.294922f, -0.352539f,
-0.319824f, -0.369873f, 0.344727f, -0.387207f, 0.365967f, -0.405273f, 0.387207f, -0.42334f,
-0.401123f, -0.44458f, 0.415039f, -0.46582f, 0.415039f, -0.495117f, 0.415039f, -0.538086f,
-0.386963f, -0.562988f, 0.358887f, -0.587891f, 0.307129f, -0.587891f, 0.282227f, -0.587891f,
-0.26123f, -0.580322f, 0.240234f, -0.572754f, 0.224365f, -0.559082f, 0.208496f, -0.54541f,
-0.198242f, -0.525879f, 0.187988f, -0.506348f, 0.185059f, -0.48291f, 0.0458984f, -0.48877f,
-0.0517578f, -0.532227f, 0.0700684f, -0.570312f, 0.0883789f, -0.608398f, 0.120117f,
--0.636719f, 0.151855f, -0.665039f, 0.197998f, -0.681641f, 0.244141f, -0.698242f,
-0.305176f, -0.698242f, 0.36377f, -0.698242f, 0.409668f, -0.68457f, 0.455566f, -0.670898f,
-0.487549f, -0.645264f, 0.519531f, -0.619629f, 0.536377f, -0.583008f, 0.553223f, -0.546387f,
-0.553223f, -0.500977f, 0.213867f, 0, 0.213867f, -0.131836f, 0.35498f, -0.131836f,
-0.35498f, 0, 0.553223f, 0, 0.492188f, -0.175781f, 0.22998f, -0.175781f, 0.168945f,
-0, 0.0249023f, 0, 0.275879f, -0.687988f, 0.445801f, -0.687988f, 0.695801f, 0, 0.39209f,
--0.481934f, 0.38623f, -0.499023f, 0.380615f, -0.516357f, 0.375f, -0.533691f, 0.37085f,
--0.548096f, 0.366699f, -0.5625f, 0.364014f, -0.571777f, 0.361328f, -0.581055f, 0.36084f,
--0.582031f, 0.360352f, -0.580566f, 0.35791f, -0.571289f, 0.355469f, -0.562012f, 0.351318f,
--0.547852f, 0.347168f, -0.533691f, 0.341553f, -0.516357f, 0.335938f, -0.499023f,
-0.330078f, -0.481934f, 0.262207f, -0.28418f, 0.459961f, -0.28418f, 0.676758f, -0.196289f,
-0.676758f, -0.144043f, 0.655762f, -0.106689f, 0.634766f, -0.0693359f, 0.598389f,
--0.0456543f, 0.562012f, -0.0219727f, 0.513672f, -0.0109863f, 0.465332f, 0, 0.411133f,
-0, 0.0668945f, 0, 0.0668945f, -0.687988f, 0.381836f, -0.687988f, 0.442871f, -0.687988f,
-0.490479f, -0.67749f, 0.538086f, -0.666992f, 0.570801f, -0.645508f, 0.603516f, -0.624023f,
-0.620361f, -0.591553f, 0.637207f, -0.559082f, 0.637207f, -0.515137f, 0.637207f, -0.456543f,
-0.604736f, -0.41626f, 0.572266f, -0.375977f, 0.505859f, -0.361816f, 0.589355f, -0.352051f,
-0.633057f, -0.309326f, 0.676758f, -0.266602f, 0.676758f, -0.196289f, 0.492188f, -0.495605f,
-0.492188f, -0.541992f, 0.462646f, -0.561523f, 0.433105f, -0.581055f, 0.375f, -0.581055f,
-0.210938f, -0.581055f, 0.210938f, -0.410645f, 0.375977f, -0.410645f, 0.437012f, -0.410645f,
-0.4646f, -0.431885f, 0.492188f, -0.453125f, 0.492188f, -0.495605f, 0.532227f, -0.20752f,
-0.532227f, -0.234863f, 0.521484f, -0.253418f, 0.510742f, -0.271973f, 0.491943f, -0.283203f,
-0.473145f, -0.294434f, 0.447998f, -0.299316f, 0.422852f, -0.304199f, 0.393555f, -0.304199f,
-0.210938f, -0.304199f, 0.210938f, -0.106934f, 0.398926f, -0.106934f, 0.427246f, -0.106934f,
-0.45166f, -0.111572f, 0.476074f, -0.116211f, 0.493896f, -0.127686f, 0.511719f, -0.13916f,
-0.521973f, -0.158691f, 0.532227f, -0.178223f, 0.532227f, -0.20752f, 0.388184f, -0.103516f,
-0.428711f, -0.103516f, 0.458252f, -0.11499f, 0.487793f, -0.126465f, 0.509521f, -0.14502f,
-0.53125f, -0.163574f, 0.545654f, -0.187012f, 0.560059f, -0.210449f, 0.569336f, -0.234375f,
-0.694824f, -0.187012f, 0.679688f, -0.149902f, 0.655273f, -0.114258f, 0.630859f, -0.0786133f,
-0.594238f, -0.0512695f, 0.557617f, -0.0239258f, 0.50708f, -0.00708008f, 0.456543f,
-0.00976562f, 0.388184f, 0.00976562f, 0.298828f, 0.00976562f, 0.233398f, -0.0168457f,
-0.167969f, -0.043457f, 0.125244f, -0.0910645f, 0.0825195f, -0.138672f, 0.0617676f,
--0.204102f, 0.0410156f, -0.269531f, 0.0410156f, -0.347168f, 0.0410156f, -0.427734f,
-0.0617676f, -0.492676f, 0.0825195f, -0.557617f, 0.124512f, -0.603271f, 0.166504f,
--0.648926f, 0.230713f, -0.673584f, 0.294922f, -0.698242f, 0.381836f, -0.698242f,
-0.449219f, -0.698242f, 0.499756f, -0.684082f, 0.550293f, -0.669922f, 0.587158f, -0.644287f,
-0.624023f, -0.618652f, 0.648193f, -0.58374f, 0.672363f, -0.548828f, 0.686035f, -0.506836f,
-0.559082f, -0.472168f, 0.552246f, -0.494141f, 0.538086f, -0.514404f, 0.523926f, -0.534668f,
-0.502197f, -0.550293f, 0.480469f, -0.565918f, 0.451172f, -0.575439f, 0.421875f, -0.584961f,
-0.384766f, -0.584961f, 0.33252f, -0.584961f, 0.294922f, -0.568115f, 0.257324f, -0.55127f,
-0.233154f, -0.52002f, 0.208984f, -0.48877f, 0.19751f, -0.445068f, 0.186035f, -0.401367f,
-0.186035f, -0.347168f, 0.186035f, -0.293457f, 0.19751f, -0.248779f, 0.208984f, -0.204102f,
-0.233398f, -0.171875f, 0.257812f, -0.139648f, 0.296143f, -0.121582f, 0.334473f, -0.103516f,
-0.388184f, -0.103516f, 0.680176f, -0.349121f, 0.680176f, -0.263184f, 0.654297f, -0.197998f,
-0.628418f, -0.132812f, 0.583496f, -0.0888672f, 0.538574f, -0.0449219f, 0.477295f,
--0.0224609f, 0.416016f, 0, 0.345215f, 0, 0.0668945f, 0, 0.0668945f, -0.687988f, 0.315918f,
--0.687988f, 0.395996f, -0.687988f, 0.462891f, -0.667969f, 0.529785f, -0.647949f,
-0.578125f, -0.606445f, 0.626465f, -0.564941f, 0.65332f, -0.500977f, 0.680176f, -0.437012f,
-0.680176f, -0.349121f, 0.535156f, -0.349121f, 0.535156f, -0.40918f, 0.518799f, -0.452148f,
-0.502441f, -0.495117f, 0.473145f, -0.522705f, 0.443848f, -0.550293f, 0.403076f, -0.563477f,
-0.362305f, -0.57666f, 0.312988f, -0.57666f, 0.210938f, -0.57666f, 0.210938f, -0.111328f,
-0.333008f, -0.111328f, 0.376465f, -0.111328f, 0.41333f, -0.126465f, 0.450195f, -0.141602f,
-0.477295f, -0.171631f, 0.504395f, -0.20166f, 0.519775f, -0.246094f, 0.535156f, -0.290527f,
-0.535156f, -0.349121f, 0.0668945f, 0, 0.0668945f, -0.687988f, 0.60791f, -0.687988f,
-0.60791f, -0.57666f, 0.210938f, -0.57666f, 0.210938f, -0.403809f, 0.578125f, -0.403809f,
-0.578125f, -0.29248f, 0.210938f, -0.29248f, 0.210938f, -0.111328f, 0.62793f, -0.111328f,
-0.62793f, 0, 0.210938f, -0.57666f, 0.210938f, -0.36377f, 0.562988f, -0.36377f, 0.562988f,
--0.252441f, 0.210938f, -0.252441f, 0.210938f, 0, 0.0668945f, 0, 0.0668945f, -0.687988f,
-0.574219f, -0.687988f, 0.574219f, -0.57666f, 0.393555f, -0.103027f, 0.424805f, -0.103027f,
-0.453613f, -0.10791f, 0.482422f, -0.112793f, 0.50708f, -0.12085f, 0.531738f, -0.128906f,
-0.551514f, -0.139404f, 0.571289f, -0.149902f, 0.583984f, -0.161133f, 0.583984f, -0.256348f,
-0.416016f, -0.256348f, 0.416016f, -0.362793f, 0.71582f, -0.362793f, 0.71582f, -0.109863f,
-0.692383f, -0.0859375f, 0.65918f, -0.064209f, 0.625977f, -0.0424805f, 0.584473f,
--0.026123f, 0.542969f, -0.00976562f, 0.493896f, 0, 0.444824f, 0.00976562f, 0.389648f,
-0.00976562f, 0.29834f, 0.00976562f, 0.232422f, -0.0168457f, 0.166504f, -0.043457f,
-0.124023f, -0.0910645f, 0.081543f, -0.138672f, 0.0612793f, -0.204102f, 0.0410156f,
--0.269531f, 0.0410156f, -0.347168f, 0.0410156f, -0.427734f, 0.0625f, -0.492676f,
-0.0839844f, -0.557617f, 0.127686f, -0.603271f, 0.171387f, -0.648926f, 0.237549f,
--0.673584f, 0.303711f, -0.698242f, 0.393066f, -0.698242f, 0.458008f, -0.698242f,
-0.508545f, -0.685547f, 0.559082f, -0.672852f, 0.596924f, -0.649414f, 0.634766f, -0.625977f,
-0.6604f, -0.593018f, 0.686035f, -0.560059f, 0.701172f, -0.519043f, 0.568359f, -0.479004f,
-0.55957f, -0.500488f, 0.544922f, -0.519775f, 0.530273f, -0.539062f, 0.508545f, -0.553467f,
-0.486816f, -0.567871f, 0.458252f, -0.576416f, 0.429688f, -0.584961f, 0.393066f, -0.584961f,
-0.339355f, -0.584961f, 0.300293f, -0.568115f, 0.26123f, -0.55127f, 0.23584f, -0.52002f,
-0.210449f, -0.48877f, 0.198242f, -0.445068f, 0.186035f, -0.401367f, 0.186035f, -0.347168f,
-0.186035f, -0.293457f, 0.198486f, -0.248535f, 0.210938f, -0.203613f, 0.236572f, -0.171387f,
-0.262207f, -0.13916f, 0.30127f, -0.121094f, 0.340332f, -0.103027f, 0.393555f, -0.103027f,
-0.510742f, 0, 0.510742f, -0.294922f, 0.210938f, -0.294922f, 0.210938f, 0, 0.0668945f,
-0, 0.0668945f, -0.687988f, 0.210938f, -0.687988f, 0.210938f, -0.414062f, 0.510742f,
--0.414062f, 0.510742f, -0.687988f, 0.654785f, -0.687988f, 0.654785f, 0, 0.0668945f,
-0, 0.0668945f, -0.687988f, 0.210938f, -0.687988f, 0.210938f, 0, 0.255859f, 0.00976562f,
-0.204102f, 0.00976562f, 0.163574f, -0.000976562f, 0.123047f, -0.0117188f, 0.0932617f,
--0.0351562f, 0.0634766f, -0.0585938f, 0.0441895f, -0.0959473f, 0.0249023f, -0.133301f,
-0.0151367f, -0.186523f, 0.158203f, -0.20752f, 0.163086f, -0.178711f, 0.171875f, -0.158936f,
-0.180664f, -0.13916f, 0.193115f, -0.126709f, 0.205566f, -0.114258f, 0.22168f, -0.108643f,
-0.237793f, -0.103027f, 0.256836f, -0.103027f, 0.299805f, -0.103027f, 0.322021f, -0.131836f,
-0.344238f, -0.160645f, 0.344238f, -0.214355f, 0.344238f, -0.575195f, 0.207031f, -0.575195f,
-0.207031f, -0.687988f, 0.487793f, -0.687988f, 0.487793f, -0.217773f, 0.487793f, -0.165527f,
-0.472656f, -0.123291f, 0.45752f, -0.0810547f, 0.427979f, -0.0515137f, 0.398438f,
--0.0219727f, 0.355225f, -0.00610352f, 0.312012f, 0.00976562f, 0.255859f, 0.00976562f,
-0.0668945f, 0, 0.0668945f, -0.687988f, 0.210938f, -0.687988f, 0.210938f, -0.111328f,
-0.580078f, -0.111328f, 0.580078f, 0, 0.638184f, 0, 0.638184f, -0.416992f, 0.638184f,
--0.441895f, 0.638916f, -0.468262f, 0.639648f, -0.494629f, 0.640625f, -0.516602f,
-0.64209f, -0.54248f, 0.643066f, -0.566895f, 0.632812f, -0.52832f, 0.623535f, -0.493652f,
-0.619629f, -0.479004f, 0.615234f, -0.463379f, 0.61084f, -0.447754f, 0.606689f, -0.433105f,
-0.602539f, -0.418457f, 0.598633f, -0.405762f, 0.594727f, -0.393066f, 0.591797f, -0.383789f,
-0.467773f, 0, 0.365234f, 0, 0.241211f, -0.383789f, 0.238281f, -0.393066f, 0.234619f,
--0.405762f, 0.230957f, -0.418457f, 0.226807f, -0.433105f, 0.222656f, -0.447754f,
-0.218262f, -0.463379f, 0.213867f, -0.479004f, 0.209473f, -0.493652f, 0.199707f, -0.52832f,
-0.188965f, -0.566895f, 0.19043f, -0.538574f, 0.191895f, -0.51123f, 0.192871f, -0.487793f,
-0.193848f, -0.461914f, 0.194824f, -0.436035f, 0.194824f, -0.416992f, 0.194824f, 0,
-0.0668945f, 0, 0.0668945f, -0.687988f, 0.259766f, -0.687988f, 0.382812f, -0.303223f,
-0.387695f, -0.288086f, 0.393311f, -0.266113f, 0.398926f, -0.244141f, 0.404297f, -0.223633f,
-0.410156f, -0.199707f, 0.416992f, -0.173828f, 0.423828f, -0.199219f, 0.430176f, -0.222656f,
-0.433105f, -0.23291f, 0.436035f, -0.243652f, 0.438965f, -0.254395f, 0.441895f, -0.264648f,
-0.444824f, -0.274902f, 0.447754f, -0.28418f, 0.450684f, -0.293457f, 0.453125f, -0.300781f,
-0.574219f, -0.687988f, 0.766113f, -0.687988f, 0.766113f, 0, 0.73584f, -0.347168f,
-0.73584f, -0.266602f, 0.711914f, -0.200684f, 0.687988f, -0.134766f, 0.643066f, -0.0878906f,
-0.598145f, -0.0410156f, 0.533447f, -0.015625f, 0.46875f, 0.00976562f, 0.387207f,
-0.00976562f, 0.300781f, 0.00976562f, 0.236084f, -0.0168457f, 0.171387f, -0.043457f,
-0.12793f, -0.0910645f, 0.0844727f, -0.138672f, 0.0627441f, -0.204102f, 0.0410156f,
--0.269531f, 0.0410156f, -0.347168f, 0.0410156f, -0.427734f, 0.0637207f, -0.492676f,
-0.0864258f, -0.557617f, 0.130615f, -0.603271f, 0.174805f, -0.648926f, 0.239502f,
--0.673584f, 0.304199f, -0.698242f, 0.388184f, -0.698242f, 0.472168f, -0.698242f,
-0.536865f, -0.67334f, 0.601562f, -0.648438f, 0.645752f, -0.602539f, 0.689941f, -0.556641f,
-0.712891f, -0.491943f, 0.73584f, -0.427246f, 0.73584f, -0.347168f, 0.588867f, -0.347168f,
-0.588867f, -0.401367f, 0.575928f, -0.445068f, 0.562988f, -0.48877f, 0.537598f, -0.52002f,
-0.512207f, -0.55127f, 0.474854f, -0.568115f, 0.4375f, -0.584961f, 0.388184f, -0.584961f,
-0.337891f, -0.584961f, 0.300049f, -0.568115f, 0.262207f, -0.55127f, 0.236816f, -0.52002f,
-0.211426f, -0.48877f, 0.19873f, -0.445068f, 0.186035f, -0.401367f, 0.186035f, -0.347168f,
-0.186035f, -0.293457f, 0.198975f, -0.248779f, 0.211914f, -0.204102f, 0.237305f, -0.171875f,
-0.262695f, -0.139648f, 0.300293f, -0.121582f, 0.337891f, -0.103516f, 0.387207f, -0.103516f,
-0.439941f, -0.103516f, 0.478027f, -0.121826f, 0.516113f, -0.140137f, 0.540771f, -0.172607f,
-0.56543f, -0.205078f, 0.577148f, -0.249756f, 0.588867f, -0.294434f, 0.588867f, -0.347168f,
-0.539551f, 0, 0.379883f, -0.26123f, 0.210938f, -0.26123f, 0.210938f, 0, 0.0668945f,
-0, 0.0668945f, -0.687988f, 0.410645f, -0.687988f, 0.475098f, -0.687988f, 0.523193f,
--0.673584f, 0.571289f, -0.65918f, 0.603516f, -0.632568f, 0.635742f, -0.605957f, 0.651611f,
--0.568115f, 0.66748f, -0.530273f, 0.66748f, -0.48291f, 0.66748f, -0.444336f, 0.656006f,
--0.412354f, 0.644531f, -0.380371f, 0.624268f, -0.355469f, 0.604004f, -0.330566f,
-0.576172f, -0.313721f, 0.54834f, -0.296875f, 0.515625f, -0.289062f, 0.70166f, 0,
-0.522461f, -0.477051f, 0.522461f, -0.527344f, 0.489502f, -0.551758f, 0.456543f, -0.576172f,
-0.395508f, -0.576172f, 0.210938f, -0.576172f, 0.210938f, -0.373047f, 0.399414f, -0.373047f,
-0.431641f, -0.373047f, 0.454834f, -0.380615f, 0.478027f, -0.388184f, 0.49292f, -0.4021f,
-0.507812f, -0.416016f, 0.515137f, -0.435059f, 0.522461f, -0.454102f, 0.522461f, -0.477051f,
-0.62793f, -0.198242f, 0.62793f, -0.151367f, 0.61084f, -0.113037f, 0.59375f, -0.074707f,
-0.557861f, -0.0473633f, 0.521973f, -0.0200195f, 0.466064f, -0.00512695f, 0.410156f,
-0.00976562f, 0.333008f, 0.00976562f, 0.264648f, 0.00976562f, 0.212402f, -0.00244141f,
-0.160156f, -0.0146484f, 0.122803f, -0.0385742f, 0.0854492f, -0.0625f, 0.0622559f,
--0.0979004f, 0.0390625f, -0.133301f, 0.0288086f, -0.179199f, 0.167969f, -0.202148f,
-0.173828f, -0.179199f, 0.185059f, -0.160156f, 0.196289f, -0.141113f, 0.216064f, -0.127197f,
-0.23584f, -0.113281f, 0.265381f, -0.105713f, 0.294922f, -0.0981445f, 0.336914f, -0.0981445f,
-0.410156f, -0.0981445f, 0.448975f, -0.120361f, 0.487793f, -0.142578f, 0.487793f,
--0.189941f, 0.487793f, -0.218262f, 0.472168f, -0.236328f, 0.456543f, -0.254395f,
-0.430664f, -0.266113f, 0.404785f, -0.277832f, 0.371094f, -0.285645f, 0.337402f, -0.293457f,
-0.300781f, -0.300781f, 0.271484f, -0.307617f, 0.242188f, -0.314941f, 0.212891f, -0.322266f,
-0.186279f, -0.33252f, 0.159668f, -0.342773f, 0.136719f, -0.356934f, 0.11377f, -0.371094f,
-0.0969238f, -0.391846f, 0.0800781f, -0.412598f, 0.0705566f, -0.44043f, 0.0610352f,
--0.468262f, 0.0610352f, -0.505859f, 0.0610352f, -0.557129f, 0.081543f, -0.59375f,
-0.102051f, -0.630371f, 0.138428f, -0.653564f, 0.174805f, -0.676758f, 0.225098f, -0.6875f,
-0.275391f, -0.698242f, 0.334961f, -0.698242f, 0.402344f, -0.698242f, 0.450439f, -0.687744f,
-0.498535f, -0.677246f, 0.531006f, -0.655762f, 0.563477f, -0.634277f, 0.582275f, -0.601807f,
-0.601074f, -0.569336f, 0.609863f, -0.525879f, 0.470215f, -0.506836f, 0.459473f, -0.55127f,
-0.426514f, -0.57373f, 0.393555f, -0.596191f, 0.332031f, -0.596191f, 0.293945f, -0.596191f,
-0.268799f, -0.5896f, 0.243652f, -0.583008f, 0.22876f, -0.571777f, 0.213867f, -0.560547f,
-0.20752f, -0.545654f, 0.201172f, -0.530762f, 0.201172f, -0.51416f, 0.201172f, -0.48877f,
-0.213379f, -0.472412f, 0.225586f, -0.456055f, 0.247559f, -0.445068f, 0.269531f, -0.434082f,
-0.300049f, -0.426514f, 0.330566f, -0.418945f, 0.367188f, -0.411133f, 0.399414f, -0.404297f,
-0.431152f, -0.396729f, 0.462891f, -0.38916f, 0.491699f, -0.378906f, 0.520508f, -0.368652f,
-0.54541f, -0.354004f, 0.570312f, -0.339355f, 0.588623f, -0.318115f, 0.606934f, -0.296875f,
-0.617432f, -0.267578f, 0.62793f, -0.238281f, 0.62793f, -0.198242f, 0.377441f, -0.57666f,
-0.377441f, 0, 0.233398f, 0, 0.233398f, -0.57666f, 0.0112305f, -0.57666f, 0.0112305f,
--0.687988f, 0.600098f, -0.687988f, 0.600098f, -0.57666f, 0.353027f, 0.00976562f,
-0.288574f, 0.00976562f, 0.234863f, -0.00561523f, 0.181152f, -0.0209961f, 0.142334f,
--0.0534668f, 0.103516f, -0.0859375f, 0.0817871f, -0.136719f, 0.0600586f, -0.1875f,
-0.0600586f, -0.257812f, 0.0600586f, -0.687988f, 0.204102f, -0.687988f, 0.204102f,
--0.269043f, 0.204102f, -0.225586f, 0.214844f, -0.194092f, 0.225586f, -0.162598f,
-0.245605f, -0.142334f, 0.265625f, -0.12207f, 0.293945f, -0.112549f, 0.322266f, -0.103027f,
-0.356934f, -0.103027f, 0.39209f, -0.103027f, 0.421631f, -0.113037f, 0.451172f, -0.123047f,
-0.472412f, -0.144043f, 0.493652f, -0.165039f, 0.505371f, -0.197266f, 0.51709f, -0.229492f,
-0.51709f, -0.273926f, 0.51709f, -0.687988f, 0.661133f, -0.687988f, 0.661133f, -0.265137f,
-0.661133f, -0.194336f, 0.638184f, -0.142578f, 0.615234f, -0.0908203f, 0.574219f,
--0.0568848f, 0.533203f, -0.0229492f, 0.476807f, -0.0065918f, 0.42041f, 0.00976562f,
-0.353027f, 0.00976562f, 0.407227f, 0, 0.26123f, 0, 0.00683594f, -0.687988f, 0.157227f,
--0.687988f, 0.298828f, -0.246094f, 0.305664f, -0.224121f, 0.312012f, -0.201172f,
-0.318359f, -0.178223f, 0.32373f, -0.15918f, 0.32959f, -0.136719f, 0.334961f, -0.116211f,
-0.339844f, -0.13623f, 0.345215f, -0.158203f, 0.350098f, -0.176758f, 0.356689f, -0.199951f,
-0.363281f, -0.223145f, 0.370117f, -0.246094f, 0.51123f, -0.687988f, 0.660156f, -0.687988f,
-0.765137f, 0, 0.594238f, 0, 0.500977f, -0.397949f, 0.496582f, -0.416016f, 0.491455f,
--0.440918f, 0.486328f, -0.46582f, 0.481934f, -0.489258f, 0.476562f, -0.516113f, 0.472168f,
--0.544922f, 0.466797f, -0.516113f, 0.461426f, -0.48877f, 0.458984f, -0.477051f, 0.456543f,
--0.4646f, 0.454102f, -0.452148f, 0.451416f, -0.440186f, 0.44873f, -0.428223f, 0.446533f,
--0.41748f, 0.444336f, -0.406738f, 0.441895f, -0.397949f, 0.349121f, 0, 0.178223f,
-0, 0.000976562f, -0.687988f, 0.146973f, -0.687988f, 0.23291f, -0.305176f, 0.240234f,
--0.273926f, 0.246582f, -0.243652f, 0.25293f, -0.213379f, 0.258301f, -0.189453f, 0.26416f,
--0.161621f, 0.269043f, -0.13623f, 0.276367f, -0.172363f, 0.283203f, -0.206543f, 0.286133f,
--0.221191f, 0.289551f, -0.236816f, 0.292969f, -0.252441f, 0.296143f, -0.267578f,
-0.299316f, -0.282715f, 0.30249f, -0.296631f, 0.305664f, -0.310547f, 0.308105f, -0.321777f,
-0.393066f, -0.687988f, 0.554199f, -0.687988f, 0.641113f, -0.321777f, 0.644043f, -0.310059f,
-0.646973f, -0.295654f, 0.649902f, -0.28125f, 0.652832f, -0.265869f, 0.655762f, -0.250488f,
-0.658691f, -0.235107f, 0.661621f, -0.219727f, 0.664062f, -0.205078f, 0.669922f, -0.170898f,
-0.675781f, -0.13623f, 0.681641f, -0.163574f, 0.687988f, -0.192871f, 0.693359f, -0.217773f,
-0.700195f, -0.247559f, 0.707031f, -0.277344f, 0.713867f, -0.305176f, 0.796875f, -0.687988f,
-0.942871f, -0.687988f, 0.506836f, 0, 0.333984f, -0.273926f, 0.161133f, 0, 0.00878906f,
-0, 0.24707f, -0.361816f, 0.0288086f, -0.687988f, 0.181152f, -0.687988f, 0.333984f,
--0.444824f, 0.486816f, -0.687988f, 0.638184f, -0.687988f, 0.429199f, -0.361816f,
-0.658203f, 0, 0.405762f, -0.282227f, 0.405762f, 0, 0.262207f, 0, 0.262207f, -0.282227f,
-0.0170898f, -0.687988f, 0.167969f, -0.687988f, 0.333008f, -0.396973f, 0.5f, -0.687988f,
-0.650879f, -0.687988f, 0.582031f, 0, 0.0297852f, 0, 0.0297852f, -0.102051f, 0.401855f,
--0.575195f, 0.0668945f, -0.575195f, 0.0668945f, -0.687988f, 0.562012f, -0.687988f,
-0.562012f, -0.587891f, 0.189941f, -0.112793f, 0.582031f, -0.112793f, 0.0561523f,
-0.20752f, 0.0561523f, -0.724609f, 0.320801f, -0.724609f, 0.320801f, -0.631836f, 0.186035f,
--0.631836f, 0.186035f, 0.114258f, 0.320801f, 0.114258f, 0.320801f, 0.20752f, 0.012207f,
-0.20752f, 0.012207f, 0.114258f, 0.147949f, 0.114258f, 0.147949f, -0.631836f, 0.012207f,
--0.631836f, 0.012207f, -0.724609f, 0.276855f, -0.724609f, 0.276855f, 0.20752f, 0.450195f,
--0.250977f, 0.291016f, -0.618164f, 0.132812f, -0.250977f, 0.0219727f, -0.250977f,
-0.212891f, -0.687988f, 0.370117f, -0.687988f, 0.562012f, -0.250977f, -0.00976562f,
-0.12207f, -0.00976562f, 0.0839844f, 0.564941f, 0.0839844f, 0.564941f, 0.12207f, 0.191895f,
-0.00976562f, 0.153809f, 0.00976562f, 0.123779f, -0.000732422f, 0.09375f, -0.0112305f,
-0.0727539f, -0.0314941f, 0.0517578f, -0.0517578f, 0.0405273f, -0.081543f, 0.0292969f,
--0.111328f, 0.0292969f, -0.149414f, 0.0292969f, -0.196289f, 0.0456543f, -0.228271f,
-0.0620117f, -0.260254f, 0.090332f, -0.280029f, 0.118652f, -0.299805f, 0.156738f,
--0.308838f, 0.194824f, -0.317871f, 0.237793f, -0.318359f, 0.351562f, -0.320312f,
-0.351562f, -0.347168f, 0.351562f, -0.375977f, 0.346436f, -0.395264f, 0.341309f, -0.414551f,
-0.331543f, -0.426758f, 0.321777f, -0.438965f, 0.307373f, -0.444092f, 0.292969f, -0.449219f,
-0.274414f, -0.449219f, 0.257324f, -0.449219f, 0.243896f, -0.445801f, 0.230469f, -0.442383f,
-0.220703f, -0.433838f, 0.210938f, -0.425293f, 0.204834f, -0.410889f, 0.19873f, -0.396484f,
-0.196289f, -0.374512f, 0.0532227f, -0.381348f, 0.059082f, -0.416016f, 0.074707f,
--0.44458f, 0.090332f, -0.473145f, 0.11792f, -0.494141f, 0.145508f, -0.515137f, 0.185791f,
--0.526611f, 0.226074f, -0.538086f, 0.280273f, -0.538086f, 0.32959f, -0.538086f, 0.368164f,
--0.525879f, 0.406738f, -0.513672f, 0.433594f, -0.489502f, 0.460449f, -0.465332f,
-0.474609f, -0.430176f, 0.48877f, -0.39502f, 0.48877f, -0.348633f, 0.48877f, -0.15625f,
-0.48877f, -0.137695f, 0.490479f, -0.123047f, 0.492188f, -0.108398f, 0.496826f, -0.0983887f,
-0.501465f, -0.0883789f, 0.51001f, -0.083252f, 0.518555f, -0.078125f, 0.532227f, -0.078125f,
-0.547852f, -0.078125f, 0.5625f, -0.0810547f, 0.5625f, -0.00683594f, 0.550293f, -0.00390625f,
-0.540527f, -0.00146484f, 0.530762f, 0.000976562f, 0.520996f, 0.00244141f, 0.51123f,
-0.00390625f, 0.500244f, 0.00488281f, 0.489258f, 0.00585938f, 0.474609f, 0.00585938f,
-0.422852f, 0.00585938f, 0.398193f, -0.0195312f, 0.373535f, -0.0449219f, 0.368652f,
--0.0942383f, 0.365723f, -0.0942383f, 0.338379f, -0.0449219f, 0.295654f, -0.0175781f,
-0.25293f, 0.00976562f, 0.191895f, 0.00976562f, 0.351562f, -0.244629f, 0.28125f, -0.243652f,
-0.259277f, -0.242676f, 0.239502f, -0.23999f, 0.219727f, -0.237305f, 0.204834f, -0.22876f,
-0.189941f, -0.220215f, 0.181152f, -0.204102f, 0.172363f, -0.187988f, 0.172363f, -0.160156f,
-0.172363f, -0.122559f, 0.189697f, -0.104248f, 0.207031f, -0.0859375f, 0.23584f, -0.0859375f,
-0.262207f, -0.0859375f, 0.283691f, -0.097168f, 0.305176f, -0.108398f, 0.320068f,
--0.126709f, 0.334961f, -0.14502f, 0.343262f, -0.168945f, 0.351562f, -0.192871f, 0.351562f,
--0.217773f, 0.569824f, -0.266113f, 0.569824f, -0.206055f, 0.557861f, -0.155518f,
-0.545898f, -0.10498f, 0.520996f, -0.0681152f, 0.496094f, -0.03125f, 0.457764f, -0.0107422f,
-0.419434f, 0.00976562f, 0.367188f, 0.00976562f, 0.34375f, 0.00976562f, 0.320312f,
-0.00488281f, 0.296875f, 0, 0.275879f, -0.0112305f, 0.254883f, -0.0224609f, 0.237305f,
--0.0405273f, 0.219727f, -0.0585938f, 0.207031f, -0.0849609f, 0.206055f, -0.0849609f,
-0.206055f, -0.074707f, 0.205322f, -0.0615234f, 0.20459f, -0.0483398f, 0.203613f,
--0.0358887f, 0.202637f, -0.0234375f, 0.201416f, -0.0136719f, 0.200195f, -0.00390625f,
-0.199219f, 0, 0.065918f, 0, 0.0673828f, -0.0170898f, 0.0686035f, -0.048584f, 0.0698242f,
--0.0800781f, 0.0698242f, -0.120605f, 0.0698242f, -0.724609f, 0.207031f, -0.724609f,
-0.207031f, -0.522461f, 0.207031f, -0.506836f, 0.206787f, -0.491943f, 0.206543f, -0.477051f,
-0.206055f, -0.464355f, 0.205566f, -0.449707f, 0.205078f, -0.436523f, 0.207031f, -0.436523f,
-0.231934f, -0.491211f, 0.275391f, -0.514648f, 0.318848f, -0.538086f, 0.375977f, -0.538086f,
-0.426758f, -0.538086f, 0.463379f, -0.517822f, 0.5f, -0.497559f, 0.523682f, -0.461182f,
-0.547363f, -0.424805f, 0.558594f, -0.375f, 0.569824f, -0.325195f, 0.569824f, -0.266113f,
-0.426758f, -0.266113f, 0.426758f, -0.355957f, 0.400391f, -0.399414f, 0.374023f, -0.442871f,
-0.318848f, -0.442871f, 0.297852f, -0.442871f, 0.277344f, -0.43457f, 0.256836f, -0.42627f,
-0.240723f, -0.405518f, 0.224609f, -0.384766f, 0.214844f, -0.349854f, 0.205078f, -0.314941f,
-0.205078f, -0.261719f, 0.205078f, -0.209961f, 0.214844f, -0.175781f, 0.224609f, -0.141602f,
-0.240234f, -0.121094f, 0.255859f, -0.100586f, 0.276367f, -0.0922852f, 0.296875f,
--0.0839844f, 0.317871f, -0.0839844f, 0.370117f, -0.0839844f, 0.398438f, -0.127197f,
-0.426758f, -0.17041f, 0.426758f, -0.266113f, 0.412109f, 0, 0.411133f, -0.00390625f,
-0.409912f, -0.013916f, 0.408691f, -0.0239258f, 0.407471f, -0.0366211f, 0.40625f,
--0.0493164f, 0.405518f, -0.0625f, 0.404785f, -0.0756836f, 0.404785f, -0.0859375f,
-0.402832f, -0.0859375f, 0.378906f, -0.034668f, 0.336182f, -0.0124512f, 0.293457f,
-0.00976562f, 0.233887f, 0.00976562f, 0.184082f, 0.00976562f, 0.147705f, -0.0107422f,
-0.111328f, -0.03125f, 0.0876465f, -0.0678711f, 0.0639648f, -0.104492f, 0.0524902f,
--0.154541f, 0.0410156f, -0.20459f, 0.0410156f, -0.263672f, 0.0410156f, -0.32373f,
-0.0529785f, -0.374023f, 0.0649414f, -0.424316f, 0.0898438f, -0.460693f, 0.114746f,
--0.49707f, 0.153076f, -0.517578f, 0.191406f, -0.538086f, 0.244141f, -0.538086f, 0.27002f,
--0.538086f, 0.293945f, -0.532715f, 0.317871f, -0.527344f, 0.338379f, -0.516113f,
-0.358887f, -0.504883f, 0.375488f, -0.487305f, 0.39209f, -0.469727f, 0.403809f, -0.444824f,
-0.404785f, -0.444824f, 0.404785f, -0.449707f, 0.404541f, -0.459229f, 0.404297f, -0.46875f,
-0.404297f, -0.480957f, 0.404297f, -0.493164f, 0.404053f, -0.506348f, 0.403809f, -0.519531f,
-0.403809f, -0.531738f, 0.403809f, -0.724609f, 0.541016f, -0.724609f, 0.541016f, -0.115234f,
-0.541016f, -0.0766602f, 0.54248f, -0.0466309f, 0.543945f, -0.0166016f, 0.544922f,
-0, 0.405762f, -0.26709f, 0.405762f, -0.319336f, 0.395996f, -0.35376f, 0.38623f, -0.388184f,
-0.370361f, -0.408447f, 0.354492f, -0.428711f, 0.334229f, -0.436768f, 0.313965f, -0.444824f,
-0.292969f, -0.444824f, 0.266602f, -0.444824f, 0.246338f, -0.43457f, 0.226074f, -0.424316f,
-0.212158f, -0.402344f, 0.198242f, -0.380371f, 0.191162f, -0.346191f, 0.184082f, -0.312012f,
-0.184082f, -0.263672f, 0.184082f, -0.0839844f, 0.291992f, -0.0839844f, 0.3125f, -0.0839844f,
-0.333008f, -0.0927734f, 0.353516f, -0.101562f, 0.369629f, -0.122559f, 0.385742f,
--0.143555f, 0.395752f, -0.178955f, 0.405762f, -0.214355f, 0.405762f, -0.26709f, 0.286133f,
-0.00976562f, 0.229004f, 0.00976562f, 0.18335f, -0.00708008f, 0.137695f, -0.0239258f,
-0.105469f, -0.0583496f, 0.0732422f, -0.0927734f, 0.0561523f, -0.144775f, 0.0390625f,
--0.196777f, 0.0390625f, -0.266602f, 0.0390625f, -0.342285f, 0.0593262f, -0.394043f,
-0.0795898f, -0.445801f, 0.114014f, -0.477783f, 0.148438f, -0.509766f, 0.193359f,
--0.523926f, 0.238281f, -0.538086f, 0.288086f, -0.538086f, 0.350586f, -0.538086f,
-0.394775f, -0.516357f, 0.438965f, -0.494629f, 0.467285f, -0.455566f, 0.495605f, -0.416504f,
-0.508789f, -0.362061f, 0.521973f, -0.307617f, 0.521973f, -0.241699f, 0.521973f, -0.237793f,
-0.183105f, -0.237793f, 0.183105f, -0.20459f, 0.188965f, -0.176025f, 0.194824f, -0.147461f,
-0.208008f, -0.126709f, 0.221191f, -0.105957f, 0.242188f, -0.0939941f, 0.263184f,
--0.0820312f, 0.292969f, -0.0820312f, 0.329102f, -0.0820312f, 0.352051f, -0.0974121f,
-0.375f, -0.112793f, 0.384766f, -0.14502f, 0.51416f, -0.133789f, 0.505371f, -0.111328f,
-0.489502f, -0.0859375f, 0.473633f, -0.0605469f, 0.447266f, -0.0393066f, 0.420898f,
--0.0180664f, 0.381592f, -0.00415039f, 0.342285f, 0.00976562f, 0.286133f, 0.00976562f,
-0.286133f, -0.45166f, 0.265137f, -0.45166f, 0.246826f, -0.44458f, 0.228516f, -0.4375f,
-0.215088f, -0.422119f, 0.20166f, -0.406738f, 0.193359f, -0.382324f, 0.185059f, -0.35791f,
-0.184082f, -0.32373f, 0.38916f, -0.32373f, 0.385254f, -0.387695f, 0.358398f, -0.419678f,
-0.331543f, -0.45166f, 0.286133f, -0.45166f, 0.230957f, -0.435547f, 0.230957f, 0,
-0.0942383f, 0, 0.0942383f, -0.435547f, 0.0170898f, -0.435547f, 0.0170898f, -0.52832f,
-0.0942383f, -0.52832f, 0.0942383f, -0.583496f, 0.0942383f, -0.61377f, 0.101562f,
--0.639404f, 0.108887f, -0.665039f, 0.126465f, -0.684082f, 0.144043f, -0.703125f,
-0.173828f, -0.713867f, 0.203613f, -0.724609f, 0.248047f, -0.724609f, 0.271484f, -0.724609f,
-0.294189f, -0.722168f, 0.316895f, -0.719727f, 0.334961f, -0.716797f, 0.334961f, -0.628418f,
-0.326172f, -0.630371f, 0.315186f, -0.631592f, 0.304199f, -0.632812f, 0.294922f, -0.632812f,
-0.275879f, -0.632812f, 0.263428f, -0.628906f, 0.250977f, -0.625f, 0.243896f, -0.617188f,
-0.236816f, -0.609375f, 0.233887f, -0.597412f, 0.230957f, -0.585449f, 0.230957f, -0.569824f,
-0.230957f, -0.52832f, 0.334961f, -0.52832f, 0.334961f, -0.435547f, 0.291016f, 0.211914f,
-0.23877f, 0.211914f, 0.198975f, 0.201416f, 0.15918f, 0.190918f, 0.131104f, 0.172119f,
-0.103027f, 0.15332f, 0.0861816f, 0.127197f, 0.0693359f, 0.101074f, 0.0629883f, 0.0698242f,
-0.200195f, 0.0537109f, 0.20752f, 0.0854492f, 0.231689f, 0.103516f, 0.255859f, 0.121582f,
-0.294922f, 0.121582f, 0.319336f, 0.121582f, 0.3396f, 0.114746f, 0.359863f, 0.10791f,
-0.374268f, 0.0915527f, 0.388672f, 0.0751953f, 0.396729f, 0.0483398f, 0.404785f, 0.0214844f,
-0.404785f, -0.0180664f, 0.404785f, -0.0317383f, 0.404785f, -0.0458984f, 0.404785f,
--0.0600586f, 0.405273f, -0.0717773f, 0.405762f, -0.0854492f, 0.405762f, -0.0981445f,
-0.404785f, -0.0981445f, 0.380859f, -0.046875f, 0.337646f, -0.0239258f, 0.294434f,
--0.000976562f, 0.234863f, -0.000976562f, 0.18457f, -0.000976562f, 0.148193f, -0.020752f,
-0.111816f, -0.0405273f, 0.0878906f, -0.0759277f, 0.0639648f, -0.111328f, 0.0524902f,
--0.1604f, 0.0410156f, -0.209473f, 0.0410156f, -0.268555f, 0.0410156f, -0.32959f,
-0.0532227f, -0.37915f, 0.0654297f, -0.428711f, 0.0905762f, -0.464355f, 0.115723f,
--0.5f, 0.154053f, -0.519287f, 0.192383f, -0.538574f, 0.245117f, -0.538574f, 0.297852f,
--0.538574f, 0.3396f, -0.516113f, 0.381348f, -0.493652f, 0.404785f, -0.443359f, 0.407227f,
--0.443359f, 0.407227f, -0.453613f, 0.407959f, -0.467041f, 0.408691f, -0.480469f,
-0.409668f, -0.49292f, 0.410645f, -0.505371f, 0.411865f, -0.515137f, 0.413086f, -0.524902f,
-0.414062f, -0.52832f, 0.543945f, -0.52832f, 0.542969f, -0.510742f, 0.541992f, -0.479004f,
-0.541016f, -0.447266f, 0.541016f, -0.40625f, 0.541016f, -0.0161133f, 0.541016f, 0.0415039f,
-0.524414f, 0.0842285f, 0.507812f, 0.126953f, 0.47583f, 0.155273f, 0.443848f, 0.183594f,
-0.397217f, 0.197754f, 0.350586f, 0.211914f, 0.291016f, 0.211914f, 0.405762f, -0.271484f,
-0.405762f, -0.321289f, 0.395996f, -0.354492f, 0.38623f, -0.387695f, 0.370605f, -0.407715f,
-0.35498f, -0.427734f, 0.334717f, -0.436035f, 0.314453f, -0.444336f, 0.293945f, -0.444336f,
-0.267578f, -0.444336f, 0.247314f, -0.434082f, 0.227051f, -0.423828f, 0.212891f, -0.402344f,
-0.19873f, -0.380859f, 0.191406f, -0.347656f, 0.184082f, -0.314453f, 0.184082f, -0.268555f,
-0.184082f, -0.183105f, 0.211426f, -0.139648f, 0.23877f, -0.0961914f, 0.292969f, -0.0961914f,
-0.313477f, -0.0961914f, 0.33374f, -0.104248f, 0.354004f, -0.112305f, 0.370117f, -0.132568f,
-0.38623f, -0.152832f, 0.395996f, -0.186523f, 0.405762f, -0.220215f, 0.405762f, -0.271484f,
-0.205078f, -0.422852f, 0.23291f, -0.483398f, 0.274902f, -0.510742f, 0.316895f, -0.538086f,
-0.375f, -0.538086f, 0.422852f, -0.538086f, 0.455811f, -0.522461f, 0.48877f, -0.506836f,
-0.509521f, -0.479492f, 0.530273f, -0.452148f, 0.539551f, -0.415039f, 0.548828f, -0.37793f,
-0.548828f, -0.334961f, 0.548828f, 0, 0.412109f, 0, 0.412109f, -0.295898f, 0.412109f,
--0.32666f, 0.407227f, -0.352295f, 0.402344f, -0.37793f, 0.391113f, -0.39624f, 0.379883f,
--0.414551f, 0.361816f, -0.424805f, 0.34375f, -0.435059f, 0.317871f, -0.435059f, 0.292969f,
--0.435059f, 0.272705f, -0.424072f, 0.252441f, -0.413086f, 0.237793f, -0.392822f,
-0.223145f, -0.372559f, 0.215088f, -0.344482f, 0.207031f, -0.316406f, 0.207031f, -0.282715f,
-0.207031f, 0, 0.0698242f, 0, 0.0698242f, -0.724609f, 0.207031f, -0.724609f, 0.207031f,
--0.526855f, 0.207031f, -0.51123f, 0.206543f, -0.495361f, 0.206055f, -0.479492f, 0.205322f,
--0.465576f, 0.20459f, -0.45166f, 0.204102f, -0.44043f, 0.203613f, -0.429199f, 0.203125f,
--0.422852f, 0.0698242f, -0.623535f, 0.0698242f, -0.724609f, 0.207031f, -0.724609f,
-0.207031f, -0.623535f, 0.0698242f, 0, 0.0698242f, -0.52832f, 0.207031f, -0.52832f,
-0.207031f, 0, 0.0703125f, -0.623535f, 0.0703125f, -0.724609f, 0.20752f, -0.724609f,
-0.20752f, -0.623535f, 0.0673828f, 0.20752f, 0.0400391f, 0.20752f, 0.0197754f, 0.206299f,
--0.000488281f, 0.205078f, -0.015625f, 0.203125f, -0.015625f, 0.106445f, -0.00927734f,
-0.107422f, -0.00292969f, 0.10791f, 0.00341797f, 0.108398f, 0.00927734f, 0.108398f,
-0.0283203f, 0.108398f, 0.0400391f, 0.104492f, 0.0517578f, 0.100586f, 0.0585938f,
-0.0913086f, 0.0654297f, 0.0820312f, 0.0678711f, 0.0668945f, 0.0703125f, 0.0517578f,
-0.0703125f, 0.0292969f, 0.0703125f, -0.52832f, 0.20752f, -0.52832f, 0.20752f, 0.0625f,
-0.20752f, 0.0942383f, 0.199707f, 0.120605f, 0.191895f, 0.146973f, 0.175049f, 0.166504f,
-0.158203f, 0.186035f, 0.131592f, 0.196777f, 0.10498f, 0.20752f, 0.0673828f, 0.20752f,
-0.407227f, 0, 0.266113f, -0.239258f, 0.207031f, -0.198242f, 0.207031f, 0, 0.0698242f,
-0, 0.0698242f, -0.724609f, 0.207031f, -0.724609f, 0.207031f, -0.30957f, 0.395508f,
--0.52832f, 0.542969f, -0.52832f, 0.357422f, -0.322266f, 0.557129f, 0, 0.0698242f,
-0, 0.0698242f, -0.724609f, 0.207031f, -0.724609f, 0.207031f, 0, 0.380859f, 0, 0.380859f,
--0.296387f, 0.380859f, -0.327148f, 0.376709f, -0.352783f, 0.372559f, -0.378418f,
-0.363037f, -0.396729f, 0.353516f, -0.415039f, 0.338135f, -0.425293f, 0.322754f, -0.435547f,
-0.300781f, -0.435547f, 0.279785f, -0.435547f, 0.262695f, -0.424561f, 0.245605f, -0.413574f,
-0.233154f, -0.393311f, 0.220703f, -0.373047f, 0.213867f, -0.344971f, 0.207031f, -0.316895f,
-0.207031f, -0.283203f, 0.207031f, 0, 0.0698242f, 0, 0.0698242f, -0.410156f, 0.0698242f,
--0.427246f, 0.0695801f, -0.445312f, 0.0693359f, -0.463379f, 0.0686035f, -0.479736f,
-0.0678711f, -0.496094f, 0.0673828f, -0.509033f, 0.0668945f, -0.521973f, 0.065918f,
--0.52832f, 0.196777f, -0.52832f, 0.197754f, -0.522461f, 0.19873f, -0.509521f, 0.199707f,
--0.496582f, 0.200684f, -0.480957f, 0.20166f, -0.465332f, 0.202393f, -0.449707f, 0.203125f,
--0.434082f, 0.203125f, -0.42334f, 0.205078f, -0.42334f, 0.230469f, -0.483887f, 0.268311f,
--0.51123f, 0.306152f, -0.538574f, 0.358887f, -0.538574f, 0.419434f, -0.538574f, 0.456299f,
--0.509033f, 0.493164f, -0.479492f, 0.505859f, -0.42334f, 0.508789f, -0.42334f, 0.522949f,
--0.456055f, 0.539307f, -0.478027f, 0.555664f, -0.5f, 0.575439f, -0.513428f, 0.595215f,
--0.526855f, 0.618408f, -0.532715f, 0.641602f, -0.538574f, 0.668945f, -0.538574f,
-0.712402f, -0.538574f, 0.742432f, -0.522949f, 0.772461f, -0.507324f, 0.79126f, -0.47998f,
-0.810059f, -0.452637f, 0.818604f, -0.415527f, 0.827148f, -0.378418f, 0.827148f, -0.335449f,
-0.827148f, 0, 0.690918f, 0, 0.690918f, -0.296387f, 0.690918f, -0.327148f, 0.686768f,
--0.352783f, 0.682617f, -0.378418f, 0.673096f, -0.396729f, 0.663574f, -0.415039f,
-0.648193f, -0.425293f, 0.632812f, -0.435547f, 0.61084f, -0.435547f, 0.590332f, -0.435547f,
-0.573486f, -0.425049f, 0.556641f, -0.414551f, 0.544189f, -0.395264f, 0.531738f, -0.375977f,
-0.524902f, -0.349121f, 0.518066f, -0.322266f, 0.51709f, -0.289551f, 0.51709f, 0,
-0.412109f, 0, 0.412109f, -0.296387f, 0.412109f, -0.327148f, 0.407227f, -0.352783f,
-0.402344f, -0.378418f, 0.391113f, -0.396729f, 0.379883f, -0.415039f, 0.361816f, -0.425293f,
-0.34375f, -0.435547f, 0.317871f, -0.435547f, 0.292969f, -0.435547f, 0.272705f, -0.424561f,
-0.252441f, -0.413574f, 0.237793f, -0.393311f, 0.223145f, -0.373047f, 0.215088f, -0.344971f,
-0.207031f, -0.316895f, 0.207031f, -0.283203f, 0.207031f, 0, 0.0698242f, 0, 0.0698242f,
--0.410156f, 0.0698242f, -0.427246f, 0.0695801f, -0.445312f, 0.0693359f, -0.463379f,
-0.0686035f, -0.479736f, 0.0678711f, -0.496094f, 0.0673828f, -0.509033f, 0.0668945f,
--0.521973f, 0.065918f, -0.52832f, 0.196777f, -0.52832f, 0.197754f, -0.522461f, 0.19873f,
--0.509521f, 0.199707f, -0.496582f, 0.200684f, -0.480957f, 0.20166f, -0.465332f, 0.202393f,
--0.449707f, 0.203125f, -0.434082f, 0.203125f, -0.42334f, 0.205078f, -0.42334f, 0.23291f,
--0.483887f, 0.274902f, -0.51123f, 0.316895f, -0.538574f, 0.375f, -0.538574f, 0.422852f,
--0.538574f, 0.455811f, -0.522949f, 0.48877f, -0.507324f, 0.509521f, -0.47998f, 0.530273f,
--0.452637f, 0.539551f, -0.415527f, 0.548828f, -0.378418f, 0.548828f, -0.335449f,
-0.548828f, 0, 0.571777f, -0.264648f, 0.571777f, -0.204102f, 0.554932f, -0.153809f,
-0.538086f, -0.103516f, 0.504395f, -0.0671387f, 0.470703f, -0.0307617f, 0.42041f,
--0.010498f, 0.370117f, 0.00976562f, 0.303223f, 0.00976562f, 0.23877f, 0.00976562f,
-0.189453f, -0.0102539f, 0.140137f, -0.0302734f, 0.106689f, -0.0664062f, 0.0732422f,
--0.102539f, 0.0561523f, -0.153076f, 0.0390625f, -0.203613f, 0.0390625f, -0.264648f,
-0.0390625f, -0.32373f, 0.0554199f, -0.373779f, 0.0717773f, -0.423828f, 0.10498f,
--0.460449f, 0.138184f, -0.49707f, 0.188477f, -0.517578f, 0.23877f, -0.538086f, 0.306152f,
--0.538086f, 0.377441f, -0.538086f, 0.427734f, -0.517578f, 0.478027f, -0.49707f, 0.51001f,
--0.460693f, 0.541992f, -0.424316f, 0.556885f, -0.374268f, 0.571777f, -0.324219f,
-0.571777f, -0.264648f, 0.428223f, -0.264648f, 0.428223f, -0.358887f, 0.397461f, -0.401367f,
-0.366699f, -0.443848f, 0.308105f, -0.443848f, 0.247559f, -0.443848f, 0.215332f, -0.400879f,
-0.183105f, -0.35791f, 0.183105f, -0.264648f, 0.183105f, -0.217285f, 0.19165f, -0.183105f,
-0.200195f, -0.148926f, 0.21582f, -0.126953f, 0.231445f, -0.10498f, 0.253418f, -0.0944824f,
-0.275391f, -0.0839844f, 0.301758f, -0.0839844f, 0.332031f, -0.0839844f, 0.355713f,
--0.0944824f, 0.379395f, -0.10498f, 0.395508f, -0.126953f, 0.411621f, -0.148926f,
-0.419922f, -0.183105f, 0.428223f, -0.217285f, 0.428223f, -0.264648f, 0.569824f, -0.266602f,
-0.569824f, -0.206543f, 0.557861f, -0.155762f, 0.545898f, -0.10498f, 0.520996f, -0.0683594f,
-0.496094f, -0.0317383f, 0.457764f, -0.0109863f, 0.419434f, 0.00976562f, 0.367188f,
-0.00976562f, 0.34375f, 0.00976562f, 0.320557f, 0.00488281f, 0.297363f, 0, 0.276367f,
--0.0109863f, 0.255371f, -0.0219727f, 0.237549f, -0.0397949f, 0.219727f, -0.0576172f,
-0.207031f, -0.0839844f, 0.204102f, -0.0839844f, 0.20459f, -0.081543f, 0.205078f,
--0.0717773f, 0.205566f, -0.0620117f, 0.206055f, -0.0490723f, 0.206543f, -0.0361328f,
-0.206787f, -0.0217285f, 0.207031f, -0.00732422f, 0.207031f, 0.00488281f, 0.207031f,
-0.20752f, 0.0698242f, 0.20752f, 0.0698242f, -0.406738f, 0.0698242f, -0.447266f, 0.0686035f,
--0.479004f, 0.0673828f, -0.510742f, 0.065918f, -0.52832f, 0.199219f, -0.52832f, 0.200195f,
--0.524902f, 0.201416f, -0.515137f, 0.202637f, -0.505371f, 0.203369f, -0.492676f,
-0.204102f, -0.47998f, 0.20459f, -0.466309f, 0.205078f, -0.452637f, 0.205078f, -0.442383f,
-0.207031f, -0.442383f, 0.231934f, -0.494629f, 0.275391f, -0.51709f, 0.318848f, -0.539551f,
-0.375977f, -0.539551f, 0.42627f, -0.539551f, 0.462891f, -0.519043f, 0.499512f, -0.498535f,
-0.523193f, -0.462402f, 0.546875f, -0.42627f, 0.55835f, -0.376221f, 0.569824f, -0.326172f,
-0.569824f, -0.266602f, 0.426758f, -0.266602f, 0.426758f, -0.356934f, 0.399414f, -0.400635f,
-0.37207f, -0.444336f, 0.317871f, -0.444336f, 0.297363f, -0.444336f, 0.2771f, -0.435791f,
-0.256836f, -0.427246f, 0.240967f, -0.406494f, 0.225098f, -0.385742f, 0.215088f, -0.35083f,
-0.205078f, -0.315918f, 0.205078f, -0.262695f, 0.205078f, -0.210938f, 0.214844f, -0.176514f,
-0.224609f, -0.14209f, 0.240479f, -0.121582f, 0.256348f, -0.101074f, 0.276367f, -0.0925293f,
-0.296387f, -0.0839844f, 0.316895f, -0.0839844f, 0.343262f, -0.0839844f, 0.36377f,
--0.0944824f, 0.384277f, -0.10498f, 0.398193f, -0.127197f, 0.412109f, -0.149414f,
-0.419434f, -0.184082f, 0.426758f, -0.21875f, 0.426758f, -0.266602f, 0.0410156f, -0.263672f,
-0.0410156f, -0.32373f, 0.0532227f, -0.374268f, 0.0654297f, -0.424805f, 0.0905762f,
--0.461182f, 0.115723f, -0.497559f, 0.154053f, -0.518066f, 0.192383f, -0.538574f,
-0.245117f, -0.538574f, 0.297852f, -0.538574f, 0.3396f, -0.516113f, 0.381348f, -0.493652f,
-0.404785f, -0.443359f, 0.404785f, -0.453613f, 0.405518f, -0.467041f, 0.40625f, -0.480469f,
-0.407471f, -0.49292f, 0.408691f, -0.505371f, 0.409912f, -0.515137f, 0.411133f, -0.524902f,
-0.412109f, -0.52832f, 0.543945f, -0.52832f, 0.542969f, -0.510742f, 0.541992f, -0.479004f,
-0.541016f, -0.447266f, 0.541016f, -0.406738f, 0.541016f, 0.20752f, 0.404785f, 0.20752f,
-0.404785f, -0.012207f, 0.404785f, -0.0258789f, 0.405273f, -0.0390625f, 0.405762f,
--0.0522461f, 0.40625f, -0.0634766f, 0.406738f, -0.0761719f, 0.407227f, -0.0878906f,
-0.40625f, -0.0878906f, 0.382324f, -0.0366211f, 0.337891f, -0.0134277f, 0.293457f,
-0.00976562f, 0.233887f, 0.00976562f, 0.184082f, 0.00976562f, 0.147705f, -0.0107422f,
-0.111328f, -0.03125f, 0.0876465f, -0.0678711f, 0.0639648f, -0.104492f, 0.0524902f,
--0.154541f, 0.0410156f, -0.20459f, 0.0410156f, -0.263672f, 0.405762f, -0.266602f,
-0.405762f, -0.319336f, 0.395996f, -0.353516f, 0.38623f, -0.387695f, 0.370605f, -0.407959f,
-0.35498f, -0.428223f, 0.334717f, -0.436279f, 0.314453f, -0.444336f, 0.293945f, -0.444336f,
-0.267578f, -0.444336f, 0.247314f, -0.434082f, 0.227051f, -0.423828f, 0.212891f, -0.401855f,
-0.19873f, -0.379883f, 0.191406f, -0.345703f, 0.184082f, -0.311523f, 0.184082f, -0.263672f,
-0.184082f, -0.0839844f, 0.292969f, -0.0839844f, 0.313477f, -0.0839844f, 0.33374f,
--0.0927734f, 0.354004f, -0.101562f, 0.370117f, -0.122559f, 0.38623f, -0.143555f,
-0.395996f, -0.178711f, 0.405762f, -0.213867f, 0.405762f, -0.266602f, 0.0698242f,
-0, 0.0698242f, -0.404297f, 0.0698242f, -0.421387f, 0.0695801f, -0.44043f, 0.0693359f,
--0.459473f, 0.0686035f, -0.476807f, 0.0678711f, -0.494141f, 0.0673828f, -0.508057f,
-0.0668945f, -0.521973f, 0.065918f, -0.52832f, 0.196777f, -0.52832f, 0.197754f, -0.522461f,
-0.19873f, -0.508057f, 0.199707f, -0.493652f, 0.200684f, -0.476562f, 0.20166f, -0.459473f,
-0.202393f, -0.442627f, 0.203125f, -0.425781f, 0.203125f, -0.415527f, 0.205078f, -0.415527f,
-0.215332f, -0.444336f, 0.225586f, -0.467041f, 0.23584f, -0.489746f, 0.249756f, -0.505615f,
-0.263672f, -0.521484f, 0.283203f, -0.530029f, 0.302734f, -0.538574f, 0.331543f, -0.538574f,
-0.34375f, -0.538574f, 0.355713f, -0.536377f, 0.367676f, -0.53418f, 0.374023f, -0.53125f,
-0.374023f, -0.416504f, 0.36084f, -0.419434f, 0.347412f, -0.421631f, 0.333984f, -0.423828f,
-0.31543f, -0.423828f, 0.26416f, -0.423828f, 0.235596f, -0.382324f, 0.207031f, -0.34082f,
-0.207031f, -0.259277f, 0.207031f, 0, 0.515137f, -0.154297f, 0.515137f, -0.116211f,
-0.499268f, -0.0859375f, 0.483398f, -0.0556641f, 0.453125f, -0.0344238f, 0.422852f,
--0.0131836f, 0.378906f, -0.00170898f, 0.334961f, 0.00976562f, 0.278809f, 0.00976562f,
-0.228516f, 0.00976562f, 0.187988f, 0.00244141f, 0.147461f, -0.00488281f, 0.116943f,
--0.0217285f, 0.0864258f, -0.0385742f, 0.065918f, -0.0654297f, 0.0454102f, -0.0922852f,
-0.0351562f, -0.131836f, 0.155762f, -0.149902f, 0.161621f, -0.12793f, 0.171875f, -0.114258f,
-0.182129f, -0.100586f, 0.197266f, -0.0932617f, 0.212402f, -0.0859375f, 0.232666f,
--0.0834961f, 0.25293f, -0.0810547f, 0.278809f, -0.0810547f, 0.302246f, -0.0810547f,
-0.32251f, -0.0837402f, 0.342773f, -0.0864258f, 0.357666f, -0.0930176f, 0.372559f,
--0.0996094f, 0.380859f, -0.111572f, 0.38916f, -0.123535f, 0.38916f, -0.141602f, 0.38916f,
--0.162109f, 0.377197f, -0.174072f, 0.365234f, -0.186035f, 0.344482f, -0.193604f,
-0.32373f, -0.201172f, 0.295654f, -0.206787f, 0.267578f, -0.212402f, 0.23584f, -0.219727f,
-0.202637f, -0.227051f, 0.17041f, -0.237305f, 0.138184f, -0.247559f, 0.112793f, -0.265137f,
-0.0874023f, -0.282715f, 0.0717773f, -0.309814f, 0.0561523f, -0.336914f, 0.0561523f,
--0.378418f, 0.0561523f, -0.416016f, 0.0708008f, -0.445557f, 0.0854492f, -0.475098f,
-0.11377f, -0.49585f, 0.14209f, -0.516602f, 0.183838f, -0.527588f, 0.225586f, -0.538574f,
-0.279785f, -0.538574f, 0.322754f, -0.538574f, 0.359863f, -0.530518f, 0.396973f, -0.522461f,
-0.42627f, -0.505127f, 0.455566f, -0.487793f, 0.475342f, -0.460938f, 0.495117f, -0.434082f,
-0.50293f, -0.395996f, 0.381348f, -0.383301f, 0.37793f, -0.402344f, 0.369141f, -0.414795f,
-0.360352f, -0.427246f, 0.347412f, -0.43457f, 0.334473f, -0.441895f, 0.317383f, -0.44458f,
-0.300293f, -0.447266f, 0.279785f, -0.447266f, 0.230957f, -0.447266f, 0.206543f, -0.434814f,
-0.182129f, -0.422363f, 0.182129f, -0.393066f, 0.182129f, -0.375f, 0.192139f, -0.364258f,
-0.202148f, -0.353516f, 0.220459f, -0.346436f, 0.23877f, -0.339355f, 0.263916f, -0.334229f,
-0.289062f, -0.329102f, 0.318848f, -0.321777f, 0.355469f, -0.313965f, 0.390869f, -0.303467f,
-0.42627f, -0.292969f, 0.453857f, -0.274658f, 0.481445f, -0.256348f, 0.498291f, -0.227539f,
-0.515137f, -0.19873f, 0.515137f, -0.154297f, 0.199219f, -0.52832f, 0.199219f, -0.231934f,
-0.199219f, -0.201172f, 0.204102f, -0.175537f, 0.208984f, -0.149902f, 0.220215f, -0.131592f,
-0.231445f, -0.113281f, 0.249268f, -0.103027f, 0.26709f, -0.0927734f, 0.292969f, -0.0927734f,
-0.317871f, -0.0927734f, 0.338135f, -0.10376f, 0.358398f, -0.114746f, 0.373047f, -0.13501f,
-0.387695f, -0.155273f, 0.395752f, -0.18335f, 0.403809f, -0.211426f, 0.403809f, -0.245117f,
-0.403809f, -0.52832f, 0.541016f, -0.52832f, 0.541016f, -0.118164f, 0.541016f, -0.101562f,
-0.54126f, -0.083252f, 0.541504f, -0.0649414f, 0.542236f, -0.048584f, 0.542969f, -0.0322266f,
-0.543701f, -0.0192871f, 0.544434f, -0.00634766f, 0.544922f, 0, 0.414062f, 0, 0.413574f,
--0.00585938f, 0.412354f, -0.0187988f, 0.411133f, -0.0317383f, 0.4104f, -0.0473633f,
-0.409668f, -0.0629883f, 0.408936f, -0.0786133f, 0.408203f, -0.0942383f, 0.408203f,
--0.10498f, 0.405762f, -0.10498f, 0.378418f, -0.0449219f, 0.336182f, -0.0175781f,
-0.293945f, 0.00976562f, 0.23584f, 0.00976562f, 0.188477f, 0.00976562f, 0.155273f,
--0.00585938f, 0.12207f, -0.0214844f, 0.101318f, -0.048584f, 0.0805664f, -0.0756836f,
-0.0712891f, -0.112793f, 0.0620117f, -0.149902f, 0.0620117f, -0.192871f, 0.0620117f,
--0.52832f, 0.275879f, -0.11084f, 0.408203f, -0.52832f, 0.551758f, -0.52832f, 0.356934f,
-0, 0.192871f, 0, 0.00390625f, -0.52832f, 0.148926f, -0.52832f, 0.212891f, -0.124512f,
-0.314941f, -0.52832f, 0.461914f, -0.52832f, 0.562988f, -0.124512f, 0.652832f, -0.52832f,
-0.779785f, -0.52832f, 0.641113f, 0, 0.496094f, 0, 0.38916f, -0.430664f, 0.278809f,
-0, 0.133789f, 0, -0.00292969f, -0.52832f, 0.125977f, -0.52832f, 0.399902f, 0, 0.276855f,
--0.191406f, 0.152832f, 0, 0.00683594f, 0, 0.200195f, -0.272949f, 0.0161133f, -0.52832f,
-0.164062f, -0.52832f, 0.276855f, -0.355469f, 0.38916f, -0.52832f, 0.538086f, -0.52832f,
-0.354004f, -0.274414f, 0.548828f, 0, 0.285156f, -0.117676f, 0.407227f, -0.52832f,
-0.550781f, -0.52832f, 0.341797f, 0.027832f, 0.302246f, 0.124023f, 0.259766f, 0.164062f,
-0.213379f, 0.20752f, 0.138184f, 0.20752f, 0.0888672f, 0.20752f, 0.0517578f, 0.201172f,
-0.0517578f, 0.103516f, 0.0776367f, 0.107422f, 0.0983887f, 0.107422f, 0.119141f, 0.107422f,
-0.134766f, 0.103027f, 0.150391f, 0.0986328f, 0.163086f, 0.0883789f, 0.187988f, 0.0678711f,
-0.208008f, 0.0180664f, 0.216797f, -0.00537109f, 0.0078125f, -0.52832f, 0.152832f,
--0.52832f, 0.0332031f, 0, 0.0332031f, -0.097168f, 0.296875f, -0.429199f, 0.0532227f,
--0.429199f, 0.0532227f, -0.52832f, 0.448242f, -0.52832f, 0.448242f, -0.430176f, 0.186035f,
--0.100098f, 0.472168f, -0.100098f, 0.472168f, 0
-};
-
-const unsigned char LiberationSanskBoldVerbs[] = {
-6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1,
-1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 1, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1,
-1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1,
-1, 5, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5,
-6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 1, 1, 1, 2, 2, 5, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2,
-5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 0, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 5, 0, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5,
-6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 1, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1,
-5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2,
-2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5,
-6, 0, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 5, 6
-};
-
-const unsigned LiberationSanskBoldCharCodes[] = {
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51,
-53, 54, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
-76, 77, 79, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 93, 94, 95, 97, 98, 100, 101,
-102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118,
-119, 120, 121, 122
-};
-
-const SkFixed LiberationSanskBoldWidths[] = {
-0x00004720, 0x00005540, 0x00007960, 0x00008e60, 0x00008e60, 0x0000e3a0, 0x0000b8e0,
-0x00003ce0, 0x00005540, 0x00005540, 0x000063a0, 0x00009580, 0x00005540, 0x00004720,
-0x00004720, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60,
-0x00008e60, 0x00008e60, 0x00008e60, 0x00005540, 0x00005540, 0x00009580, 0x00009580,
-0x00009c60, 0x0000b8e0, 0x0000b8e0, 0x0000b8e0, 0x0000b8e0, 0x0000aac0, 0x00009c60,
-0x0000c720, 0x0000b8e0, 0x00004720, 0x00008e60, 0x00009c60, 0x0000d540, 0x0000c720,
-0x0000b8e0, 0x0000aac0, 0x00009c60, 0x0000b8e0, 0x0000aac0, 0x0000f1a0, 0x0000aac0,
-0x0000aac0, 0x00009c60, 0x00005540, 0x00005540, 0x00009580, 0x00008e60, 0x00008e60,
-0x00009c60, 0x00009c60, 0x00008e60, 0x00005540, 0x00009c60, 0x00009c60, 0x00004720,
-0x00004720, 0x00008e60, 0x00004720, 0x0000e3a0, 0x00009c60, 0x00009c60, 0x00009c60,
-0x00009c60, 0x000063a0, 0x00008e60, 0x00009c60, 0x00008e60, 0x0000c720, 0x00008e60,
-0x00008e60, 0x00008000
-};
-
-const int LiberationSanskBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSanskBoldCharCodes);
-
-const SkPaint::FontMetrics LiberationSanskBoldMetrics = {
-0x2c663933, -1.0332f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.24609f, 4.07409e-11f,
--0.184082f, 1.06201f, 0.538086f, 6.66449e-1f, 0.10498f, 0.105957f
-};
-
-const SkScalar LiberationSanskItalicPoints[] = {
-0.518066f, 0, 0.481445f, -0.201172f, 0.169434f, -0.201172f, 0.0522461f, 0, -0.0493164f,
-0, 0.364746f, -0.687988f, 0.470703f, -0.687988f, 0.613281f, 0, 0.425293f, -0.504883f,
-0.421387f, -0.524902f, 0.417725f, -0.543945f, 0.414062f, -0.562988f, 0.411621f, -0.578857f,
-0.40918f, -0.594727f, 0.407471f, -0.605225f, 0.405762f, -0.615723f, 0.405273f, -0.617676f,
-0.404297f, -0.615723f, 0.398682f, -0.60498f, 0.393066f, -0.594238f, 0.384277f, -0.578369f,
-0.375488f, -0.5625f, 0.364746f, -0.543213f, 0.354004f, -0.523926f, 0.342285f, -0.504395f,
-0.210449f, -0.273926f, 0.467773f, -0.273926f, 0.498535f, 0, 0.560547f, -0.318848f,
-0.186035f, -0.318848f, 0.124023f, 0, 0.0307617f, 0, 0.164551f, -0.687988f, 0.257812f,
--0.687988f, 0.201172f, -0.396973f, 0.575684f, -0.396973f, 0.632324f, -0.687988f,
-0.723145f, -0.687988f, 0.589355f, 0, 0.418945f, -0.611816f, 0.299805f, 0, 0.207031f,
-0, 0.326172f, -0.611816f, 0.0898438f, -0.611816f, 0.104492f, -0.687988f, 0.669922f,
--0.687988f, 0.655273f, -0.611816f, 0.686523f, 0, 0.577637f, 0, 0.542969f, -0.437012f,
-0.54248f, -0.446289f, 0.541748f, -0.458008f, 0.541016f, -0.469727f, 0.540283f, -0.482666f,
-0.539551f, -0.495605f, 0.538818f, -0.509033f, 0.538086f, -0.522461f, 0.537598f, -0.534668f,
-0.536133f, -0.563965f, 0.535156f, -0.595215f, 0.523438f, -0.564453f, 0.51123f, -0.534668f,
-0.500977f, -0.509277f, 0.489502f, -0.482422f, 0.478027f, -0.455566f, 0.469238f, -0.437012f,
-0.264648f, 0, 0.155762f, 0, 0.0864258f, -0.687988f, 0.182617f, -0.687988f, 0.221191f,
--0.250977f, 0.223633f, -0.220215f, 0.225098f, -0.190186f, 0.226562f, -0.160156f,
-0.227539f, -0.135742f, 0.228516f, -0.107422f, 0.229004f, -0.0820312f, 0.243164f,
--0.115723f, 0.257324f, -0.148438f, 0.263184f, -0.162598f, 0.269775f, -0.17749f, 0.276367f,
--0.192383f, 0.282715f, -0.207031f, 0.289062f, -0.22168f, 0.295166f, -0.235107f, 0.30127f,
--0.248535f, 0.306641f, -0.259766f, 0.509277f, -0.687988f, 0.598633f, -0.687988f,
-0.635254f, -0.259766f, 0.63623f, -0.249023f, 0.637207f, -0.235352f, 0.638184f, -0.22168f,
-0.638916f, -0.207275f, 0.639648f, -0.192871f, 0.640381f, -0.177979f, 0.641113f, -0.163086f,
-0.641602f, -0.148926f, 0.643066f, -0.116211f, 0.643555f, -0.0820312f, 0.644043f,
--0.0820312f, 0.651123f, -0.098877f, 0.658203f, -0.115723f, 0.668945f, -0.141113f,
-0.679688f, -0.166504f, 0.692627f, -0.196045f, 0.705566f, -0.225586f, 0.717773f, -0.250977f,
-0.924316f, -0.687988f, 1.02246f, -0.687988f, 0.383301f, -0.285156f, 0.328125f, 0,
-0.235352f, 0, 0.291504f, -0.285156f, 0.104004f, -0.687988f, 0.199707f, -0.687988f,
-0.349121f, -0.358887f, 0.622559f, -0.687988f, 0.727051f, -0.687988f, 0.515137f, -0.00292969f,
-0.500977f, 0.000488281f, 0.484619f, 0.00268555f, 0.468262f, 0.00488281f, 0.452637f,
-0.00488281f, 0.407227f, 0.00488281f, 0.386475f, -0.013916f, 0.365723f, -0.0327148f,
-0.365723f, -0.0698242f, 0.365723f, -0.0771484f, 0.366699f, -0.0856934f, 0.367676f,
--0.0942383f, 0.368164f, -0.101074f, 0.365234f, -0.101074f, 0.348145f, -0.0751953f,
-0.329834f, -0.0546875f, 0.311523f, -0.0341797f, 0.289307f, -0.0197754f, 0.26709f,
--0.00537109f, 0.239746f, 0.00219727f, 0.212402f, 0.00976562f, 0.17627f, 0.00976562f,
-0.138184f, 0.00976562f, 0.109619f, -0.00244141f, 0.0810547f, -0.0146484f, 0.0615234f,
--0.0349121f, 0.0419922f, -0.0551758f, 0.0322266f, -0.081543f, 0.0224609f, -0.10791f,
-0.0224609f, -0.135742f, 0.0224609f, -0.175293f, 0.0339355f, -0.204102f, 0.0454102f,
--0.23291f, 0.0651855f, -0.253418f, 0.0849609f, -0.273926f, 0.111572f, -0.286865f,
-0.138184f, -0.299805f, 0.168213f, -0.307129f, 0.198242f, -0.314453f, 0.230469f, -0.317383f,
-0.262695f, -0.320312f, 0.293457f, -0.320801f, 0.406738f, -0.322266f, 0.410156f, -0.339844f,
-0.412598f, -0.352051f, 0.414307f, -0.363281f, 0.416016f, -0.374512f, 0.416016f, -0.384277f,
-0.416016f, -0.428711f, 0.390137f, -0.449951f, 0.364258f, -0.471191f, 0.318359f, -0.471191f,
-0.294434f, -0.471191f, 0.273682f, -0.467529f, 0.25293f, -0.463867f, 0.236572f, -0.454346f,
-0.220215f, -0.444824f, 0.207764f, -0.428467f, 0.195312f, -0.412109f, 0.1875f, -0.387207f,
-0.100586f, -0.401367f, 0.109863f, -0.431641f, 0.125977f, -0.456787f, 0.14209f, -0.481934f,
-0.168457f, -0.5f, 0.194824f, -0.518066f, 0.232666f, -0.528076f, 0.270508f, -0.538086f,
-0.323242f, -0.538086f, 0.366699f, -0.538086f, 0.400391f, -0.527344f, 0.434082f, -0.516602f,
-0.457031f, -0.497559f, 0.47998f, -0.478516f, 0.491943f, -0.452148f, 0.503906f, -0.425781f,
-0.503906f, -0.394043f, 0.503906f, -0.378906f, 0.501221f, -0.357666f, 0.498535f, -0.336426f,
-0.494629f, -0.317383f, 0.458496f, -0.132812f, 0.456055f, -0.12207f, 0.45459f, -0.11084f,
-0.453125f, -0.0996094f, 0.453125f, -0.0898438f, 0.453125f, -0.0717773f, 0.462646f,
--0.0629883f, 0.472168f, -0.0541992f, 0.492676f, -0.0541992f, 0.5f, -0.0541992f, 0.507568f,
--0.0551758f, 0.515137f, -0.0561523f, 0.521973f, -0.0576172f, 0.39502f, -0.261719f,
-0.297852f, -0.259766f, 0.27832f, -0.259277f, 0.257324f, -0.257812f, 0.236328f, -0.256348f,
-0.216064f, -0.251709f, 0.195801f, -0.24707f, 0.17749f, -0.239258f, 0.15918f, -0.231445f,
-0.145508f, -0.218018f, 0.131836f, -0.20459f, 0.123779f, -0.185547f, 0.115723f, -0.166504f,
-0.115723f, -0.139648f, 0.115723f, -0.124023f, 0.12085f, -0.109131f, 0.125977f, -0.0942383f,
-0.136719f, -0.0827637f, 0.147461f, -0.0712891f, 0.16333f, -0.064209f, 0.179199f,
--0.0571289f, 0.200684f, -0.0571289f, 0.243164f, -0.0571289f, 0.274902f, -0.0717773f,
-0.306641f, -0.0864258f, 0.329102f, -0.10791f, 0.351562f, -0.129395f, 0.364502f, -0.154541f,
-0.377441f, -0.179688f, 0.381836f, -0.200684f, 0.363281f, -0.538086f, 0.402344f, -0.538086f,
-0.432617f, -0.525879f, 0.462891f, -0.513672f, 0.483398f, -0.491211f, 0.503906f, -0.46875f,
-0.514648f, -0.436768f, 0.525391f, -0.404785f, 0.525391f, -0.365234f, 0.525391f, -0.34082f,
-0.523193f, -0.311768f, 0.520996f, -0.282715f, 0.515137f, -0.251953f, 0.501953f, -0.182617f,
-0.480469f, -0.133057f, 0.458984f, -0.0834961f, 0.428711f, -0.0517578f, 0.398438f,
--0.0200195f, 0.359375f, -0.00512695f, 0.320312f, 0.00976562f, 0.271973f, 0.00976562f,
-0.211914f, 0.00976562f, 0.174316f, -0.015625f, 0.136719f, -0.0410156f, 0.121094f,
--0.0869141f, 0.119629f, -0.0869141f, 0.117188f, -0.0742188f, 0.11377f, -0.0598145f,
-0.110352f, -0.0454102f, 0.107178f, -0.0327148f, 0.104004f, -0.0200195f, 0.101807f,
--0.0109863f, 0.0996094f, -0.00195312f, 0.0986328f, 0, 0.0141602f, 0, 0.015625f, -0.00439453f,
-0.0180664f, -0.0148926f, 0.0205078f, -0.0253906f, 0.0236816f, -0.0400391f, 0.0268555f,
--0.0546875f, 0.0307617f, -0.0722656f, 0.034668f, -0.0898438f, 0.0380859f, -0.108887f,
-0.157715f, -0.724609f, 0.245605f, -0.724609f, 0.205078f, -0.518066f, 0.202637f, -0.503906f,
-0.199463f, -0.491211f, 0.196289f, -0.478516f, 0.193848f, -0.469238f, 0.190918f, -0.458496f,
-0.188477f, -0.449707f, 0.19043f, -0.449707f, 0.208008f, -0.472656f, 0.226318f, -0.489258f,
-0.244629f, -0.505859f, 0.265381f, -0.516846f, 0.286133f, -0.527832f, 0.310059f, -0.532959f,
-0.333984f, -0.538086f, 0.363281f, -0.538086f, 0.337891f, -0.470215f, 0.306641f, -0.470215f,
-0.278564f, -0.460938f, 0.250488f, -0.45166f, 0.226562f, -0.428955f, 0.202637f, -0.40625f,
-0.184326f, -0.367676f, 0.166016f, -0.329102f, 0.154785f, -0.270508f, 0.145508f, -0.222656f,
-0.145508f, -0.184082f, 0.145508f, -0.152832f, 0.153809f, -0.128662f, 0.162109f, -0.104492f,
-0.17749f, -0.0881348f, 0.192871f, -0.0717773f, 0.2146f, -0.0634766f, 0.236328f, -0.0551758f,
-0.262695f, -0.0551758f, 0.292969f, -0.0551758f, 0.317383f, -0.064209f, 0.341797f,
--0.0732422f, 0.361572f, -0.095459f, 0.381348f, -0.117676f, 0.396484f, -0.155029f,
-0.411621f, -0.192383f, 0.422363f, -0.249023f, 0.433594f, -0.308105f, 0.433594f, -0.349609f,
-0.433594f, -0.409668f, 0.410645f, -0.439941f, 0.387695f, -0.470215f, 0.337891f, -0.470215f,
-0.125f, -0.245605f, 0.122559f, -0.231934f, 0.121826f, -0.218018f, 0.121094f, -0.204102f,
-0.120605f, -0.19043f, 0.120605f, -0.125488f, 0.153076f, -0.0908203f, 0.185547f, -0.0561523f,
-0.250977f, -0.0561523f, 0.27832f, -0.0561523f, 0.300781f, -0.0632324f, 0.323242f,
--0.0703125f, 0.341553f, -0.0822754f, 0.359863f, -0.0942383f, 0.373779f, -0.110107f,
-0.387695f, -0.125977f, 0.396973f, -0.143555f, 0.464355f, -0.112793f, 0.452148f, -0.0908203f,
-0.43457f, -0.0690918f, 0.416992f, -0.0473633f, 0.390869f, -0.0297852f, 0.364746f,
--0.012207f, 0.328125f, -0.0012207f, 0.291504f, 0.00976562f, 0.240723f, 0.00976562f,
-0.191895f, 0.00976562f, 0.15332f, -0.00415039f, 0.114746f, -0.0180664f, 0.0881348f,
--0.0446777f, 0.0615234f, -0.0712891f, 0.0476074f, -0.109863f, 0.0336914f, -0.148438f,
-0.0336914f, -0.197754f, 0.0336914f, -0.274902f, 0.0544434f, -0.337891f, 0.0751953f,
--0.400879f, 0.112061f, -0.445312f, 0.148926f, -0.489746f, 0.198975f, -0.513916f,
-0.249023f, -0.538086f, 0.307617f, -0.538086f, 0.361328f, -0.538086f, 0.400879f, -0.523926f,
-0.44043f, -0.509766f, 0.466797f, -0.484375f, 0.493164f, -0.458984f, 0.506104f, -0.423584f,
-0.519043f, -0.388184f, 0.519043f, -0.345703f, 0.519043f, -0.335449f, 0.518311f, -0.323242f,
-0.517578f, -0.311035f, 0.516113f, -0.297852f, 0.514648f, -0.284668f, 0.512451f, -0.27124f,
-0.510254f, -0.257812f, 0.507324f, -0.245605f, 0.429688f, -0.312988f, 0.430664f, -0.322754f,
-0.431152f, -0.331299f, 0.431641f, -0.339844f, 0.431641f, -0.348145f, 0.431641f, -0.380371f,
-0.422852f, -0.404053f, 0.414062f, -0.427734f, 0.397949f, -0.443115f, 0.381836f, -0.458496f,
-0.359375f, -0.46582f, 0.336914f, -0.473145f, 0.30957f, -0.473145f, 0.286133f, -0.473145f,
-0.260254f, -0.466064f, 0.234375f, -0.458984f, 0.210693f, -0.440918f, 0.187012f, -0.422852f,
-0.16748f, -0.391846f, 0.147949f, -0.36084f, 0.136719f, -0.312988f, 0.211914f, -0.464355f,
-0.121582f, 0, 0.0336914f, 0, 0.124023f, -0.464355f, 0.0498047f, -0.464355f, 0.0625f,
--0.52832f, 0.136719f, -0.52832f, 0.147949f, -0.587891f, 0.153809f, -0.616699f, 0.163086f,
--0.641602f, 0.172363f, -0.666504f, 0.189697f, -0.685059f, 0.207031f, -0.703613f,
-0.234375f, -0.714111f, 0.261719f, -0.724609f, 0.303711f, -0.724609f, 0.319336f, -0.724609f,
-0.335693f, -0.723145f, 0.352051f, -0.72168f, 0.364258f, -0.71875f, 0.351562f, -0.651855f,
-0.347168f, -0.652832f, 0.341553f, -0.65332f, 0.335938f, -0.653809f, 0.32959f, -0.654541f,
-0.323242f, -0.655273f, 0.317383f, -0.655518f, 0.311523f, -0.655762f, 0.307129f, -0.655762f,
-0.288574f, -0.655762f, 0.276123f, -0.650391f, 0.263672f, -0.64502f, 0.255615f, -0.634766f,
-0.247559f, -0.624512f, 0.242676f, -0.609619f, 0.237793f, -0.594727f, 0.233887f, -0.575684f,
-0.224609f, -0.52832f, 0.327637f, -0.52832f, 0.314941f, -0.464355f, 0.193848f, 0.20752f,
-0.148438f, 0.20752f, 0.114746f, 0.198486f, 0.0810547f, 0.189453f, 0.0578613f, 0.17334f,
-0.034668f, 0.157227f, 0.0212402f, 0.134521f, 0.0078125f, 0.111816f, 0.00195312f,
-0.0844727f, 0.081543f, 0.0639648f, 0.0898438f, 0.101074f, 0.118408f, 0.12085f, 0.146973f,
-0.140625f, 0.195801f, 0.140625f, 0.230957f, 0.140625f, 0.257812f, 0.131592f, 0.284668f,
-0.122559f, 0.303955f, 0.104004f, 0.323242f, 0.0854492f, 0.336182f, 0.0563965f, 0.349121f,
-0.0273438f, 0.356934f, -0.0131836f, 0.359375f, -0.0258789f, 0.362305f, -0.0405273f,
-0.365234f, -0.0551758f, 0.367676f, -0.0678711f, 0.370605f, -0.0830078f, 0.373535f,
--0.0981445f, 0.372559f, -0.0981445f, 0.358887f, -0.0786133f, 0.343506f, -0.0600586f,
-0.328125f, -0.0415039f, 0.308105f, -0.0273438f, 0.288086f, -0.0131836f, 0.261719f,
--0.00463867f, 0.235352f, 0.00390625f, 0.200195f, 0.00390625f, 0.161621f, 0.00390625f,
-0.130859f, -0.00952148f, 0.100098f, -0.0229492f, 0.0786133f, -0.0466309f, 0.0571289f,
--0.0703125f, 0.0456543f, -0.103271f, 0.0341797f, -0.13623f, 0.0341797f, -0.175293f,
-0.0341797f, -0.199219f, 0.0368652f, -0.22583f, 0.0395508f, -0.252441f, 0.0454102f,
--0.283203f, 0.0698242f, -0.410645f, 0.128174f, -0.474121f, 0.186523f, -0.537598f,
-0.287109f, -0.537598f, 0.314941f, -0.537598f, 0.339844f, -0.531006f, 0.364746f, -0.524414f,
-0.384521f, -0.511475f, 0.404297f, -0.498535f, 0.418701f, -0.47998f, 0.433105f, -0.461426f,
-0.439453f, -0.437988f, 0.44043f, -0.437988f, 0.442871f, -0.450195f, 0.446533f, -0.465332f,
-0.450195f, -0.480469f, 0.453613f, -0.493896f, 0.457031f, -0.507324f, 0.459961f, -0.51709f,
-0.462891f, -0.526855f, 0.463867f, -0.52832f, 0.547363f, -0.52832f, 0.546387f, -0.523926f,
-0.543945f, -0.513428f, 0.541504f, -0.50293f, 0.538086f, -0.488281f, 0.534668f, -0.473633f,
-0.531006f, -0.455811f, 0.527344f, -0.437988f, 0.523438f, -0.418945f, 0.444824f, -0.0151367f,
-0.43457f, 0.0371094f, 0.416504f, 0.0783691f, 0.398438f, 0.119629f, 0.368652f, 0.148438f,
-0.338867f, 0.177246f, 0.296143f, 0.192383f, 0.253418f, 0.20752f, 0.193848f, 0.20752f,
-0.126465f, -0.182129f, 0.126465f, -0.123047f, 0.1521f, -0.092041f, 0.177734f, -0.0610352f,
-0.227539f, -0.0610352f, 0.253906f, -0.0610352f, 0.281006f, -0.0722656f, 0.308105f,
--0.0834961f, 0.332275f, -0.10791f, 0.356445f, -0.132324f, 0.375732f, -0.170898f,
-0.39502f, -0.209473f, 0.405762f, -0.26416f, 0.409668f, -0.284668f, 0.411621f, -0.306396f,
-0.413574f, -0.328125f, 0.413574f, -0.34375f, 0.413574f, -0.376465f, 0.404785f, -0.400635f,
-0.395996f, -0.424805f, 0.380127f, -0.440918f, 0.364258f, -0.457031f, 0.342773f, -0.464844f,
-0.321289f, -0.472656f, 0.296387f, -0.472656f, 0.266113f, -0.472656f, 0.241455f, -0.463623f,
-0.216797f, -0.45459f, 0.197266f, -0.432861f, 0.177734f, -0.411133f, 0.163086f, -0.374756f,
-0.148438f, -0.338379f, 0.137695f, -0.283203f, 0.132324f, -0.254395f, 0.129395f, -0.228027f,
-0.126465f, -0.20166f, 0.126465f, -0.182129f, 0.322266f, 0, 0.382812f, -0.30957f,
-0.384766f, -0.319336f, 0.386963f, -0.331055f, 0.38916f, -0.342773f, 0.390869f, -0.354492f,
-0.392578f, -0.366211f, 0.393799f, -0.376709f, 0.39502f, -0.387207f, 0.39502f, -0.394531f,
-0.39502f, -0.431152f, 0.376465f, -0.450439f, 0.35791f, -0.469727f, 0.315918f, -0.469727f,
-0.288086f, -0.469727f, 0.262939f, -0.457275f, 0.237793f, -0.444824f, 0.217773f, -0.422119f,
-0.197754f, -0.399414f, 0.183105f, -0.366943f, 0.168457f, -0.334473f, 0.161621f, -0.294922f,
-0.104004f, 0, 0.0166016f, 0, 0.0976562f, -0.415527f, 0.101074f, -0.432129f, 0.104248f,
--0.450439f, 0.107422f, -0.46875f, 0.110107f, -0.485107f, 0.112793f, -0.501465f, 0.114502f,
--0.513184f, 0.116211f, -0.524902f, 0.116699f, -0.52832f, 0.199707f, -0.52832f, 0.199707f,
--0.525879f, 0.198242f, -0.515137f, 0.196777f, -0.504395f, 0.19458f, -0.490479f, 0.192383f,
--0.476562f, 0.190186f, -0.462158f, 0.187988f, -0.447754f, 0.186035f, -0.437988f,
-0.1875f, -0.437988f, 0.202148f, -0.460938f, 0.217773f, -0.479492f, 0.233398f, -0.498047f,
-0.251953f, -0.510986f, 0.270508f, -0.523926f, 0.293213f, -0.530762f, 0.315918f, -0.537598f,
-0.344727f, -0.537598f, 0.403809f, -0.537598f, 0.438477f, -0.508545f, 0.473145f, -0.479492f,
-0.47998f, -0.424316f, 0.495605f, -0.44873f, 0.512207f, -0.469238f, 0.528809f, -0.489746f,
-0.549072f, -0.505127f, 0.569336f, -0.520508f, 0.593994f, -0.529053f, 0.618652f, -0.537598f,
-0.649902f, -0.537598f, 0.71582f, -0.537598f, 0.751221f, -0.501953f, 0.786621f, -0.466309f,
-0.786621f, -0.398926f, 0.786621f, -0.381348f, 0.783447f, -0.359375f, 0.780273f, -0.337402f,
-0.776367f, -0.318848f, 0.714355f, 0, 0.627441f, 0, 0.687988f, -0.30957f, 0.689941f,
--0.319336f, 0.692139f, -0.331055f, 0.694336f, -0.342773f, 0.696045f, -0.354492f,
-0.697754f, -0.366211f, 0.698975f, -0.376709f, 0.700195f, -0.387207f, 0.700195f, -0.394531f,
-0.700195f, -0.431152f, 0.681641f, -0.450439f, 0.663086f, -0.469727f, 0.621094f, -0.469727f,
-0.593262f, -0.469727f, 0.568115f, -0.45752f, 0.542969f, -0.445312f, 0.522949f, -0.422852f,
-0.50293f, -0.400391f, 0.488281f, -0.368164f, 0.473633f, -0.335938f, 0.466797f, -0.296387f,
-0.40918f, 0, 0.350098f, 0, 0.411621f, -0.314941f, 0.415527f, -0.333984f, 0.417969f,
--0.35376f, 0.42041f, -0.373535f, 0.42041f, -0.388184f, 0.42041f, -0.426758f, 0.399902f,
--0.448242f, 0.379395f, -0.469727f, 0.333008f, -0.469727f, 0.301758f, -0.469727f,
-0.27417f, -0.457275f, 0.246582f, -0.444824f, 0.224121f, -0.422119f, 0.20166f, -0.399414f,
-0.185791f, -0.367432f, 0.169922f, -0.335449f, 0.162109f, -0.295898f, 0.104492f, 0,
-0.0166016f, 0, 0.0976562f, -0.415527f, 0.101074f, -0.432129f, 0.104248f, -0.450439f,
-0.107422f, -0.46875f, 0.110107f, -0.485107f, 0.112793f, -0.501465f, 0.114502f, -0.513184f,
-0.116211f, -0.524902f, 0.116699f, -0.52832f, 0.199707f, -0.52832f, 0.199707f, -0.525879f,
-0.198242f, -0.515137f, 0.196777f, -0.504395f, 0.19458f, -0.490479f, 0.192383f, -0.476562f,
-0.190186f, -0.462158f, 0.187988f, -0.447754f, 0.186035f, -0.437988f, 0.1875f, -0.437988f,
-0.204102f, -0.460938f, 0.22168f, -0.479492f, 0.239258f, -0.498047f, 0.260498f, -0.510986f,
-0.281738f, -0.523926f, 0.307373f, -0.530762f, 0.333008f, -0.537598f, 0.365723f, -0.537598f,
-0.437988f, -0.537598f, 0.474365f, -0.501953f, 0.510742f, -0.466309f, 0.510742f, -0.398926f,
-0.510742f, -0.381348f, 0.507568f, -0.359375f, 0.504395f, -0.337402f, 0.500488f, -0.318848f,
-0.438477f, 0, 0.524414f, -0.333496f, 0.524414f, -0.308105f, 0.521484f, -0.282471f,
-0.518555f, -0.256836f, 0.511719f, -0.228027f, 0.49707f, -0.163574f, 0.470947f, -0.118164f,
-0.444824f, -0.0727539f, 0.409668f, -0.0444336f, 0.374512f, -0.0161133f, 0.331543f,
--0.00317383f, 0.288574f, 0.00976562f, 0.239746f, 0.00976562f, 0.192871f, 0.00976562f,
-0.154785f, -0.00463867f, 0.116699f, -0.019043f, 0.0895996f, -0.0466309f, 0.0625f,
--0.0742188f, 0.0476074f, -0.114014f, 0.0327148f, -0.153809f, 0.0327148f, -0.20459f,
-0.0332031f, -0.227539f, 0.0354004f, -0.251953f, 0.0375977f, -0.276367f, 0.043457f,
--0.302734f, 0.0576172f, -0.364258f, 0.0825195f, -0.408447f, 0.107422f, -0.452637f,
-0.141602f, -0.481445f, 0.175781f, -0.510254f, 0.218994f, -0.523926f, 0.262207f, -0.537598f,
-0.313477f, -0.537598f, 0.365234f, -0.537598f, 0.404541f, -0.523926f, 0.443848f, -0.510254f,
-0.470459f, -0.483887f, 0.49707f, -0.45752f, 0.510742f, -0.419678f, 0.524414f, -0.381836f,
-0.524414f, -0.333496f, 0.433594f, -0.333496f, 0.433594f, -0.371094f, 0.425293f, -0.397461f,
-0.416992f, -0.423828f, 0.401123f, -0.440674f, 0.385254f, -0.45752f, 0.362793f, -0.465332f,
-0.340332f, -0.473145f, 0.3125f, -0.473145f, 0.286621f, -0.473145f, 0.260498f, -0.467041f,
-0.234375f, -0.460938f, 0.210693f, -0.442383f, 0.187012f, -0.423828f, 0.16748f, -0.389648f,
-0.147949f, -0.355469f, 0.134766f, -0.298828f, 0.128418f, -0.271973f, 0.125732f, -0.247803f,
-0.123047f, -0.223633f, 0.123047f, -0.203125f, 0.123047f, -0.163086f, 0.132324f, -0.134766f,
-0.141602f, -0.106445f, 0.157959f, -0.0888672f, 0.174316f, -0.0712891f, 0.196533f,
--0.0632324f, 0.21875f, -0.0551758f, 0.245117f, -0.0551758f, 0.271484f, -0.0551758f,
-0.297119f, -0.0610352f, 0.322754f, -0.0668945f, 0.345703f, -0.0856934f, 0.368652f,
--0.104492f, 0.387939f, -0.13916f, 0.407227f, -0.173828f, 0.42041f, -0.230957f, 0.427246f,
--0.260254f, 0.429932f, -0.284668f, 0.432617f, -0.309082f, 0.433594f, -0.333496f,
-0.270508f, 0.00976562f, 0.210449f, 0.00976562f, 0.172607f, -0.015625f, 0.134766f,
--0.0410156f, 0.119141f, -0.0869141f, 0.116699f, -0.0869141f, 0.116699f, -0.0859375f,
-0.115723f, -0.0773926f, 0.114746f, -0.0688477f, 0.112793f, -0.0561523f, 0.11084f,
--0.043457f, 0.108154f, -0.0283203f, 0.105469f, -0.0131836f, 0.102539f, 0.000976562f,
-0.0625f, 0.20752f, -0.0249023f, 0.20752f, 0.0966797f, -0.42041f, 0.100586f, -0.439453f,
-0.103516f, -0.457031f, 0.106445f, -0.474609f, 0.108643f, -0.489014f, 0.11084f, -0.503418f,
-0.112061f, -0.513672f, 0.113281f, -0.523926f, 0.11377f, -0.52832f, 0.195312f, -0.52832f,
-0.195312f, -0.524414f, 0.194824f, -0.515625f, 0.194336f, -0.506836f, 0.193115f, -0.49585f,
-0.191895f, -0.484863f, 0.19043f, -0.472656f, 0.188965f, -0.460449f, 0.187012f, -0.449707f,
-0.188965f, -0.449707f, 0.206543f, -0.472656f, 0.224854f, -0.489258f, 0.243164f, -0.505859f,
-0.263916f, -0.516846f, 0.284668f, -0.527832f, 0.308594f, -0.532959f, 0.33252f, -0.538086f,
-0.361816f, -0.538086f, 0.400879f, -0.538086f, 0.431152f, -0.525879f, 0.461426f, -0.513672f,
-0.481934f, -0.491211f, 0.502441f, -0.46875f, 0.513184f, -0.436768f, 0.523926f, -0.404785f,
-0.523926f, -0.365234f, 0.523926f, -0.34082f, 0.521729f, -0.311768f, 0.519531f, -0.282715f,
-0.513672f, -0.251953f, 0.500488f, -0.182617f, 0.479004f, -0.133057f, 0.45752f, -0.0834961f,
-0.427246f, -0.0517578f, 0.396973f, -0.0200195f, 0.35791f, -0.00512695f, 0.318848f,
-0.00976562f, 0.270508f, 0.00976562f, 0.336426f, -0.470215f, 0.305176f, -0.470215f,
-0.2771f, -0.460938f, 0.249023f, -0.45166f, 0.225098f, -0.428955f, 0.201172f, -0.40625f,
-0.182861f, -0.367676f, 0.164551f, -0.329102f, 0.15332f, -0.270508f, 0.144043f, -0.222656f,
-0.144043f, -0.184082f, 0.144043f, -0.152832f, 0.152344f, -0.128662f, 0.160645f, -0.104492f,
-0.176025f, -0.0881348f, 0.191406f, -0.0717773f, 0.213135f, -0.0634766f, 0.234863f,
--0.0551758f, 0.26123f, -0.0551758f, 0.291504f, -0.0551758f, 0.315918f, -0.064209f,
-0.340332f, -0.0732422f, 0.360107f, -0.095459f, 0.379883f, -0.117676f, 0.39502f, -0.155029f,
-0.410156f, -0.192383f, 0.420898f, -0.249023f, 0.432129f, -0.308105f, 0.432129f, -0.349609f,
-0.432129f, -0.409668f, 0.40918f, -0.439941f, 0.38623f, -0.470215f, 0.336426f, -0.470215f,
-0.350586f, -0.458008f, 0.342285f, -0.460449f, 0.330811f, -0.462402f, 0.319336f, -0.464355f,
-0.306641f, -0.464355f, 0.275391f, -0.464355f, 0.250488f, -0.446289f, 0.225586f, -0.428223f,
-0.206787f, -0.400391f, 0.187988f, -0.372559f, 0.175781f, -0.339111f, 0.163574f, -0.305664f,
-0.158203f, -0.275391f, 0.104492f, 0, 0.0166016f, 0, 0.0957031f, -0.405273f, 0.0991211f,
--0.422363f, 0.102051f, -0.439453f, 0.10498f, -0.456543f, 0.107666f, -0.472656f, 0.110352f,
--0.48877f, 0.112793f, -0.503174f, 0.115234f, -0.517578f, 0.116699f, -0.52832f, 0.199707f,
--0.52832f, 0.198242f, -0.517578f, 0.196045f, -0.50293f, 0.193848f, -0.488281f, 0.191406f,
--0.473145f, 0.188965f, -0.458008f, 0.186768f, -0.444092f, 0.18457f, -0.430176f, 0.182617f,
--0.42041f, 0.18457f, -0.42041f, 0.199707f, -0.450684f, 0.2146f, -0.4729f, 0.229492f,
--0.495117f, 0.245605f, -0.509521f, 0.261719f, -0.523926f, 0.280029f, -0.531006f,
-0.29834f, -0.538086f, 0.320312f, -0.538086f, 0.325684f, -0.538086f, 0.332031f, -0.537354f,
-0.338379f, -0.536621f, 0.344971f, -0.535645f, 0.351562f, -0.534668f, 0.357422f, -0.533447f,
-0.363281f, -0.532227f, 0.366699f, -0.53125f, 0.442871f, -0.154785f, 0.442871f, -0.113281f,
-0.42627f, -0.0822754f, 0.409668f, -0.0512695f, 0.37915f, -0.0307617f, 0.348633f,
--0.0102539f, 0.305176f, -0.000244141f, 0.261719f, 0.00976562f, 0.20752f, 0.00976562f,
-0.162109f, 0.00976562f, 0.12793f, 0.00195312f, 0.09375f, -0.00585938f, 0.0690918f,
--0.020752f, 0.0444336f, -0.0356445f, 0.0280762f, -0.0578613f, 0.0117188f, -0.0800781f,
-0.00244141f, -0.108887f, 0.0742188f, -0.13623f, 0.081543f, -0.116699f, 0.0930176f,
--0.101318f, 0.104492f, -0.0859375f, 0.121338f, -0.0754395f, 0.138184f, -0.0649414f,
-0.161377f, -0.0595703f, 0.18457f, -0.0541992f, 0.215332f, -0.0541992f, 0.246582f,
--0.0541992f, 0.272705f, -0.0593262f, 0.298828f, -0.0644531f, 0.317627f, -0.0756836f,
-0.336426f, -0.0869141f, 0.346924f, -0.104492f, 0.357422f, -0.12207f, 0.357422f, -0.146973f,
-0.357422f, -0.166504f, 0.348145f, -0.18042f, 0.338867f, -0.194336f, 0.322021f, -0.204834f,
-0.305176f, -0.215332f, 0.281006f, -0.224365f, 0.256836f, -0.233398f, 0.227051f, -0.242676f,
-0.195312f, -0.25293f, 0.166748f, -0.265137f, 0.138184f, -0.277344f, 0.116455f, -0.294434f,
-0.0947266f, -0.311523f, 0.0817871f, -0.334717f, 0.0688477f, -0.35791f, 0.0688477f,
--0.38916f, 0.0688477f, -0.429199f, 0.0861816f, -0.457275f, 0.103516f, -0.485352f,
-0.133057f, -0.50293f, 0.162598f, -0.520508f, 0.201904f, -0.528564f, 0.241211f, -0.536621f,
-0.285156f, -0.536621f, 0.325195f, -0.536621f, 0.358398f, -0.529785f, 0.391602f, -0.522949f,
-0.416504f, -0.508057f, 0.441406f, -0.493164f, 0.45752f, -0.469482f, 0.473633f, -0.445801f,
-0.479492f, -0.412109f, 0.399902f, -0.399902f, 0.38916f, -0.438477f, 0.359375f, -0.455566f,
-0.32959f, -0.472656f, 0.279297f, -0.472656f, 0.253418f, -0.472656f, 0.230713f, -0.46875f,
-0.208008f, -0.464844f, 0.190918f, -0.456055f, 0.173828f, -0.447266f, 0.163818f, -0.433105f,
-0.153809f, -0.418945f, 0.153809f, -0.398926f, 0.153809f, -0.378906f, 0.163086f, -0.365479f,
-0.172363f, -0.352051f, 0.189209f, -0.341797f, 0.206055f, -0.331543f, 0.229736f, -0.323486f,
-0.253418f, -0.31543f, 0.282715f, -0.306152f, 0.310547f, -0.297363f, 0.339111f, -0.285645f,
-0.367676f, -0.273926f, 0.390625f, -0.256592f, 0.413574f, -0.239258f, 0.428223f, -0.2146f,
-0.442871f, -0.189941f, 0.442871f, -0.154785f, 0.202637f, -0.52832f, 0.141113f, -0.213379f,
-0.137207f, -0.194336f, 0.134766f, -0.174561f, 0.132324f, -0.154785f, 0.132324f, -0.140137f,
-0.132324f, -0.101562f, 0.152832f, -0.0800781f, 0.17334f, -0.0585938f, 0.219727f,
--0.0585938f, 0.250977f, -0.0585938f, 0.278564f, -0.0710449f, 0.306152f, -0.0834961f,
-0.328613f, -0.106201f, 0.351074f, -0.128906f, 0.366943f, -0.160889f, 0.382812f, -0.192871f,
-0.390625f, -0.232422f, 0.448242f, -0.52832f, 0.536133f, -0.52832f, 0.455078f, -0.112793f,
-0.45166f, -0.0961914f, 0.448486f, -0.0778809f, 0.445312f, -0.0595703f, 0.442627f,
--0.0432129f, 0.439941f, -0.0268555f, 0.438232f, -0.0151367f, 0.436523f, -0.00341797f,
-0.436035f, 0, 0.353027f, 0, 0.353027f, -0.00244141f, 0.354492f, -0.0131836f, 0.355957f,
--0.0239258f, 0.358154f, -0.0378418f, 0.360352f, -0.0517578f, 0.362549f, -0.0661621f,
-0.364746f, -0.0805664f, 0.366699f, -0.090332f, 0.365234f, -0.090332f, 0.348633f,
--0.0673828f, 0.331055f, -0.0488281f, 0.313477f, -0.0302734f, 0.292236f, -0.017334f,
-0.270996f, -0.00439453f, 0.245361f, 0.00244141f, 0.219727f, 0.00927734f, 0.187012f,
-0.00927734f, 0.114746f, 0.00927734f, 0.0783691f, -0.0263672f, 0.0419922f, -0.0620117f,
-0.0419922f, -0.129395f, 0.0419922f, -0.146973f, 0.045166f, -0.168945f, 0.0483398f,
--0.190918f, 0.0522461f, -0.209473f, 0.114258f, -0.52832f, 0.244629f, 0, 0.217773f,
-0.0463867f, 0.192871f, 0.0844727f, 0.167969f, 0.122559f, 0.140625f, 0.149902f, 0.113281f,
-0.177246f, 0.0812988f, 0.192383f, 0.0493164f, 0.20752f, 0.0078125f, 0.20752f, -0.00830078f,
-0.20752f, -0.0251465f, 0.205811f, -0.0419922f, 0.204102f, -0.0566406f, 0.200684f,
--0.0415039f, 0.135254f, -0.0332031f, 0.136719f, -0.0227051f, 0.137939f, -0.012207f,
-0.13916f, -0.00390625f, 0.13916f, 0.0424805f, 0.13916f, 0.0778809f, 0.10791f, 0.113281f,
-0.0766602f, 0.147461f, 0.0170898f, 0.160645f, -0.00585938f, 0.0546875f, -0.52832f,
-0.144043f, -0.52832f, 0.19873f, -0.236328f, 0.20166f, -0.220703f, 0.205078f, -0.200195f,
-0.208496f, -0.179688f, 0.211426f, -0.159424f, 0.214355f, -0.13916f, 0.216553f, -0.121826f,
-0.21875f, -0.104492f, 0.219238f, -0.0957031f, 0.224121f, -0.106445f, 0.231934f, -0.121826f,
-0.239746f, -0.137207f, 0.249268f, -0.154541f, 0.258789f, -0.171875f, 0.268799f, -0.190186f,
-0.278809f, -0.208496f, 0.288086f, -0.225586f, 0.453125f, -0.52832f, 0.550293f, -0.52832f
-};
-
-const unsigned char LiberationSanskItalicVerbs[] = {
-6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1,
-1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6
-};
-
-const unsigned LiberationSanskItalicCharCodes[] = {
-32, 65, 72, 84, 87, 89, 97,
-98, 101, 102, 103, 109, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed LiberationSanskItalicWidths[] = {
-0x00004720, 0x0000aac0, 0x0000b8e0, 0x00009c60, 0x0000f1a0, 0x0000aac0, 0x00008e60,
-0x00008e60, 0x00008e60, 0x00004720, 0x00008e60, 0x0000d540, 0x00008e60, 0x00008e60,
-0x00008e60, 0x00005540, 0x00008000, 0x00008e60, 0x00008000
-};
-
-const int LiberationSanskItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSanskItalicCharCodes);
-
-const SkPaint::FontMetrics LiberationSanskItalicMetrics = {
-0x00000003, -1.01416f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.33447f, 0,
--0.271973f, 1.0625f, 0.537598f, 0, 0.0732422f, 0.105957f
-};
-
-const SkScalar LiberationSanskBoldItalicPoints[] = {
-0.206543f, -0.208008f, 0.0942383f, -0.208008f, 0.172363f, -0.687988f, 0.315918f, -0.687988f,
-0.0385742f, 0, 0.0639648f, -0.131836f, 0.20459f, -0.131836f, 0.179199f, 0, 0.169434f,
--0.0322266f, 0.163086f, 0.000488281f, 0.154297f, 0.0273438f, 0.145508f, 0.0541992f,
-0.134277f, 0.0769043f, 0.123047f, 0.0996094f, 0.109619f, 0.118652f, 0.0961914f, 0.137695f,
-0.0805664f, 0.154785f, -0.00976562f, 0.154785f, 0.00732422f, 0.137695f, 0.0229492f,
-0.118652f, 0.0385742f, 0.0996094f, 0.0512695f, 0.0795898f, 0.0639648f, 0.0595703f,
-0.0727539f, 0.0395508f, 0.081543f, 0.0195312f, 0.0854492f, 0, 0.0224609f, 0, 0.0512695f,
--0.148926f, 0.192383f, -0.148926f, 0.0273438f, -0.199707f, 0.050293f, -0.318848f,
-0.304199f, -0.318848f, 0.28125f, -0.199707f, 0.0224609f, 0, 0.0512695f, -0.148926f,
-0.192383f, -0.148926f, 0.163574f, 0, -0.0371094f, 0.0200195f, 0.249512f, -0.724609f,
-0.365723f, -0.724609f, 0.0810547f, 0.0200195f, 0.353516f, -0.698242f, 0.394043f,
--0.698242f, 0.429199f, -0.687256f, 0.464355f, -0.67627f, 0.490234f, -0.649902f, 0.516113f,
--0.623535f, 0.53125f, -0.579834f, 0.546387f, -0.536133f, 0.546387f, -0.470703f, 0.546387f,
--0.439941f, 0.541748f, -0.404785f, 0.537109f, -0.369629f, 0.527832f, -0.324707f,
-0.51416f, -0.259766f, 0.495605f, -0.209473f, 0.477051f, -0.15918f, 0.454346f, -0.12207f,
-0.431641f, -0.0849609f, 0.405762f, -0.0598145f, 0.379883f, -0.034668f, 0.351562f,
--0.019043f, 0.323242f, -0.00341797f, 0.293457f, 0.00317383f, 0.263672f, 0.00976562f,
-0.233398f, 0.00976562f, 0.1875f, 0.00976562f, 0.151855f, -0.00317383f, 0.116211f,
--0.0161133f, 0.0915527f, -0.0441895f, 0.0668945f, -0.0722656f, 0.0541992f, -0.116211f,
-0.0415039f, -0.160156f, 0.0415039f, -0.22168f, 0.0415039f, -0.251465f, 0.0456543f,
--0.285645f, 0.0498047f, -0.319824f, 0.0581055f, -0.364258f, 0.0712891f, -0.433105f,
-0.090332f, -0.484863f, 0.109375f, -0.536621f, 0.132568f, -0.57373f, 0.155762f, -0.61084f,
-0.182373f, -0.63501f, 0.208984f, -0.65918f, 0.237305f, -0.673096f, 0.265625f, -0.687012f,
-0.295166f, -0.692627f, 0.324707f, -0.698242f, 0.353516f, -0.698242f, 0.242676f, -0.0981445f,
-0.269531f, -0.0981445f, 0.291748f, -0.109619f, 0.313965f, -0.121094f, 0.33252f, -0.148438f,
-0.351074f, -0.175781f, 0.366211f, -0.221191f, 0.381348f, -0.266602f, 0.393555f, -0.334473f,
-0.401855f, -0.380371f, 0.407471f, -0.414307f, 0.413086f, -0.448242f, 0.413086f, -0.477051f,
-0.413086f, -0.530762f, 0.395264f, -0.560791f, 0.377441f, -0.59082f, 0.338867f, -0.59082f,
-0.30957f, -0.59082f, 0.287598f, -0.579346f, 0.265625f, -0.567871f, 0.248535f, -0.540771f,
-0.231445f, -0.513672f, 0.218262f, -0.468262f, 0.205078f, -0.422852f, 0.193359f, -0.354492f,
-0.186035f, -0.312012f, 0.18042f, -0.271729f, 0.174805f, -0.231445f, 0.174805f, -0.202637f,
-0.174805f, -0.180664f, 0.177979f, -0.161377f, 0.181152f, -0.14209f, 0.188965f, -0.128174f,
-0.196777f, -0.114258f, 0.209961f, -0.106201f, 0.223145f, -0.0981445f, 0.242676f,
--0.0981445f, 0.0161133f, 0, 0.0371094f, -0.112793f, 0.20752f, -0.112793f, 0.294922f,
--0.5625f, 0.108887f, -0.458008f, 0.131836f, -0.576172f, 0.325195f, -0.687988f, 0.457031f,
--0.687988f, 0.344727f, -0.112793f, 0.502441f, -0.112793f, 0.480957f, 0, -0.015625f,
-0, 0.00244141f, -0.0952148f, 0.0258789f, -0.135742f, 0.0556641f, -0.169189f, 0.0854492f,
--0.202637f, 0.118164f, -0.230957f, 0.150879f, -0.259277f, 0.184814f, -0.283691f,
-0.21875f, -0.308105f, 0.250732f, -0.330566f, 0.282715f, -0.353027f, 0.310791f, -0.374268f,
-0.338867f, -0.395508f, 0.359619f, -0.418213f, 0.380371f, -0.440918f, 0.392578f, -0.465576f,
-0.404785f, -0.490234f, 0.404785f, -0.519043f, 0.404785f, -0.538574f, 0.398926f, -0.552002f,
-0.393066f, -0.56543f, 0.382568f, -0.573486f, 0.37207f, -0.581543f, 0.357422f, -0.585205f,
-0.342773f, -0.588867f, 0.325684f, -0.588867f, 0.306641f, -0.588867f, 0.290039f, -0.584473f,
-0.273438f, -0.580078f, 0.259521f, -0.569824f, 0.245605f, -0.55957f, 0.234863f, -0.542236f,
-0.224121f, -0.524902f, 0.216797f, -0.499023f, 0.0869141f, -0.527832f, 0.0986328f,
--0.567383f, 0.118652f, -0.598877f, 0.138672f, -0.630371f, 0.168945f, -0.652344f,
-0.199219f, -0.674316f, 0.240479f, -0.686279f, 0.281738f, -0.698242f, 0.335449f, -0.698242f,
-0.390625f, -0.698242f, 0.430176f, -0.686279f, 0.469727f, -0.674316f, 0.495605f, -0.652344f,
-0.521484f, -0.630371f, 0.533691f, -0.599121f, 0.545898f, -0.567871f, 0.545898f, -0.528809f,
-0.545898f, -0.490723f, 0.533691f, -0.458496f, 0.521484f, -0.42627f, 0.500488f, -0.398438f,
-0.479492f, -0.370605f, 0.451904f, -0.346191f, 0.424316f, -0.321777f, 0.393311f, -0.299316f,
-0.362305f, -0.276855f, 0.330078f, -0.255127f, 0.297852f, -0.233398f, 0.267822f, -0.210938f,
-0.237793f, -0.188477f, 0.211914f, -0.164307f, 0.186035f, -0.140137f, 0.16748f, -0.112793f,
-0.486816f, -0.112793f, 0.465332f, 0, 0.26123f, -0.404785f, 0.28418f, -0.404785f,
-0.309814f, -0.408691f, 0.335449f, -0.412598f, 0.356689f, -0.424316f, 0.37793f, -0.436035f,
-0.391846f, -0.457275f, 0.405762f, -0.478516f, 0.405762f, -0.513184f, 0.405762f, -0.54834f,
-0.386963f, -0.568604f, 0.368164f, -0.588867f, 0.329102f, -0.588867f, 0.284668f, -0.588867f,
-0.255371f, -0.566895f, 0.226074f, -0.544922f, 0.213379f, -0.499023f, 0.0830078f,
--0.524414f, 0.0961914f, -0.570312f, 0.119141f, -0.603271f, 0.14209f, -0.63623f, 0.173828f,
--0.657227f, 0.205566f, -0.678223f, 0.24585f, -0.688232f, 0.286133f, -0.698242f, 0.334473f,
--0.698242f, 0.384277f, -0.698242f, 0.42334f, -0.686768f, 0.462402f, -0.675293f, 0.489502f,
--0.653564f, 0.516602f, -0.631836f, 0.530762f, -0.60083f, 0.544922f, -0.569824f, 0.544922f,
--0.530273f, 0.544922f, -0.493164f, 0.533203f, -0.462402f, 0.521484f, -0.431641f,
-0.498779f, -0.408936f, 0.476074f, -0.38623f, 0.443359f, -0.37207f, 0.410645f, -0.35791f,
-0.368652f, -0.354004f, 0.368164f, -0.352051f, 0.398926f, -0.347168f, 0.423828f, -0.335693f,
-0.44873f, -0.324219f, 0.466309f, -0.305664f, 0.483887f, -0.287109f, 0.493408f, -0.261719f,
-0.50293f, -0.236328f, 0.50293f, -0.204102f, 0.50293f, -0.161621f, 0.486328f, -0.122803f,
-0.469727f, -0.0839844f, 0.437744f, -0.0544434f, 0.405762f, -0.0249023f, 0.358398f,
--0.00756836f, 0.311035f, 0.00976562f, 0.249512f, 0.00976562f, 0.188965f, 0.00976562f,
-0.144775f, -0.00341797f, 0.100586f, -0.0166016f, 0.0712891f, -0.0402832f, 0.0419922f,
--0.0639648f, 0.0266113f, -0.0964355f, 0.0112305f, -0.128906f, 0.0078125f, -0.16748f,
-0.145508f, -0.186035f, 0.148438f, -0.161621f, 0.156982f, -0.145264f, 0.165527f, -0.128906f,
-0.179443f, -0.118896f, 0.193359f, -0.108887f, 0.212646f, -0.104736f, 0.231934f, -0.100586f,
-0.255859f, -0.100586f, 0.283203f, -0.100586f, 0.303467f, -0.108398f, 0.32373f, -0.116211f,
-0.337158f, -0.129883f, 0.350586f, -0.143555f, 0.357178f, -0.162354f, 0.36377f, -0.181152f,
-0.36377f, -0.203125f, 0.36377f, -0.248535f, 0.337402f, -0.27124f, 0.311035f, -0.293945f,
-0.256348f, -0.293945f, 0.204102f, -0.293945f, 0.225586f, -0.404785f, 0.426758f, -0.139648f,
-0.400391f, 0, 0.269531f, 0, 0.295898f, -0.139648f, -0.0166016f, -0.139648f, 0.00341797f,
--0.240723f, 0.353516f, -0.687988f, 0.53418f, -0.687988f, 0.447266f, -0.242188f, 0.539062f,
--0.242188f, 0.518555f, -0.139648f, 0.366211f, -0.498047f, 0.367676f, -0.505371f,
-0.370605f, -0.517578f, 0.373535f, -0.529785f, 0.377197f, -0.543213f, 0.380859f, -0.556641f,
-0.384521f, -0.569092f, 0.388184f, -0.581543f, 0.390625f, -0.588867f, 0.387207f, -0.583008f,
-0.380371f, -0.57251f, 0.373535f, -0.562012f, 0.365479f, -0.550049f, 0.357422f, -0.538086f,
-0.348877f, -0.526367f, 0.340332f, -0.514648f, 0.333496f, -0.505859f, 0.126465f, -0.242188f,
-0.316406f, -0.242188f, 0.154297f, -0.687988f, 0.567871f, -0.687988f, 0.546875f, -0.575195f,
-0.256836f, -0.575195f, 0.214355f, -0.412109f, 0.223145f, -0.419922f, 0.235107f, -0.427734f,
-0.24707f, -0.435547f, 0.262207f, -0.441895f, 0.277344f, -0.448242f, 0.296387f, -0.452148f,
-0.31543f, -0.456055f, 0.338867f, -0.456055f, 0.376953f, -0.456055f, 0.409912f, -0.442871f,
-0.442871f, -0.429688f, 0.467285f, -0.403809f, 0.491699f, -0.37793f, 0.505615f, -0.340088f,
-0.519531f, -0.302246f, 0.519531f, -0.25293f, 0.519531f, -0.194824f, 0.500488f, -0.146484f,
-0.481445f, -0.0981445f, 0.445312f, -0.0634766f, 0.40918f, -0.0288086f, 0.356689f,
--0.00952148f, 0.304199f, 0.00976562f, 0.237305f, 0.00976562f, 0.182617f, 0.00976562f,
-0.142578f, -0.00317383f, 0.102539f, -0.0161133f, 0.0749512f, -0.0388184f, 0.0473633f,
--0.0615234f, 0.0314941f, -0.0927734f, 0.015625f, -0.124023f, 0.00976562f, -0.160645f,
-0.147949f, -0.182617f, 0.151855f, -0.162109f, 0.158691f, -0.146729f, 0.165527f, -0.131348f,
-0.177246f, -0.121094f, 0.188965f, -0.11084f, 0.206543f, -0.105713f, 0.224121f, -0.100586f,
-0.249023f, -0.100586f, 0.281738f, -0.100586f, 0.306396f, -0.111328f, 0.331055f, -0.12207f,
-0.347412f, -0.140869f, 0.36377f, -0.159668f, 0.371826f, -0.18457f, 0.379883f, -0.209473f,
-0.379883f, -0.237305f, 0.379883f, -0.265625f, 0.372803f, -0.286133f, 0.365723f, -0.306641f,
-0.353271f, -0.319824f, 0.34082f, -0.333008f, 0.323975f, -0.339111f, 0.307129f, -0.345215f,
-0.287598f, -0.345215f, 0.255859f, -0.345215f, 0.231934f, -0.333984f, 0.208008f, -0.322754f,
-0.188965f, -0.300781f, 0.0551758f, -0.300781f, 0.260254f, 0.00976562f, 0.208008f,
-0.00976562f, 0.168213f, -0.00708008f, 0.128418f, -0.0239258f, 0.101318f, -0.0559082f,
-0.0742188f, -0.0878906f, 0.0603027f, -0.133789f, 0.0463867f, -0.179688f, 0.0463867f,
--0.237793f, 0.0463867f, -0.337402f, 0.0695801f, -0.421631f, 0.0927734f, -0.505859f,
-0.134521f, -0.567383f, 0.17627f, -0.628906f, 0.234863f, -0.663574f, 0.293457f, -0.698242f,
-0.36377f, -0.698242f, 0.397461f, -0.698242f, 0.430664f, -0.690918f, 0.463867f, -0.683594f,
-0.491211f, -0.665527f, 0.518555f, -0.647461f, 0.537354f, -0.616943f, 0.556152f, -0.586426f,
-0.561523f, -0.540039f, 0.431641f, -0.52002f, 0.424805f, -0.555664f, 0.406738f, -0.572754f,
-0.388672f, -0.589844f, 0.356445f, -0.589844f, 0.300293f, -0.589844f, 0.258789f, -0.533691f,
-0.217285f, -0.477539f, 0.198242f, -0.364258f, 0.224121f, -0.399414f, 0.263916f, -0.421143f,
-0.303711f, -0.442871f, 0.354004f, -0.442871f, 0.392578f, -0.442871f, 0.424316f, -0.430908f,
-0.456055f, -0.418945f, 0.47876f, -0.395752f, 0.501465f, -0.372559f, 0.513916f, -0.338623f,
-0.526367f, -0.304688f, 0.526367f, -0.260254f, 0.526367f, -0.206055f, 0.507568f, -0.157227f,
-0.48877f, -0.108398f, 0.454102f, -0.0712891f, 0.419434f, -0.0341797f, 0.370361f,
--0.012207f, 0.321289f, 0.00976562f, 0.260254f, 0.00976562f, 0.180176f, -0.209473f,
-0.180176f, -0.158203f, 0.204102f, -0.12793f, 0.228027f, -0.0976562f, 0.272461f, -0.0976562f,
-0.297363f, -0.0976562f, 0.318359f, -0.107422f, 0.339355f, -0.117188f, 0.354492f,
--0.135986f, 0.369629f, -0.154785f, 0.378174f, -0.181885f, 0.386719f, -0.208984f,
-0.386719f, -0.243652f, 0.386719f, -0.269043f, 0.380127f, -0.287598f, 0.373535f, -0.306152f,
-0.361816f, -0.318115f, 0.350098f, -0.330078f, 0.334229f, -0.335938f, 0.318359f, -0.341797f,
-0.299805f, -0.341797f, 0.277832f, -0.341797f, 0.256348f, -0.333496f, 0.234863f, -0.325195f,
-0.218018f, -0.308838f, 0.201172f, -0.29248f, 0.190674f, -0.267578f, 0.180176f, -0.242676f,
-0.180176f, -0.209473f, 0.345215f, -0.697754f, 0.394531f, -0.697754f, 0.43335f, -0.686035f,
-0.472168f, -0.674316f, 0.499023f, -0.652832f, 0.525879f, -0.631348f, 0.540283f, -0.60083f,
-0.554688f, -0.570312f, 0.554688f, -0.532715f, 0.554688f, -0.5f, 0.544189f, -0.470947f,
-0.533691f, -0.441895f, 0.513916f, -0.419678f, 0.494141f, -0.397461f, 0.465332f, -0.382568f,
-0.436523f, -0.367676f, 0.400391f, -0.362793f, 0.399902f, -0.36084f, 0.424805f, -0.353516f,
-0.445557f, -0.340332f, 0.466309f, -0.327148f, 0.480957f, -0.30835f, 0.495605f, -0.289551f,
-0.503906f, -0.265137f, 0.512207f, -0.240723f, 0.512207f, -0.210938f, 0.512207f, -0.163574f,
-0.495117f, -0.123291f, 0.478027f, -0.0830078f, 0.444092f, -0.0534668f, 0.410156f,
--0.0239258f, 0.359375f, -0.00708008f, 0.308594f, 0.00976562f, 0.240723f, 0.00976562f,
-0.182617f, 0.00976562f, 0.139648f, -0.00415039f, 0.0966797f, -0.0180664f, 0.0686035f,
--0.0429688f, 0.0405273f, -0.0678711f, 0.0268555f, -0.101807f, 0.0131836f, -0.135742f,
-0.0131836f, -0.175781f, 0.0131836f, -0.221191f, 0.029541f, -0.253174f, 0.0458984f,
--0.285156f, 0.0715332f, -0.306885f, 0.097168f, -0.328613f, 0.128174f, -0.341309f,
-0.15918f, -0.354004f, 0.188477f, -0.359863f, 0.188477f, -0.361816f, 0.143555f, -0.381836f,
-0.120361f, -0.421143f, 0.097168f, -0.460449f, 0.097168f, -0.513672f, 0.097168f, -0.556152f,
-0.114014f, -0.590332f, 0.130859f, -0.624512f, 0.162842f, -0.648193f, 0.194824f, -0.671875f,
-0.240967f, -0.684814f, 0.287109f, -0.697754f, 0.345215f, -0.697754f, 0.316406f, -0.410156f,
-0.345703f, -0.410156f, 0.364746f, -0.420654f, 0.383789f, -0.431152f, 0.395264f, -0.447266f,
-0.406738f, -0.463379f, 0.411133f, -0.482666f, 0.415527f, -0.501953f, 0.415527f, -0.519531f,
-0.415527f, -0.558594f, 0.39502f, -0.580078f, 0.374512f, -0.601562f, 0.331543f, -0.601562f,
-0.310547f, -0.601562f, 0.29248f, -0.595459f, 0.274414f, -0.589355f, 0.260986f, -0.57666f,
-0.247559f, -0.563965f, 0.23999f, -0.544434f, 0.232422f, -0.524902f, 0.232422f, -0.498047f,
-0.232422f, -0.482422f, 0.236328f, -0.466553f, 0.240234f, -0.450684f, 0.249756f, -0.438232f,
-0.259277f, -0.425781f, 0.275391f, -0.417969f, 0.291504f, -0.410156f, 0.316406f, -0.410156f,
-0.273926f, -0.3125f, 0.244629f, -0.3125f, 0.222412f, -0.303223f, 0.200195f, -0.293945f,
-0.185303f, -0.2771f, 0.17041f, -0.260254f, 0.162598f, -0.236572f, 0.154785f, -0.212891f,
-0.154785f, -0.184082f, 0.154785f, -0.163086f, 0.160645f, -0.145264f, 0.166504f, -0.127441f,
-0.178711f, -0.114502f, 0.190918f, -0.101562f, 0.209717f, -0.0942383f, 0.228516f,
--0.0869141f, 0.253906f, -0.0869141f, 0.27832f, -0.0869141f, 0.299561f, -0.0952148f,
-0.320801f, -0.103516f, 0.33667f, -0.119873f, 0.352539f, -0.13623f, 0.361816f, -0.1604f,
-0.371094f, -0.18457f, 0.371094f, -0.216797f, 0.371094f, -0.234863f, 0.366455f, -0.251953f,
-0.361816f, -0.269043f, 0.350342f, -0.282471f, 0.338867f, -0.295898f, 0.320312f, -0.304199f,
-0.301758f, -0.3125f, 0.273926f, -0.3125f, 0.398926f, -0.318848f, 0.383789f, -0.300781f,
-0.367432f, -0.287109f, 0.351074f, -0.273438f, 0.33252f, -0.26416f, 0.313965f, -0.254883f,
-0.292236f, -0.250244f, 0.270508f, -0.245605f, 0.244141f, -0.245605f, 0.204102f, -0.245605f,
-0.172119f, -0.259521f, 0.140137f, -0.273438f, 0.11792f, -0.298584f, 0.0957031f, -0.32373f,
-0.0837402f, -0.358887f, 0.0717773f, -0.394043f, 0.0717773f, -0.436035f, 0.0717773f,
--0.491211f, 0.0915527f, -0.539062f, 0.111328f, -0.586914f, 0.146484f, -0.622314f,
-0.181641f, -0.657715f, 0.230469f, -0.677979f, 0.279297f, -0.698242f, 0.337891f, -0.698242f,
-0.384277f, -0.698242f, 0.42334f, -0.683105f, 0.462402f, -0.667969f, 0.490967f, -0.638428f,
-0.519531f, -0.608887f, 0.535645f, -0.565918f, 0.551758f, -0.522949f, 0.551758f, -0.467285f,
-0.551758f, -0.454102f, 0.550781f, -0.4375f, 0.549805f, -0.420898f, 0.548096f, -0.403076f,
-0.546387f, -0.385254f, 0.543701f, -0.366699f, 0.541016f, -0.348145f, 0.537598f, -0.331543f,
-0.519043f, -0.239746f, 0.487793f, -0.174805f, 0.456543f, -0.109863f, 0.416748f, -0.0688477f,
-0.376953f, -0.027832f, 0.330322f, -0.0090332f, 0.283691f, 0.00976562f, 0.233887f,
-0.00976562f, 0.192383f, 0.00976562f, 0.156738f, 0, 0.121094f, -0.00976562f, 0.09375f,
--0.0300293f, 0.0664062f, -0.050293f, 0.0483398f, -0.0805664f, 0.0302734f, -0.11084f,
-0.0234375f, -0.151855f, 0.157227f, -0.175293f, 0.164062f, -0.138672f, 0.18457f, -0.118652f,
-0.205078f, -0.0986328f, 0.243164f, -0.0986328f, 0.264648f, -0.0986328f, 0.286865f,
--0.108154f, 0.309082f, -0.117676f, 0.329834f, -0.142334f, 0.350586f, -0.166992f,
-0.368408f, -0.209717f, 0.38623f, -0.252441f, 0.398926f, -0.318848f, 0.41748f, -0.492676f,
-0.41748f, -0.513184f, 0.411377f, -0.531006f, 0.405273f, -0.548828f, 0.393799f, -0.562256f,
-0.382324f, -0.575684f, 0.366455f, -0.583252f, 0.350586f, -0.59082f, 0.331055f, -0.59082f,
-0.304688f, -0.59082f, 0.282715f, -0.581055f, 0.260742f, -0.571289f, 0.244873f, -0.552002f,
-0.229004f, -0.532715f, 0.219971f, -0.504395f, 0.210938f, -0.476074f, 0.210938f, -0.439453f,
-0.210938f, -0.41748f, 0.217529f, -0.400146f, 0.224121f, -0.382812f, 0.235596f, -0.37085f,
-0.24707f, -0.358887f, 0.263184f, -0.352783f, 0.279297f, -0.34668f, 0.29834f, -0.34668f,
-0.316895f, -0.34668f, 0.335205f, -0.351807f, 0.353516f, -0.356934f, 0.369141f, -0.369141f,
-0.384766f, -0.381348f, 0.396484f, -0.400879f, 0.408203f, -0.42041f, 0.413574f, -0.449219f,
-0.415527f, -0.460938f, 0.416504f, -0.47168f, 0.41748f, -0.482422f, 0.41748f, -0.492676f,
-0.114746f, -0.367188f, 0.141602f, -0.504883f, 0.282227f, -0.504883f, 0.255371f, -0.367188f,
-0.043457f, 0, 0.0703125f, -0.137207f, 0.210938f, -0.137207f, 0.184082f, 0, 0.507324f,
-0, 0.480469f, -0.175781f, 0.218262f, -0.175781f, 0.123047f, 0, -0.0205078f, 0, 0.36377f,
--0.687988f, 0.533691f, -0.687988f, 0.649902f, 0, 0.436523f, -0.504883f, 0.435547f,
--0.512207f, 0.434082f, -0.523193f, 0.432617f, -0.53418f, 0.431152f, -0.545654f, 0.429688f,
--0.557129f, 0.428711f, -0.567139f, 0.427734f, -0.577148f, 0.427734f, -0.582031f,
-0.425781f, -0.576172f, 0.420654f, -0.564209f, 0.415527f, -0.552246f, 0.408936f, -0.537598f,
-0.402344f, -0.522949f, 0.394531f, -0.507324f, 0.386719f, -0.491699f, 0.379883f, -0.478516f,
-0.276367f, -0.28418f, 0.469238f, -0.28418f, 0.151367f, -0.687988f, 0.436523f, -0.687988f,
-0.500488f, -0.687988f, 0.547119f, -0.677246f, 0.59375f, -0.666504f, 0.624512f, -0.645996f,
-0.655273f, -0.625488f, 0.670166f, -0.595947f, 0.685059f, -0.566406f, 0.685059f, -0.528809f,
-0.685059f, -0.493164f, 0.673828f, -0.465088f, 0.662598f, -0.437012f, 0.641846f, -0.41626f,
-0.621094f, -0.395508f, 0.591797f, -0.381592f, 0.5625f, -0.367676f, 0.526855f, -0.360352f,
-0.561523f, -0.354492f, 0.587891f, -0.34082f, 0.614258f, -0.327148f, 0.63208f, -0.307373f,
-0.649902f, -0.287598f, 0.658936f, -0.262939f, 0.667969f, -0.238281f, 0.667969f, -0.210449f,
-0.667969f, -0.149414f, 0.643311f, -0.108887f, 0.618652f, -0.0683594f, 0.576904f,
--0.0441895f, 0.535156f, -0.0200195f, 0.479492f, -0.0100098f, 0.423828f, 0, 0.361816f,
-0, 0.0175781f, 0, 0.241211f, -0.410645f, 0.384766f, -0.410645f, 0.427246f, -0.410645f,
-0.457275f, -0.416016f, 0.487305f, -0.421387f, 0.506104f, -0.433105f, 0.524902f, -0.444824f,
-0.533447f, -0.463135f, 0.541992f, -0.481445f, 0.541992f, -0.506836f, 0.541992f, -0.52832f,
-0.533936f, -0.542725f, 0.525879f, -0.557129f, 0.510498f, -0.565674f, 0.495117f, -0.574219f,
-0.472412f, -0.577637f, 0.449707f, -0.581055f, 0.420898f, -0.581055f, 0.273926f, -0.581055f,
-0.182129f, -0.106934f, 0.342285f, -0.106934f, 0.388672f, -0.106934f, 0.422852f, -0.111816f,
-0.457031f, -0.116699f, 0.479248f, -0.128906f, 0.501465f, -0.141113f, 0.512451f, -0.161621f,
-0.523438f, -0.182129f, 0.523438f, -0.213379f, 0.523438f, -0.257324f, 0.490234f, -0.280762f,
-0.457031f, -0.304199f, 0.381836f, -0.304199f, 0.220703f, -0.304199f, 0.195801f, -0.279785f,
-0.195801f, -0.23877f, 0.206055f, -0.206055f, 0.216309f, -0.17334f, 0.236572f, -0.150391f,
-0.256836f, -0.127441f, 0.286865f, -0.115234f, 0.316895f, -0.103027f, 0.356934f, -0.103027f,
-0.39502f, -0.103027f, 0.42627f, -0.113281f, 0.45752f, -0.123535f, 0.482666f, -0.141113f,
-0.507812f, -0.158691f, 0.5271f, -0.181396f, 0.546387f, -0.204102f, 0.561035f, -0.229004f,
-0.671875f, -0.171875f, 0.650879f, -0.134766f, 0.621582f, -0.101562f, 0.592285f, -0.0683594f,
-0.552734f, -0.0437012f, 0.513184f, -0.019043f, 0.462402f, -0.00463867f, 0.411621f,
-0.00976562f, 0.347168f, 0.00976562f, 0.270508f, 0.00976562f, 0.214111f, -0.0126953f,
-0.157715f, -0.0351562f, 0.121094f, -0.0739746f, 0.0844727f, -0.112793f, 0.0666504f,
--0.165283f, 0.0488281f, -0.217773f, 0.0488281f, -0.277832f, 0.0488281f, -0.338379f,
-0.0615234f, -0.393066f, 0.0742188f, -0.447754f, 0.0983887f, -0.494385f, 0.122559f,
--0.541016f, 0.157715f, -0.578857f, 0.192871f, -0.616699f, 0.237793f, -0.643066f,
-0.282715f, -0.669434f, 0.33667f, -0.683838f, 0.390625f, -0.698242f, 0.452637f, -0.698242f,
-0.519531f, -0.698242f, 0.568115f, -0.682617f, 0.616699f, -0.666992f, 0.650391f, -0.640625f,
-0.684082f, -0.614258f, 0.704102f, -0.57959f, 0.724121f, -0.544922f, 0.733887f, -0.506836f,
-0.600098f, -0.472168f, 0.594238f, -0.493652f, 0.582275f, -0.513916f, 0.570312f, -0.53418f,
-0.551758f, -0.550049f, 0.533203f, -0.565918f, 0.507324f, -0.575439f, 0.481445f, -0.584961f,
-0.448242f, -0.584961f, 0.386719f, -0.584961f, 0.3396f, -0.562744f, 0.29248f, -0.540527f,
-0.260498f, -0.500244f, 0.228516f, -0.459961f, 0.212158f, -0.403809f, 0.195801f, -0.347656f,
-0.195801f, -0.279785f, 0.358398f, -0.687988f, 0.437988f, -0.687988f, 0.500244f, -0.669434f,
-0.5625f, -0.650879f, 0.605469f, -0.614014f, 0.648438f, -0.577148f, 0.671143f, -0.522217f,
-0.693848f, -0.467285f, 0.693848f, -0.394043f, 0.693848f, -0.329102f, 0.678955f, -0.274658f,
-0.664062f, -0.220215f, 0.637451f, -0.176514f, 0.61084f, -0.132812f, 0.573975f, -0.0998535f,
-0.537109f, -0.0668945f, 0.493408f, -0.0446777f, 0.449707f, -0.0224609f, 0.400391f,
--0.0112305f, 0.351074f, 0, 0.299805f, 0, 0.0175781f, 0, 0.151367f, -0.687988f, 0.183105f,
--0.111328f, 0.29541f, -0.111328f, 0.352051f, -0.111328f, 0.400391f, -0.129395f, 0.44873f,
--0.147461f, 0.483887f, -0.182373f, 0.519043f, -0.217285f, 0.539062f, -0.268799f,
-0.559082f, -0.320312f, 0.559082f, -0.387695f, 0.559082f, -0.435547f, 0.54541f, -0.470947f,
-0.531738f, -0.506348f, 0.506104f, -0.529785f, 0.480469f, -0.553223f, 0.443359f, -0.564941f,
-0.40625f, -0.57666f, 0.359375f, -0.57666f, 0.273438f, -0.57666f, 0.0175781f, 0, 0.150879f,
--0.687988f, 0.691895f, -0.687988f, 0.67041f, -0.57666f, 0.273438f, -0.57666f, 0.239746f,
--0.403809f, 0.606934f, -0.403809f, 0.585449f, -0.29248f, 0.218262f, -0.29248f, 0.183105f,
--0.111328f, 0.600098f, -0.111328f, 0.578125f, 0, 0.273438f, -0.57666f, 0.231934f,
--0.36377f, 0.558105f, -0.36377f, 0.536621f, -0.252441f, 0.210449f, -0.252441f, 0.161133f,
-0, 0.0175781f, 0, 0.150879f, -0.687988f, 0.632324f, -0.687988f, 0.61084f, -0.57666f,
-0.683594f, -0.0854492f, 0.650879f, -0.0629883f, 0.616455f, -0.045166f, 0.582031f,
--0.0273438f, 0.542969f, -0.0153809f, 0.503906f, -0.00341797f, 0.459229f, 0.00292969f,
-0.414551f, 0.00927734f, 0.361328f, 0.00927734f, 0.282227f, 0.00927734f, 0.223389f,
--0.0129395f, 0.164551f, -0.0351562f, 0.125732f, -0.0742188f, 0.0869141f, -0.113281f,
-0.0678711f, -0.167236f, 0.0488281f, -0.221191f, 0.0488281f, -0.284668f, 0.0488281f,
--0.376465f, 0.0776367f, -0.452637f, 0.106445f, -0.528809f, 0.159912f, -0.583496f,
-0.213379f, -0.638184f, 0.289551f, -0.668213f, 0.365723f, -0.698242f, 0.459961f, -0.698242f,
-0.523926f, -0.698242f, 0.572754f, -0.682617f, 0.621582f, -0.666992f, 0.656738f, -0.640625f,
-0.691895f, -0.614258f, 0.714111f, -0.579834f, 0.736328f, -0.54541f, 0.74707f, -0.507324f,
-0.609375f, -0.469238f, 0.603516f, -0.491699f, 0.591553f, -0.512695f, 0.57959f, -0.533691f,
-0.560547f, -0.549805f, 0.541504f, -0.565918f, 0.514648f, -0.575439f, 0.487793f, -0.584961f,
-0.452148f, -0.584961f, 0.390137f, -0.584961f, 0.342041f, -0.5625f, 0.293945f, -0.540039f,
-0.26123f, -0.500488f, 0.228516f, -0.460938f, 0.21167f, -0.406738f, 0.194824f, -0.352539f,
-0.194824f, -0.289062f, 0.194824f, -0.251465f, 0.204834f, -0.217773f, 0.214844f, -0.184082f,
-0.236328f, -0.158447f, 0.257812f, -0.132812f, 0.291748f, -0.11792f, 0.325684f, -0.103027f,
-0.373047f, -0.103027f, 0.40332f, -0.103027f, 0.430664f, -0.106934f, 0.458008f, -0.11084f,
-0.481934f, -0.117432f, 0.505859f, -0.124023f, 0.525635f, -0.132324f, 0.54541f, -0.140625f,
-0.560547f, -0.149902f, 0.583008f, -0.26123f, 0.416016f, -0.26123f, 0.435059f, -0.362793f,
-0.734863f, -0.362793f, 0.466797f, 0, 0.524414f, -0.294922f, 0.21875f, -0.294922f,
-0.161133f, 0, 0.0175781f, 0, 0.150879f, -0.687988f, 0.294922f, -0.687988f, 0.241699f,
--0.414062f, 0.547363f, -0.414062f, 0.600586f, -0.687988f, 0.739258f, -0.687988f,
-0.605469f, 0, 0.0175781f, 0, 0.150879f, -0.687988f, 0.294922f, -0.687988f, 0.161133f,
-0, 0.48584f, 0, 0.3125f, -0.3125f, 0.209473f, -0.252441f, 0.160156f, 0, 0.0175781f,
-0, 0.150879f, -0.687988f, 0.294922f, -0.687988f, 0.231445f, -0.375977f, 0.602539f,
--0.687988f, 0.782715f, -0.687988f, 0.417969f, -0.387207f, 0.64502f, 0, 0.0175781f,
-0, 0.150879f, -0.687988f, 0.294922f, -0.687988f, 0.183105f, -0.111328f, 0.552246f,
--0.111328f, 0.530273f, 0, 0.588867f, 0, 0.672852f, -0.431641f, 0.678223f, -0.458496f,
-0.68457f, -0.486084f, 0.690918f, -0.513672f, 0.696289f, -0.536621f, 0.702637f, -0.563477f,
-0.708984f, -0.588867f, 0.691406f, -0.550781f, 0.675293f, -0.515137f, 0.668457f, -0.5f,
-0.660889f, -0.483887f, 0.65332f, -0.467773f, 0.645996f, -0.452393f, 0.638672f, -0.437012f,
-0.63208f, -0.423096f, 0.625488f, -0.40918f, 0.619629f, -0.398438f, 0.418457f, 0,
-0.315918f, 0, 0.27002f, -0.399902f, 0.269043f, -0.40918f, 0.267578f, -0.422119f,
-0.266113f, -0.435059f, 0.264404f, -0.450195f, 0.262695f, -0.465332f, 0.260986f, -0.481445f,
-0.259277f, -0.497559f, 0.257812f, -0.512695f, 0.254395f, -0.548828f, 0.250488f, -0.588867f,
-0.24707f, -0.559082f, 0.243652f, -0.530273f, 0.242188f, -0.518066f, 0.240479f, -0.504883f,
-0.23877f, -0.491699f, 0.237061f, -0.479004f, 0.235352f, -0.466309f, 0.233398f, -0.45459f,
-0.231445f, -0.442871f, 0.229492f, -0.433105f, 0.145508f, 0, 0.0175781f, 0, 0.151367f,
--0.687988f, 0.344238f, -0.687988f, 0.387207f, -0.303223f, 0.38916f, -0.288086f, 0.391113f,
--0.265381f, 0.393066f, -0.242676f, 0.39502f, -0.220703f, 0.396973f, -0.195312f, 0.399414f,
--0.168457f, 0.411621f, -0.195312f, 0.42334f, -0.220215f, 0.433105f, -0.241699f, 0.444092f,
--0.263916f, 0.455078f, -0.286133f, 0.462402f, -0.300781f, 0.658691f, -0.687988f,
-0.850586f, -0.687988f, 0.716797f, 0, 0.431641f, 0, 0.249023f, -0.552246f, 0.246094f,
--0.53125f, 0.243164f, -0.510742f, 0.240723f, -0.493164f, 0.237305f, -0.4729f, 0.233887f,
--0.452637f, 0.230469f, -0.435547f, 0.145508f, 0, 0.0175781f, 0, 0.151367f, -0.687988f,
-0.322266f, -0.687988f, 0.506348f, -0.130859f, 0.509277f, -0.149902f, 0.512207f, -0.170898f,
-0.514648f, -0.188965f, 0.518311f, -0.211182f, 0.521973f, -0.233398f, 0.526367f, -0.255859f,
-0.611328f, -0.687988f, 0.739258f, -0.687988f, 0.605469f, 0, 0.453125f, -0.698242f,
-0.525391f, -0.698242f, 0.58252f, -0.678467f, 0.639648f, -0.658691f, 0.679443f, -0.621826f,
-0.719238f, -0.584961f, 0.740234f, -0.532715f, 0.76123f, -0.480469f, 0.76123f, -0.415527f,
-0.76123f, -0.391602f, 0.758789f, -0.365967f, 0.756348f, -0.340332f, 0.751465f, -0.316895f,
-0.736328f, -0.241699f, 0.701904f, -0.181396f, 0.66748f, -0.121094f, 0.616699f, -0.0786133f,
-0.565918f, -0.0361328f, 0.499756f, -0.0131836f, 0.433594f, 0.00976562f, 0.35498f,
-0.00976562f, 0.280273f, 0.00976562f, 0.223145f, -0.0114746f, 0.166016f, -0.0327148f,
-0.127197f, -0.0710449f, 0.0883789f, -0.109375f, 0.0686035f, -0.162598f, 0.0488281f,
--0.21582f, 0.0488281f, -0.279785f, 0.0488281f, -0.302246f, 0.0510254f, -0.325684f,
-0.0532227f, -0.349121f, 0.0581055f, -0.373047f, 0.0732422f, -0.446289f, 0.106934f,
--0.506348f, 0.140625f, -0.566406f, 0.190918f, -0.609131f, 0.241211f, -0.651855f,
-0.307373f, -0.675049f, 0.373535f, -0.698242f, 0.453125f, -0.698242f, 0.446289f, -0.584473f,
-0.394043f, -0.584473f, 0.353027f, -0.568848f, 0.312012f, -0.553223f, 0.281982f, -0.523926f,
-0.251953f, -0.494629f, 0.231934f, -0.451904f, 0.211914f, -0.40918f, 0.20166f, -0.35498f,
-0.198242f, -0.336914f, 0.196777f, -0.318604f, 0.195312f, -0.300293f, 0.195312f, -0.283691f,
-0.195312f, -0.193848f, 0.239258f, -0.148682f, 0.283203f, -0.103516f, 0.361816f, -0.103516f,
-0.414551f, -0.103516f, 0.455566f, -0.119385f, 0.496582f, -0.135254f, 0.526855f, -0.165039f,
-0.557129f, -0.194824f, 0.576904f, -0.237061f, 0.59668f, -0.279297f, 0.606934f, -0.332031f,
-0.610352f, -0.349609f, 0.611572f, -0.369629f, 0.612793f, -0.389648f, 0.612793f, -0.403809f,
-0.612793f, -0.449219f, 0.601074f, -0.48291f, 0.589355f, -0.516602f, 0.567871f, -0.539307f,
-0.546387f, -0.562012f, 0.515381f, -0.573242f, 0.484375f, -0.584473f, 0.446289f, -0.584473f,
-0.415039f, -0.687988f, 0.475586f, -0.687988f, 0.522705f, -0.673828f, 0.569824f, -0.659668f,
-0.602295f, -0.632812f, 0.634766f, -0.605957f, 0.651611f, -0.567871f, 0.668457f, -0.529785f,
-0.668457f, -0.481934f, 0.668457f, -0.42627f, 0.648682f, -0.381836f, 0.628906f, -0.337402f,
-0.592773f, -0.306396f, 0.556641f, -0.275391f, 0.505859f, -0.258789f, 0.455078f, -0.242188f,
-0.393066f, -0.242188f, 0.208984f, -0.242188f, 0.161133f, 0, 0.0175781f, 0, 0.150879f,
--0.687988f, 0.22998f, -0.353027f, 0.371094f, -0.353027f, 0.446777f, -0.353027f, 0.484619f,
--0.381348f, 0.522461f, -0.409668f, 0.522461f, -0.474121f, 0.522461f, -0.500977f,
-0.513672f, -0.520264f, 0.504883f, -0.539551f, 0.48877f, -0.552002f, 0.472656f, -0.564453f,
-0.450439f, -0.570312f, 0.428223f, -0.576172f, 0.401367f, -0.576172f, 0.273438f, -0.576172f,
-0.453125f, -0.698242f, 0.525391f, -0.698242f, 0.58252f, -0.678467f, 0.639648f, -0.658691f,
-0.679443f, -0.621826f, 0.719238f, -0.584961f, 0.740234f, -0.532715f, 0.76123f, -0.480469f,
-0.76123f, -0.415527f, 0.76123f, -0.391602f, 0.758789f, -0.365967f, 0.756348f, -0.340332f,
-0.751465f, -0.316895f, 0.738281f, -0.250977f, 0.710205f, -0.196533f, 0.682129f, -0.14209f,
-0.641113f, -0.10083f, 0.600098f, -0.0595703f, 0.547119f, -0.032959f, 0.494141f, -0.00634766f,
-0.430664f, 0.00390625f, 0.439941f, 0.0517578f, 0.462158f, 0.0732422f, 0.484375f,
-0.0947266f, 0.527832f, 0.0947266f, 0.536133f, 0.0947266f, 0.545898f, 0.0942383f,
-0.555664f, 0.09375f, 0.56543f, 0.0927734f, 0.575195f, 0.0917969f, 0.584473f, 0.0905762f,
-0.59375f, 0.0893555f, 0.601074f, 0.0878906f, 0.579102f, 0.183105f, 0.564941f, 0.187988f,
-0.542725f, 0.19165f, 0.520508f, 0.195312f, 0.496582f, 0.195312f, 0.442383f, 0.195312f,
-0.404297f, 0.181641f, 0.366211f, 0.167969f, 0.341309f, 0.142822f, 0.316406f, 0.117676f,
-0.303223f, 0.0825195f, 0.290039f, 0.0473633f, 0.285156f, 0.00439453f, 0.227539f,
--0.00488281f, 0.18335f, -0.029541f, 0.13916f, -0.0541992f, 0.109131f, -0.0910645f,
-0.0791016f, -0.12793f, 0.0639648f, -0.175781f, 0.0488281f, -0.223633f, 0.0488281f,
--0.279785f, 0.0488281f, -0.302246f, 0.0510254f, -0.325684f, 0.0532227f, -0.349121f,
-0.0581055f, -0.373047f, 0.0732422f, -0.446289f, 0.106934f, -0.506348f, 0.140625f,
--0.566406f, 0.190918f, -0.609131f, 0.241211f, -0.651855f, 0.307373f, -0.675049f,
-0.373535f, -0.698242f, 0.453125f, -0.698242f, 0.446289f, -0.584473f, 0.394043f, -0.584473f,
-0.353027f, -0.568848f, 0.312012f, -0.553223f, 0.281982f, -0.523926f, 0.251953f, -0.494629f,
-0.231934f, -0.451904f, 0.211914f, -0.40918f, 0.20166f, -0.35498f, 0.198242f, -0.336914f,
-0.196777f, -0.318604f, 0.195312f, -0.300293f, 0.195312f, -0.283691f, 0.195312f, -0.193848f,
-0.239258f, -0.148682f, 0.283203f, -0.103516f, 0.361816f, -0.103516f, 0.414551f, -0.103516f,
-0.455566f, -0.119385f, 0.496582f, -0.135254f, 0.526855f, -0.165039f, 0.557129f, -0.194824f,
-0.576904f, -0.237061f, 0.59668f, -0.279297f, 0.606934f, -0.332031f, 0.610352f, -0.349609f,
-0.611572f, -0.369629f, 0.612793f, -0.389648f, 0.612793f, -0.403809f, 0.612793f, -0.449219f,
-0.601074f, -0.48291f, 0.589355f, -0.516602f, 0.567871f, -0.539307f, 0.546387f, -0.562012f,
-0.515381f, -0.573242f, 0.484375f, -0.584473f, 0.446289f, -0.584473f, 0.493164f, 0,
-0.380859f, -0.260742f, 0.211914f, -0.260742f, 0.161621f, 0, 0.0175781f, 0, 0.151367f,
--0.687988f, 0.469238f, -0.687988f, 0.535156f, -0.687988f, 0.582031f, -0.671875f,
-0.628906f, -0.655762f, 0.658447f, -0.628662f, 0.687988f, -0.601562f, 0.70166f, -0.565918f,
-0.715332f, -0.530273f, 0.715332f, -0.491211f, 0.715332f, -0.445312f, 0.698975f, -0.409424f,
-0.682617f, -0.373535f, 0.655518f, -0.347656f, 0.628418f, -0.321777f, 0.592773f, -0.306152f,
-0.557129f, -0.290527f, 0.518555f, -0.284668f, 0.652344f, 0, 0.425781f, -0.373047f,
-0.458496f, -0.373047f, 0.484863f, -0.379395f, 0.51123f, -0.385742f, 0.530029f, -0.399414f,
-0.548828f, -0.413086f, 0.559082f, -0.433838f, 0.569336f, -0.45459f, 0.569336f, -0.48291f,
-0.569336f, -0.508301f, 0.560059f, -0.526123f, 0.550781f, -0.543945f, 0.534668f, -0.554932f,
-0.518555f, -0.565918f, 0.49707f, -0.571045f, 0.475586f, -0.576172f, 0.451172f, -0.576172f,
-0.273438f, -0.576172f, 0.233887f, -0.373047f, 0.292969f, 0.00976562f, 0.227051f,
-0.00976562f, 0.177246f, -0.00195312f, 0.127441f, -0.0136719f, 0.0930176f, -0.0373535f,
-0.0585938f, -0.0610352f, 0.0388184f, -0.0961914f, 0.019043f, -0.131348f, 0.012207f,
--0.178223f, 0.15332f, -0.202148f, 0.158203f, -0.175781f, 0.168945f, -0.15625f, 0.179688f,
--0.136719f, 0.197754f, -0.123779f, 0.21582f, -0.11084f, 0.241699f, -0.104492f, 0.267578f,
--0.0981445f, 0.302734f, -0.0981445f, 0.339844f, -0.0981445f, 0.37085f, -0.103027f,
-0.401855f, -0.10791f, 0.424072f, -0.119385f, 0.446289f, -0.130859f, 0.45874f, -0.149414f,
-0.471191f, -0.167969f, 0.471191f, -0.195312f, 0.471191f, -0.218262f, 0.461914f, -0.234375f,
-0.452637f, -0.250488f, 0.434326f, -0.262207f, 0.416016f, -0.273926f, 0.388916f, -0.283203f,
-0.361816f, -0.29248f, 0.325684f, -0.301758f, 0.279785f, -0.313965f, 0.239502f, -0.329102f,
-0.199219f, -0.344238f, 0.169189f, -0.367432f, 0.13916f, -0.390625f, 0.121582f, -0.424072f,
-0.104004f, -0.45752f, 0.104004f, -0.506348f, 0.104004f, -0.552734f, 0.125977f, -0.588623f,
-0.147949f, -0.624512f, 0.185791f, -0.648926f, 0.223633f, -0.67334f, 0.274658f, -0.685791f,
-0.325684f, -0.698242f, 0.383789f, -0.698242f, 0.446777f, -0.698242f, 0.494385f, -0.686279f,
-0.541992f, -0.674316f, 0.575684f, -0.652588f, 0.609375f, -0.630859f, 0.629395f, -0.600342f,
-0.649414f, -0.569824f, 0.656738f, -0.532715f, 0.516113f, -0.5f, 0.505371f, -0.543945f,
-0.469482f, -0.570068f, 0.433594f, -0.596191f, 0.375977f, -0.596191f, 0.34375f, -0.596191f,
-0.31958f, -0.589844f, 0.29541f, -0.583496f, 0.279053f, -0.572266f, 0.262695f, -0.561035f,
-0.254395f, -0.54541f, 0.246094f, -0.529785f, 0.246094f, -0.51123f, 0.246094f, -0.489258f,
-0.25708f, -0.474365f, 0.268066f, -0.459473f, 0.287354f, -0.44873f, 0.306641f, -0.437988f,
-0.333496f, -0.429688f, 0.360352f, -0.421387f, 0.392578f, -0.412598f, 0.41748f, -0.405762f,
-0.443604f, -0.397705f, 0.469727f, -0.389648f, 0.494141f, -0.378662f, 0.518555f, -0.367676f,
-0.540039f, -0.352783f, 0.561523f, -0.337891f, 0.577637f, -0.317139f, 0.59375f, -0.296387f,
-0.603027f, -0.269287f, 0.612305f, -0.242188f, 0.612305f, -0.206543f, 0.612305f, -0.155273f,
-0.592773f, -0.115234f, 0.573242f, -0.0751953f, 0.533691f, -0.0473633f, 0.494141f,
--0.0195312f, 0.434082f, -0.00488281f, 0.374023f, 0.00976562f, 0.292969f, 0.00976562f,
-0.437012f, -0.57666f, 0.324707f, 0, 0.180664f, 0, 0.292969f, -0.57666f, 0.0708008f,
--0.57666f, 0.0922852f, -0.687988f, 0.681152f, -0.687988f, 0.659668f, -0.57666f, 0.335938f,
--0.103027f, 0.374512f, -0.103027f, 0.404297f, -0.111328f, 0.434082f, -0.119629f,
-0.456299f, -0.138672f, 0.478516f, -0.157715f, 0.493164f, -0.188477f, 0.507812f, -0.219238f,
-0.516602f, -0.26416f, 0.598633f, -0.687988f, 0.742676f, -0.687988f, 0.65918f, -0.258789f,
-0.645508f, -0.189453f, 0.618652f, -0.138916f, 0.591797f, -0.0883789f, 0.551025f,
--0.0554199f, 0.510254f, -0.0224609f, 0.454834f, -0.00634766f, 0.399414f, 0.00976562f,
-0.328125f, 0.00976562f, 0.265137f, 0.00976562f, 0.214844f, -0.00463867f, 0.164551f,
--0.019043f, 0.129883f, -0.046875f, 0.0952148f, -0.074707f, 0.0766602f, -0.115967f,
-0.0581055f, -0.157227f, 0.0581055f, -0.210449f, 0.0581055f, -0.220703f, 0.059082f,
--0.234131f, 0.0600586f, -0.247559f, 0.0617676f, -0.26123f, 0.0634766f, -0.274902f,
-0.0654297f, -0.287842f, 0.0673828f, -0.300781f, 0.0693359f, -0.310059f, 0.141602f,
--0.687988f, 0.285645f, -0.687988f, 0.210938f, -0.29248f, 0.20752f, -0.275879f, 0.204834f,
--0.252686f, 0.202148f, -0.229492f, 0.202148f, -0.208496f, 0.202148f, -0.182129f,
-0.211914f, -0.162354f, 0.22168f, -0.142578f, 0.239502f, -0.129395f, 0.257324f, -0.116211f,
-0.281982f, -0.109619f, 0.306641f, -0.103027f, 0.335938f, -0.103027f, 0.703613f, 0,
-0.532715f, 0, 0.519531f, -0.396484f, 0.519531f, -0.401855f, 0.519043f, -0.419189f,
-0.518555f, -0.436523f, 0.518066f, -0.458496f, 0.517578f, -0.480469f, 0.517334f, -0.503906f,
-0.51709f, -0.527344f, 0.51709f, -0.544922f, 0.506348f, -0.516113f, 0.496094f, -0.48877f,
-0.491699f, -0.477051f, 0.486816f, -0.4646f, 0.481934f, -0.452148f, 0.477295f, -0.440186f,
-0.472656f, -0.428223f, 0.468262f, -0.41748f, 0.463867f, -0.406738f, 0.459961f, -0.397949f,
-0.290039f, 0, 0.116699f, 0, 0.0732422f, -0.687988f, 0.209961f, -0.687988f, 0.227539f,
--0.290039f, 0.228516f, -0.266602f, 0.229248f, -0.237549f, 0.22998f, -0.208496f, 0.230469f,
--0.182129f, 0.230957f, -0.151855f, 0.230957f, -0.121094f, 0.245117f, -0.157227f,
-0.258789f, -0.191406f, 0.264648f, -0.206055f, 0.270996f, -0.22168f, 0.277344f, -0.237305f,
-0.283691f, -0.252441f, 0.290039f, -0.267578f, 0.295654f, -0.281494f, 0.30127f, -0.29541f,
-0.306152f, -0.306641f, 0.469238f, -0.687988f, 0.623535f, -0.687988f, 0.63916f, -0.250977f,
-0.640137f, -0.230469f, 0.640869f, -0.208008f, 0.641602f, -0.185547f, 0.642578f, -0.166016f,
-0.643555f, -0.143066f, 0.644043f, -0.121094f, 0.654297f, -0.148926f, 0.665527f, -0.178223f,
-0.675293f, -0.203125f, 0.687012f, -0.23291f, 0.69873f, -0.262695f, 0.709961f, -0.290527f,
-0.873047f, -0.687988f, 1.01514f, -0.687988f, 0.107422f, -0.687988f, 0.258301f, -0.687988f,
-0.367676f, -0.458008f, 0.563965f, -0.687988f, 0.716797f, -0.687988f, 0.423828f, -0.357422f,
-0.603027f, 0, 0.453125f, 0, 0.32959f, -0.259766f, 0.107422f, 0, -0.0458984f, 0, 0.272461f,
--0.359375f, 0.408203f, -0.282227f, 0.353516f, 0, 0.209961f, 0, 0.264648f, -0.282227f,
-0.0839844f, -0.687988f, 0.226562f, -0.687988f, 0.353027f, -0.392578f, 0.584473f,
--0.687988f, 0.742188f, -0.687988f, 0.52832f, 0, -0.0234375f, 0, -0.00390625f, -0.102051f,
-0.44873f, -0.575195f, 0.125f, -0.575195f, 0.146973f, -0.687988f, 0.64209f, -0.687988f,
-0.622559f, -0.587891f, 0.168457f, -0.112793f, 0.550293f, -0.112793f, -0.0263672f,
-0.20752f, 0.154297f, -0.724609f, 0.418945f, -0.724609f, 0.400879f, -0.631836f, 0.266113f,
--0.631836f, 0.121094f, 0.114258f, 0.255859f, 0.114258f, 0.237793f, 0.20752f, 0.141113f,
-0.0200195f, 0.0541992f, -0.725098f, 0.17041f, -0.725098f, 0.259766f, 0.0200195f,
--0.0849609f, 0.20752f, -0.0668945f, 0.114258f, 0.0683594f, 0.114258f, 0.213379f,
--0.631836f, 0.0776367f, -0.631836f, 0.0957031f, -0.724609f, 0.360352f, -0.724609f,
-0.179199f, 0.20752f, -0.0585938f, 0.12207f, -0.0585938f, 0.0839844f, 0.516113f, 0.0839844f,
-0.516113f, 0.12207f, 0.52002f, -0.00585938f, 0.499512f, 0.00195312f, 0.478516f, 0.00341797f,
-0.45752f, 0.00488281f, 0.435547f, 0.00488281f, 0.386719f, 0.00488281f, 0.360352f,
--0.015625f, 0.333984f, -0.0361328f, 0.333984f, -0.0698242f, 0.333984f, -0.0771484f,
-0.334473f, -0.0852051f, 0.334961f, -0.0932617f, 0.336426f, -0.101074f, 0.333496f,
--0.101074f, 0.316895f, -0.0751953f, 0.299805f, -0.0546875f, 0.282715f, -0.0341797f,
-0.261963f, -0.0197754f, 0.241211f, -0.00537109f, 0.215332f, 0.00219727f, 0.189453f,
-0.00976562f, 0.154785f, 0.00976562f, 0.116699f, 0.00976562f, 0.088623f, -0.00244141f,
-0.0605469f, -0.0146484f, 0.0419922f, -0.0349121f, 0.0234375f, -0.0551758f, 0.0141602f,
--0.081543f, 0.00488281f, -0.10791f, 0.00488281f, -0.135742f, 0.00488281f, -0.175293f,
-0.0158691f, -0.204102f, 0.0268555f, -0.23291f, 0.0458984f, -0.253418f, 0.0649414f,
--0.273926f, 0.0905762f, -0.286865f, 0.116211f, -0.299805f, 0.145508f, -0.307129f,
-0.174805f, -0.314453f, 0.206543f, -0.317383f, 0.238281f, -0.320312f, 0.269043f, -0.320801f,
-0.362305f, -0.322266f, 0.366211f, -0.339844f, 0.369629f, -0.354492f, 0.371094f, -0.365479f,
-0.372559f, -0.376465f, 0.372559f, -0.38623f, 0.372559f, -0.418457f, 0.355957f, -0.433594f,
-0.339355f, -0.44873f, 0.310547f, -0.44873f, 0.296387f, -0.44873f, 0.28125f, -0.446777f,
-0.266113f, -0.444824f, 0.252686f, -0.437744f, 0.239258f, -0.430664f, 0.228271f, -0.416748f,
-0.217285f, -0.402832f, 0.211426f, -0.379395f, 0.0830078f, -0.394531f, 0.0908203f,
--0.427246f, 0.108398f, -0.453613f, 0.125977f, -0.47998f, 0.154297f, -0.498779f, 0.182617f,
--0.517578f, 0.221924f, -0.527832f, 0.26123f, -0.538086f, 0.312988f, -0.538086f, 0.414062f,
--0.538086f, 0.461182f, -0.502441f, 0.508301f, -0.466797f, 0.508301f, -0.394043f,
-0.508301f, -0.378906f, 0.504395f, -0.35791f, 0.500488f, -0.336914f, 0.496582f, -0.317383f,
-0.461914f, -0.14502f, 0.460449f, -0.136719f, 0.459229f, -0.127197f, 0.458008f, -0.117676f,
-0.458008f, -0.109863f, 0.458008f, -0.0981445f, 0.462891f, -0.0917969f, 0.467773f,
--0.0854492f, 0.474121f, -0.0825195f, 0.480469f, -0.0795898f, 0.486816f, -0.0788574f,
-0.493164f, -0.078125f, 0.496582f, -0.078125f, 0.503418f, -0.078125f, 0.509521f, -0.0786133f,
-0.515625f, -0.0791016f, 0.526855f, -0.081543f, 0.347168f, -0.245605f, 0.268066f,
--0.245605f, 0.210938f, -0.244629f, 0.177979f, -0.222168f, 0.14502f, -0.199707f, 0.14502f,
--0.158691f, 0.14502f, -0.139648f, 0.150879f, -0.125732f, 0.156738f, -0.111816f, 0.166504f,
--0.103027f, 0.17627f, -0.0942383f, 0.189209f, -0.0900879f, 0.202148f, -0.0859375f,
-0.216309f, -0.0859375f, 0.230469f, -0.0859375f, 0.247803f, -0.0915527f, 0.265137f,
--0.097168f, 0.281982f, -0.110352f, 0.298828f, -0.123535f, 0.313477f, -0.145752f,
-0.328125f, -0.167969f, 0.336426f, -0.200684f, 0.41748f, -0.538086f, 0.457031f, -0.538086f,
-0.487793f, -0.525879f, 0.518555f, -0.513672f, 0.539307f, -0.491211f, 0.560059f, -0.46875f,
-0.571045f, -0.436768f, 0.582031f, -0.404785f, 0.582031f, -0.365234f, 0.582031f, -0.358398f,
-0.582031f, -0.334961f, 0.57959f, -0.307617f, 0.577148f, -0.280273f, 0.571777f, -0.251953f,
-0.558105f, -0.182617f, 0.536621f, -0.133057f, 0.515137f, -0.0834961f, 0.484619f,
--0.0517578f, 0.454102f, -0.0200195f, 0.414795f, -0.00512695f, 0.375488f, 0.00976562f,
-0.32666f, 0.00976562f, 0.265625f, 0.00976562f, 0.227539f, -0.015625f, 0.189453f,
--0.0410156f, 0.173828f, -0.0869141f, 0.172852f, -0.0869141f, 0.169922f, -0.0742188f,
-0.16626f, -0.0598145f, 0.162598f, -0.0454102f, 0.158936f, -0.0327148f, 0.155273f,
--0.0200195f, 0.152832f, -0.0109863f, 0.150391f, -0.00195312f, 0.149414f, 0, 0.0170898f,
-0, 0.0185547f, -0.00439453f, 0.0209961f, -0.0148926f, 0.0234375f, -0.0253906f, 0.0266113f,
--0.0400391f, 0.0297852f, -0.0546875f, 0.0336914f, -0.0722656f, 0.0375977f, -0.0898438f,
-0.0410156f, -0.108887f, 0.161133f, -0.724609f, 0.29834f, -0.724609f, 0.257324f, -0.516113f,
-0.250977f, -0.483887f, 0.246582f, -0.464844f, 0.242188f, -0.445801f, 0.241699f, -0.445801f,
-0.243652f, -0.445801f, 0.270996f, -0.486816f, 0.314697f, -0.512451f, 0.358398f, -0.538086f,
-0.41748f, -0.538086f, 0.358887f, -0.442871f, 0.333496f, -0.442871f, 0.310059f, -0.434814f,
-0.286621f, -0.426758f, 0.26709f, -0.407227f, 0.247559f, -0.387695f, 0.232178f, -0.354492f,
-0.216797f, -0.321289f, 0.207031f, -0.270508f, 0.203125f, -0.249023f, 0.200928f, -0.230469f,
-0.19873f, -0.211914f, 0.19873f, -0.195801f, 0.19873f, -0.168457f, 0.205811f, -0.147705f,
-0.212891f, -0.126953f, 0.22583f, -0.112793f, 0.23877f, -0.0986328f, 0.256836f, -0.0915527f,
-0.274902f, -0.0844727f, 0.296875f, -0.0844727f, 0.321777f, -0.0844727f, 0.341553f,
--0.092041f, 0.361328f, -0.0996094f, 0.377197f, -0.118408f, 0.393066f, -0.137207f,
-0.405518f, -0.169678f, 0.417969f, -0.202148f, 0.428223f, -0.251953f, 0.433594f, -0.276855f,
-0.436279f, -0.298584f, 0.438965f, -0.320312f, 0.438965f, -0.338867f, 0.438965f, -0.390137f,
-0.421631f, -0.416504f, 0.404297f, -0.442871f, 0.358887f, -0.442871f, 0.261719f, -0.0844727f,
-0.302246f, -0.0844727f, 0.328613f, -0.110107f, 0.35498f, -0.135742f, 0.370605f, -0.186035f,
-0.50293f, -0.161621f, 0.491211f, -0.123047f, 0.470947f, -0.0913086f, 0.450684f, -0.0595703f,
-0.420654f, -0.0371094f, 0.390625f, -0.0146484f, 0.349365f, -0.00244141f, 0.308105f,
-0.00976562f, 0.253906f, 0.00976562f, 0.197266f, 0.00976562f, 0.155273f, -0.00537109f,
-0.113281f, -0.0205078f, 0.0856934f, -0.0480957f, 0.0581055f, -0.0756836f, 0.0444336f,
--0.11377f, 0.0307617f, -0.151855f, 0.0307617f, -0.197754f, 0.0307617f, -0.217285f,
-0.0324707f, -0.240234f, 0.0341797f, -0.263184f, 0.0395508f, -0.285156f, 0.0517578f,
--0.339355f, 0.0705566f, -0.37915f, 0.0893555f, -0.418945f, 0.112549f, -0.447021f,
-0.135742f, -0.475098f, 0.162598f, -0.49292f, 0.189453f, -0.510742f, 0.217773f, -0.520752f,
-0.246094f, -0.530762f, 0.275146f, -0.534424f, 0.304199f, -0.538086f, 0.332031f, -0.538086f,
-0.384277f, -0.538086f, 0.422363f, -0.523926f, 0.460449f, -0.509766f, 0.486084f, -0.485596f,
-0.511719f, -0.461426f, 0.525146f, -0.429443f, 0.538574f, -0.397461f, 0.541504f, -0.361816f,
-0.402832f, -0.350586f, 0.400391f, -0.394531f, 0.380615f, -0.419189f, 0.36084f, -0.443848f,
-0.321289f, -0.443848f, 0.293945f, -0.443848f, 0.273682f, -0.434814f, 0.253418f, -0.425781f,
-0.237793f, -0.406006f, 0.222168f, -0.38623f, 0.209717f, -0.355225f, 0.197266f, -0.324219f,
-0.186035f, -0.280762f, 0.184082f, -0.270996f, 0.182129f, -0.26001f, 0.180176f, -0.249023f,
-0.178467f, -0.238037f, 0.176758f, -0.227051f, 0.175781f, -0.217041f, 0.174805f, -0.207031f,
-0.174805f, -0.19873f, 0.174805f, -0.139648f, 0.196777f, -0.112061f, 0.21875f, -0.0844727f,
-0.261719f, -0.0844727f, 0.365723f, -0.078125f, 0.348145f, -0.0551758f, 0.32959f,
--0.0385742f, 0.311035f, -0.0219727f, 0.290283f, -0.0109863f, 0.269531f, 0, 0.245117f,
-0.00512695f, 0.220703f, 0.0102539f, 0.191406f, 0.0102539f, 0.152344f, 0.0102539f,
-0.121826f, -0.00341797f, 0.0913086f, -0.0170898f, 0.0705566f, -0.0415039f, 0.0498047f,
--0.065918f, 0.0390625f, -0.0996094f, 0.0283203f, -0.133301f, 0.0283203f, -0.172852f,
-0.0283203f, -0.194824f, 0.0305176f, -0.220215f, 0.0327148f, -0.245605f, 0.0385742f,
--0.276367f, 0.0522461f, -0.345703f, 0.0759277f, -0.395264f, 0.0996094f, -0.444824f,
-0.131104f, -0.476562f, 0.162598f, -0.508301f, 0.201172f, -0.523193f, 0.239746f, -0.538086f,
-0.283203f, -0.538086f, 0.318848f, -0.538086f, 0.344971f, -0.530518f, 0.371094f, -0.522949f,
-0.389404f, -0.509766f, 0.407715f, -0.496582f, 0.419189f, -0.479004f, 0.430664f, -0.461426f,
-0.436523f, -0.441406f, 0.438965f, -0.441406f, 0.439941f, -0.451172f, 0.442871f, -0.470703f,
-0.445801f, -0.490234f, 0.45166f, -0.520508f, 0.492676f, -0.724609f, 0.62793f, -0.724609f,
-0.511719f, -0.112793f, 0.506348f, -0.0830078f, 0.50293f, -0.0546875f, 0.499512f,
--0.0263672f, 0.497559f, 0, 0.360352f, 0, 0.360352f, -0.00390625f, 0.360596f, -0.0117188f,
-0.36084f, -0.0195312f, 0.361816f, -0.0302734f, 0.362793f, -0.0410156f, 0.364258f,
--0.0532227f, 0.365723f, -0.0654297f, 0.367676f, -0.078125f, 0.251465f, -0.0839844f,
-0.277344f, -0.0839844f, 0.300537f, -0.092041f, 0.32373f, -0.100098f, 0.343262f, -0.119873f,
-0.362793f, -0.139648f, 0.37793f, -0.173096f, 0.393066f, -0.206543f, 0.402832f, -0.257324f,
-0.406738f, -0.278809f, 0.408936f, -0.297607f, 0.411133f, -0.316406f, 0.411133f, -0.33252f,
-0.411133f, -0.391113f, 0.388184f, -0.417725f, 0.365234f, -0.444336f, 0.319336f, -0.444336f,
-0.296387f, -0.444336f, 0.275391f, -0.436523f, 0.254395f, -0.428711f, 0.236816f, -0.409424f,
-0.219238f, -0.390137f, 0.205078f, -0.357666f, 0.190918f, -0.325195f, 0.182129f, -0.275879f,
-0.177734f, -0.250977f, 0.175537f, -0.230713f, 0.17334f, -0.210449f, 0.17334f, -0.191895f,
-0.17334f, -0.140137f, 0.191895f, -0.112061f, 0.210449f, -0.0839844f, 0.251465f, -0.0839844f,
-0.174805f, -0.232422f, 0.172852f, -0.22168f, 0.172119f, -0.210938f, 0.171387f, -0.200195f,
-0.171387f, -0.188965f, 0.171387f, -0.137207f, 0.194092f, -0.109619f, 0.216797f, -0.0820312f,
-0.26123f, -0.0820312f, 0.281738f, -0.0820312f, 0.297852f, -0.0883789f, 0.313965f,
--0.0947266f, 0.32666f, -0.105713f, 0.339355f, -0.116699f, 0.348877f, -0.131836f,
-0.358398f, -0.146973f, 0.365234f, -0.164551f, 0.484863f, -0.128418f, 0.470215f, -0.097168f,
-0.45166f, -0.0715332f, 0.433105f, -0.0458984f, 0.40625f, -0.027832f, 0.379395f, -0.00976562f,
-0.341797f, 0, 0.304199f, 0.00976562f, 0.251953f, 0.00976562f, 0.198242f, 0.00976562f,
-0.156982f, -0.00537109f, 0.115723f, -0.0205078f, 0.0876465f, -0.0483398f, 0.0595703f,
--0.0761719f, 0.045166f, -0.115723f, 0.0307617f, -0.155273f, 0.0307617f, -0.204102f,
-0.0307617f, -0.28418f, 0.052002f, -0.346191f, 0.0732422f, -0.408203f, 0.111084f,
--0.450928f, 0.148926f, -0.493652f, 0.201172f, -0.515869f, 0.253418f, -0.538086f,
-0.31543f, -0.538086f, 0.370117f, -0.538086f, 0.410156f, -0.523438f, 0.450195f, -0.508789f,
-0.476562f, -0.482178f, 0.50293f, -0.455566f, 0.515625f, -0.418701f, 0.52832f, -0.381836f,
-0.52832f, -0.337402f, 0.52832f, -0.31543f, 0.525146f, -0.286865f, 0.521973f, -0.258301f,
-0.516602f, -0.232422f, 0.401367f, -0.32373f, 0.402344f, -0.331543f, 0.402588f, -0.337891f,
-0.402832f, -0.344238f, 0.402832f, -0.351074f, 0.402832f, -0.40332f, 0.378662f, -0.427246f,
-0.354492f, -0.451172f, 0.31543f, -0.451172f, 0.298828f, -0.451172f, 0.280273f, -0.445801f,
-0.261719f, -0.44043f, 0.244385f, -0.426025f, 0.227051f, -0.411621f, 0.213135f, -0.386963f,
-0.199219f, -0.362305f, 0.190918f, -0.32373f, 0.257812f, -0.435547f, 0.172852f, 0,
-0.0361328f, 0, 0.121094f, -0.435547f, 0.0439453f, -0.435547f, 0.0620117f, -0.52832f,
-0.13916f, -0.52832f, 0.149902f, -0.583496f, 0.15625f, -0.616699f, 0.169189f, -0.643066f,
-0.182129f, -0.669434f, 0.204834f, -0.6875f, 0.227539f, -0.705566f, 0.260742f, -0.715088f,
-0.293945f, -0.724609f, 0.34082f, -0.724609f, 0.362793f, -0.724609f, 0.382568f, -0.721924f,
-0.402344f, -0.719238f, 0.416504f, -0.716309f, 0.398926f, -0.62793f, 0.394531f, -0.628906f,
-0.388428f, -0.629639f, 0.382324f, -0.630371f, 0.375732f, -0.631104f, 0.369141f, -0.631836f,
-0.362793f, -0.632324f, 0.356445f, -0.632812f, 0.352051f, -0.632812f, 0.319336f, -0.632812f,
-0.304688f, -0.617188f, 0.290039f, -0.601562f, 0.283691f, -0.569824f, 0.275879f, -0.52832f,
-0.379883f, -0.52832f, 0.361816f, -0.435547f, 0.210449f, 0.20752f, 0.15918f, 0.20752f,
-0.121582f, 0.198486f, 0.0839844f, 0.189453f, 0.0581055f, 0.171875f, 0.0322266f, 0.154297f,
-0.017334f, 0.128662f, 0.00244141f, 0.103027f, -0.00341797f, 0.0693359f, 0.134766f,
-0.0546875f, 0.141602f, 0.0869141f, 0.164551f, 0.101807f, 0.1875f, 0.116699f, 0.226562f,
-0.116699f, 0.254883f, 0.116699f, 0.275879f, 0.109131f, 0.296875f, 0.101562f, 0.312256f,
-0.0856934f, 0.327637f, 0.0698242f, 0.338135f, 0.045166f, 0.348633f, 0.0205078f, 0.356445f,
--0.0131836f, 0.359375f, -0.0273438f, 0.362061f, -0.0422363f, 0.364746f, -0.0571289f,
-0.367188f, -0.0698242f, 0.369629f, -0.0844727f, 0.371582f, -0.0981445f, 0.370605f,
--0.0981445f, 0.356934f, -0.0786133f, 0.341553f, -0.0600586f, 0.326172f, -0.0415039f,
-0.305908f, -0.0273438f, 0.285645f, -0.0131836f, 0.259277f, -0.00463867f, 0.23291f,
-0.00390625f, 0.197754f, 0.00390625f, 0.15918f, 0.00390625f, 0.128174f, -0.00927734f,
-0.097168f, -0.0224609f, 0.0759277f, -0.0458984f, 0.0546875f, -0.0693359f, 0.0432129f,
--0.102051f, 0.0317383f, -0.134766f, 0.0317383f, -0.173828f, 0.0317383f, -0.197754f,
-0.0339355f, -0.225098f, 0.0361328f, -0.252441f, 0.0419922f, -0.283203f, 0.0668945f,
--0.410645f, 0.125732f, -0.474121f, 0.18457f, -0.537598f, 0.286133f, -0.537598f, 0.313965f,
--0.537598f, 0.339111f, -0.530762f, 0.364258f, -0.523926f, 0.384277f, -0.510986f,
-0.404297f, -0.498047f, 0.418701f, -0.479248f, 0.433105f, -0.460449f, 0.439941f, -0.436035f,
-0.440918f, -0.436035f, 0.443359f, -0.44873f, 0.447021f, -0.463867f, 0.450684f, -0.479004f,
-0.454102f, -0.49292f, 0.45752f, -0.506836f, 0.460449f, -0.516846f, 0.463379f, -0.526855f,
-0.464355f, -0.52832f, 0.59375f, -0.52832f, 0.592773f, -0.523926f, 0.590332f, -0.513184f,
-0.587891f, -0.502441f, 0.584473f, -0.487549f, 0.581055f, -0.472656f, 0.577393f, -0.454346f,
-0.57373f, -0.436035f, 0.569824f, -0.416504f, 0.489258f, -0.00488281f, 0.478516f,
-0.0478516f, 0.458496f, 0.0876465f, 0.438477f, 0.127441f, 0.405518f, 0.154053f, 0.372559f,
-0.180664f, 0.324707f, 0.194092f, 0.276855f, 0.20752f, 0.210449f, 0.20752f, 0.406738f,
--0.267578f, 0.410156f, -0.284668f, 0.411621f, -0.303223f, 0.413086f, -0.321777f,
-0.413086f, -0.334961f, 0.413086f, -0.362793f, 0.405762f, -0.383057f, 0.398438f, -0.40332f,
-0.385498f, -0.416992f, 0.372559f, -0.430664f, 0.354736f, -0.437256f, 0.336914f, -0.443848f,
-0.316406f, -0.443848f, 0.291504f, -0.443848f, 0.27124f, -0.436279f, 0.250977f, -0.428711f,
-0.235107f, -0.4104f, 0.219238f, -0.39209f, 0.207031f, -0.361084f, 0.194824f, -0.330078f,
-0.186035f, -0.283691f, 0.181641f, -0.259277f, 0.178467f, -0.235352f, 0.175293f, -0.211426f,
-0.175293f, -0.193359f, 0.175293f, -0.143066f, 0.197021f, -0.119629f, 0.21875f, -0.0961914f,
-0.259766f, -0.0961914f, 0.28125f, -0.0961914f, 0.303711f, -0.105713f, 0.326172f,
--0.115234f, 0.346191f, -0.135986f, 0.366211f, -0.156738f, 0.38208f, -0.189209f, 0.397949f,
--0.22168f, 0.406738f, -0.267578f, 0.293457f, -0.724609f, 0.254883f, -0.526855f, 0.25293f,
--0.516602f, 0.250488f, -0.504639f, 0.248047f, -0.492676f, 0.245361f, -0.480957f,
-0.242676f, -0.469238f, 0.240234f, -0.458008f, 0.237793f, -0.446777f, 0.23584f, -0.437988f,
-0.237305f, -0.437988f, 0.251953f, -0.458496f, 0.269775f, -0.476562f, 0.287598f, -0.494629f,
-0.30957f, -0.508301f, 0.331543f, -0.521973f, 0.358643f, -0.529785f, 0.385742f, -0.537598f,
-0.419434f, -0.537598f, 0.493652f, -0.537598f, 0.53125f, -0.501953f, 0.568848f, -0.466309f,
-0.568848f, -0.398926f, 0.568848f, -0.390137f, 0.567627f, -0.378906f, 0.566406f, -0.367676f,
-0.564941f, -0.356689f, 0.563477f, -0.345703f, 0.561768f, -0.335693f, 0.560059f, -0.325684f,
-0.558594f, -0.318848f, 0.496582f, 0, 0.360352f, 0, 0.417969f, -0.290527f, 0.419922f,
--0.299805f, 0.422119f, -0.311035f, 0.424316f, -0.322266f, 0.42627f, -0.333496f, 0.428223f,
--0.344727f, 0.429443f, -0.354736f, 0.430664f, -0.364746f, 0.430664f, -0.371094f,
-0.430664f, -0.401855f, 0.411865f, -0.417969f, 0.393066f, -0.434082f, 0.356445f, -0.434082f,
-0.333496f, -0.434082f, 0.310547f, -0.424316f, 0.287598f, -0.414551f, 0.267822f, -0.396484f,
-0.248047f, -0.378418f, 0.233154f, -0.352783f, 0.218262f, -0.327148f, 0.212402f, -0.295898f,
-0.154785f, 0, 0.0170898f, 0, 0.156738f, -0.724609f, 0.137695f, -0.623535f, 0.157715f,
--0.724609f, 0.294922f, -0.724609f, 0.274902f, -0.623535f, 0.0170898f, 0, 0.119629f,
--0.52832f, 0.256836f, -0.52832f, 0.153809f, 0, 0.138184f, -0.623535f, 0.157715f,
--0.724609f, 0.294922f, -0.724609f, 0.275391f, -0.623535f, -0.0263672f, 0.20752f,
--0.0507812f, 0.20752f, -0.0717773f, 0.204834f, -0.0927734f, 0.202148f, -0.107422f,
-0.198242f, -0.0898438f, 0.106445f, -0.0834961f, 0.107422f, -0.0754395f, 0.10791f,
--0.0673828f, 0.108398f, -0.0615234f, 0.108398f, -0.0449219f, 0.108398f, -0.0332031f,
-0.104492f, -0.0214844f, 0.100586f, -0.0131836f, 0.0913086f, -0.00488281f, 0.0820312f,
-0.000732422f, 0.0668945f, 0.00634766f, 0.0517578f, 0.0107422f, 0.0292969f, 0.119629f,
--0.52832f, 0.256836f, -0.52832f, 0.141602f, 0.0625f, 0.135254f, 0.0942383f, 0.122314f,
-0.120605f, 0.109375f, 0.146973f, 0.0888672f, 0.166504f, 0.0683594f, 0.186035f, 0.0397949f,
-0.196777f, 0.0112305f, 0.20752f, -0.0263672f, 0.20752f, 0.355469f, 0, 0.263672f,
--0.242676f, 0.195312f, -0.206055f, 0.153809f, 0, 0.0170898f, 0, 0.157715f, -0.724609f,
-0.294922f, -0.724609f, 0.213379f, -0.30957f, 0.44043f, -0.52832f, 0.597656f, -0.52832f,
-0.366699f, -0.322266f, 0.500977f, 0, 0.0170898f, 0, 0.157715f, -0.724609f, 0.294922f,
--0.724609f, 0.153809f, 0, 0.645508f, -0.435547f, 0.623535f, -0.435547f, 0.60376f,
--0.425781f, 0.583984f, -0.416016f, 0.568115f, -0.397705f, 0.552246f, -0.379395f,
-0.540771f, -0.35376f, 0.529297f, -0.328125f, 0.522949f, -0.296387f, 0.464844f, 0,
-0.328613f, 0, 0.388672f, -0.310059f, 0.390137f, -0.317871f, 0.391602f, -0.326904f,
-0.393066f, -0.335938f, 0.394287f, -0.345215f, 0.395508f, -0.354492f, 0.39624f, -0.362549f,
-0.396973f, -0.370605f, 0.396973f, -0.376465f, 0.396973f, -0.435547f, 0.335449f, -0.435547f,
-0.312988f, -0.435547f, 0.293457f, -0.425537f, 0.273926f, -0.415527f, 0.257812f, -0.397217f,
-0.241699f, -0.378906f, 0.230225f, -0.352783f, 0.21875f, -0.32666f, 0.212402f, -0.294922f,
-0.154785f, 0, 0.0170898f, 0, 0.0981445f, -0.415527f, 0.101562f, -0.432129f, 0.104736f,
--0.450439f, 0.10791f, -0.46875f, 0.110596f, -0.485107f, 0.113281f, -0.501465f, 0.11499f,
--0.513184f, 0.116699f, -0.524902f, 0.117188f, -0.52832f, 0.25f, -0.52832f, 0.25f,
--0.525879f, 0.248535f, -0.515137f, 0.24707f, -0.504395f, 0.244873f, -0.490479f, 0.242676f,
--0.476562f, 0.240479f, -0.462158f, 0.238281f, -0.447754f, 0.236328f, -0.437988f,
-0.237793f, -0.437988f, 0.25293f, -0.460938f, 0.268799f, -0.479492f, 0.284668f, -0.498047f,
-0.303467f, -0.510986f, 0.322266f, -0.523926f, 0.345459f, -0.530762f, 0.368652f, -0.537598f,
-0.397949f, -0.537598f, 0.458496f, -0.537598f, 0.493652f, -0.508545f, 0.528809f, -0.479492f,
-0.535645f, -0.424316f, 0.55127f, -0.44873f, 0.568359f, -0.469238f, 0.585449f, -0.489746f,
-0.605957f, -0.505127f, 0.626465f, -0.520508f, 0.651611f, -0.529053f, 0.676758f, -0.537598f,
-0.708496f, -0.537598f, 0.775879f, -0.537598f, 0.811768f, -0.501953f, 0.847656f, -0.466309f,
-0.847656f, -0.398926f, 0.847656f, -0.381348f, 0.844482f, -0.359375f, 0.841309f, -0.337402f,
-0.837402f, -0.318848f, 0.774902f, 0, 0.638672f, 0, 0.698242f, -0.306152f, 0.699707f,
--0.313477f, 0.701172f, -0.32251f, 0.702637f, -0.331543f, 0.704102f, -0.340576f, 0.705566f,
--0.349609f, 0.706299f, -0.358398f, 0.707031f, -0.367188f, 0.707031f, -0.374023f,
-0.707031f, -0.376465f, 0.705566f, -0.435547f, 0.645508f, -0.435547f, 0.360352f, 0,
-0.417969f, -0.290527f, 0.419922f, -0.299805f, 0.422119f, -0.311035f, 0.424316f, -0.322266f,
-0.42627f, -0.333496f, 0.428223f, -0.344727f, 0.429443f, -0.354736f, 0.430664f, -0.364746f,
-0.430664f, -0.371094f, 0.430664f, -0.401855f, 0.412109f, -0.417969f, 0.393555f, -0.434082f,
-0.356445f, -0.434082f, 0.333496f, -0.434082f, 0.310547f, -0.424316f, 0.287598f, -0.414551f,
-0.267822f, -0.396484f, 0.248047f, -0.378418f, 0.233154f, -0.352783f, 0.218262f, -0.327148f,
-0.212402f, -0.295898f, 0.154785f, 0, 0.0170898f, 0, 0.0981445f, -0.415527f, 0.101562f,
--0.432129f, 0.104736f, -0.450439f, 0.10791f, -0.46875f, 0.110352f, -0.485107f, 0.112793f,
--0.501465f, 0.114502f, -0.513184f, 0.116211f, -0.524902f, 0.116699f, -0.52832f, 0.247559f,
--0.52832f, 0.247559f, -0.525879f, 0.246338f, -0.515137f, 0.245117f, -0.504395f, 0.243408f,
--0.490479f, 0.241699f, -0.476562f, 0.239746f, -0.462158f, 0.237793f, -0.447754f,
-0.23584f, -0.437988f, 0.237305f, -0.437988f, 0.251953f, -0.458496f, 0.269775f, -0.476562f,
-0.287598f, -0.494629f, 0.30957f, -0.508301f, 0.331543f, -0.521973f, 0.358643f, -0.529785f,
-0.385742f, -0.537598f, 0.419434f, -0.537598f, 0.493652f, -0.537598f, 0.53125f, -0.501953f,
-0.568848f, -0.466309f, 0.568848f, -0.398926f, 0.568848f, -0.390137f, 0.567627f, -0.378906f,
-0.566406f, -0.367676f, 0.564941f, -0.356689f, 0.563477f, -0.345703f, 0.561768f, -0.335693f,
-0.560059f, -0.325684f, 0.558594f, -0.318848f, 0.496582f, 0, 0.578613f, -0.333496f,
-0.578613f, -0.253906f, 0.554688f, -0.190186f, 0.530762f, -0.126465f, 0.488281f, -0.0820312f,
-0.445801f, -0.0375977f, 0.387695f, -0.013916f, 0.32959f, 0.00976562f, 0.26123f, 0.00976562f,
-0.208984f, 0.00976562f, 0.166504f, -0.00463867f, 0.124023f, -0.019043f, 0.09375f,
--0.0466309f, 0.0634766f, -0.0742188f, 0.0471191f, -0.114014f, 0.0307617f, -0.153809f,
-0.0307617f, -0.20459f, 0.0307617f, -0.280273f, 0.0534668f, -0.341797f, 0.0761719f,
--0.40332f, 0.117676f, -0.446777f, 0.15918f, -0.490234f, 0.216797f, -0.513916f, 0.274414f,
--0.537598f, 0.34375f, -0.537598f, 0.401367f, -0.537598f, 0.445312f, -0.523926f, 0.489258f,
--0.510254f, 0.518799f, -0.483887f, 0.54834f, -0.45752f, 0.563477f, -0.419678f, 0.578613f,
--0.381836f, 0.578613f, -0.333496f, 0.435059f, -0.323242f, 0.435059f, -0.355469f,
-0.427979f, -0.378418f, 0.420898f, -0.401367f, 0.407715f, -0.415771f, 0.394531f, -0.430176f,
-0.375732f, -0.437012f, 0.356934f, -0.443848f, 0.333496f, -0.443848f, 0.312012f, -0.443848f,
-0.290039f, -0.438721f, 0.268066f, -0.433594f, 0.248291f, -0.41748f, 0.228516f, -0.401367f,
-0.212158f, -0.371582f, 0.195801f, -0.341797f, 0.18457f, -0.292969f, 0.179199f, -0.269531f,
-0.177002f, -0.248779f, 0.174805f, -0.228027f, 0.174805f, -0.210449f, 0.174805f, -0.175293f,
-0.182373f, -0.151367f, 0.189941f, -0.127441f, 0.203613f, -0.112305f, 0.217285f, -0.097168f,
-0.23584f, -0.0905762f, 0.254395f, -0.0839844f, 0.276367f, -0.0839844f, 0.29834f,
--0.0839844f, 0.319824f, -0.0888672f, 0.341309f, -0.09375f, 0.36084f, -0.109619f,
-0.380371f, -0.125488f, 0.396484f, -0.155029f, 0.412598f, -0.18457f, 0.423828f, -0.234375f,
-0.429199f, -0.259766f, 0.431641f, -0.281006f, 0.434082f, -0.302246f, 0.435059f, -0.323242f,
-0.355469f, -0.442871f, 0.330078f, -0.442871f, 0.306641f, -0.434814f, 0.283203f, -0.426758f,
-0.263672f, -0.407227f, 0.244141f, -0.387695f, 0.22876f, -0.354492f, 0.213379f, -0.321289f,
-0.203613f, -0.270508f, 0.199707f, -0.249023f, 0.19751f, -0.230469f, 0.195312f, -0.211914f,
-0.195312f, -0.195801f, 0.195312f, -0.168457f, 0.202393f, -0.147705f, 0.209473f, -0.126953f,
-0.222412f, -0.112793f, 0.235352f, -0.0986328f, 0.253418f, -0.0915527f, 0.271484f,
--0.0844727f, 0.293457f, -0.0844727f, 0.318359f, -0.0844727f, 0.338623f, -0.0922852f,
-0.358887f, -0.100098f, 0.375f, -0.119141f, 0.391113f, -0.138184f, 0.403564f, -0.170654f,
-0.416016f, -0.203125f, 0.424805f, -0.251953f, 0.429199f, -0.276855f, 0.431641f, -0.298584f,
-0.434082f, -0.320312f, 0.434082f, -0.338867f, 0.434082f, -0.390625f, 0.415283f, -0.416748f,
-0.396484f, -0.442871f, 0.355469f, -0.442871f, 0.240723f, -0.445801f, 0.257812f, -0.469727f,
-0.275879f, -0.487061f, 0.293945f, -0.504395f, 0.314941f, -0.515869f, 0.335938f, -0.527344f,
-0.360352f, -0.532715f, 0.384766f, -0.538086f, 0.414062f, -0.538086f, 0.453613f, -0.538086f,
-0.484375f, -0.525879f, 0.515137f, -0.513672f, 0.535889f, -0.491211f, 0.556641f, -0.46875f,
-0.567627f, -0.436768f, 0.578613f, -0.404785f, 0.578613f, -0.365234f, 0.578613f, -0.336426f,
-0.576172f, -0.30835f, 0.57373f, -0.280273f, 0.568359f, -0.251953f, 0.554688f, -0.182617f,
-0.533203f, -0.133057f, 0.511719f, -0.0834961f, 0.481201f, -0.0517578f, 0.450684f,
--0.0200195f, 0.411377f, -0.00512695f, 0.37207f, 0.00976562f, 0.323242f, 0.00976562f,
-0.262207f, 0.00976562f, 0.224121f, -0.015625f, 0.186035f, -0.0410156f, 0.17041f,
--0.0869141f, 0.169434f, -0.0869141f, 0.166992f, -0.0664062f, 0.162598f, -0.0419922f,
-0.158203f, -0.0175781f, 0.153809f, 0.00488281f, 0.114746f, 0.20752f, -0.0219727f,
-0.20752f, 0.0966797f, -0.406738f, 0.100098f, -0.423828f, 0.102295f, -0.435791f, 0.104492f,
--0.447754f, 0.106201f, -0.460205f, 0.10791f, -0.472656f, 0.110107f, -0.488281f, 0.112305f,
--0.503906f, 0.115723f, -0.52832f, 0.25f, -0.52832f, 0.25f, -0.525391f, 0.249023f,
--0.515625f, 0.248047f, -0.505859f, 0.246582f, -0.493408f, 0.245117f, -0.480957f,
-0.243164f, -0.468018f, 0.241211f, -0.455078f, 0.23877f, -0.445801f, 0.438477f, -0.440918f,
-0.440918f, -0.453125f, 0.444092f, -0.466553f, 0.447266f, -0.47998f, 0.450439f, -0.491943f,
-0.453613f, -0.503906f, 0.456543f, -0.513672f, 0.459473f, -0.523438f, 0.461426f, -0.52832f,
-0.593262f, -0.52832f, 0.59082f, -0.52002f, 0.583252f, -0.485352f, 0.575684f, -0.450684f,
-0.563477f, -0.388184f, 0.448242f, 0.20752f, 0.311035f, 0.20752f, 0.352539f, -0.00341797f,
-0.355957f, -0.0195312f, 0.360352f, -0.0385742f, 0.364746f, -0.0576172f, 0.370117f,
--0.0795898f, 0.368164f, -0.0795898f, 0.350586f, -0.0566406f, 0.332031f, -0.0397949f,
-0.313477f, -0.0229492f, 0.292236f, -0.0117188f, 0.270996f, -0.000488281f, 0.246338f,
-0.00488281f, 0.22168f, 0.0102539f, 0.192383f, 0.0102539f, 0.152832f, 0.0102539f,
-0.122559f, -0.00317383f, 0.0922852f, -0.0166016f, 0.0712891f, -0.0402832f, 0.050293f,
--0.0639648f, 0.0395508f, -0.097168f, 0.0288086f, -0.130371f, 0.0288086f, -0.169922f,
-0.0288086f, -0.191895f, 0.0310059f, -0.218506f, 0.0332031f, -0.245117f, 0.0390625f,
--0.275879f, 0.0527344f, -0.345703f, 0.0766602f, -0.395508f, 0.100586f, -0.445312f,
-0.132324f, -0.477051f, 0.164062f, -0.508789f, 0.202393f, -0.523438f, 0.240723f, -0.538086f,
-0.283203f, -0.538086f, 0.31543f, -0.538086f, 0.3396f, -0.532715f, 0.36377f, -0.527344f,
-0.381836f, -0.515625f, 0.399902f, -0.503906f, 0.413086f, -0.485352f, 0.42627f, -0.466797f,
-0.436035f, -0.440918f, 0.25293f, -0.0839844f, 0.278809f, -0.0839844f, 0.302002f,
--0.092041f, 0.325195f, -0.100098f, 0.344727f, -0.119873f, 0.364258f, -0.139648f,
-0.379395f, -0.173096f, 0.394531f, -0.206543f, 0.403809f, -0.257324f, 0.407715f, -0.278809f,
-0.409668f, -0.297363f, 0.411621f, -0.315918f, 0.411621f, -0.332031f, 0.411621f, -0.386719f,
-0.391357f, -0.415527f, 0.371094f, -0.444336f, 0.32666f, -0.444336f, 0.300781f, -0.444336f,
-0.278564f, -0.436768f, 0.256348f, -0.429199f, 0.238037f, -0.410156f, 0.219727f, -0.391113f,
-0.205811f, -0.358643f, 0.191895f, -0.326172f, 0.182617f, -0.275879f, 0.177734f, -0.250488f,
-0.175781f, -0.22876f, 0.173828f, -0.207031f, 0.173828f, -0.188477f, 0.173828f, -0.164551f,
-0.178467f, -0.145264f, 0.183105f, -0.125977f, 0.192627f, -0.112305f, 0.202148f, -0.0986328f,
-0.217041f, -0.0913086f, 0.231934f, -0.0839844f, 0.25293f, -0.0839844f, 0.412109f,
--0.416504f, 0.400879f, -0.418945f, 0.388184f, -0.421387f, 0.375488f, -0.423828f,
-0.356445f, -0.423828f, 0.296387f, -0.423828f, 0.258545f, -0.381348f, 0.220703f, -0.338867f,
-0.203613f, -0.250977f, 0.154297f, 0, 0.0170898f, 0, 0.0957031f, -0.405273f, 0.0991211f,
--0.422363f, 0.102051f, -0.439453f, 0.10498f, -0.456543f, 0.107666f, -0.472656f, 0.110352f,
--0.48877f, 0.112549f, -0.503174f, 0.114746f, -0.517578f, 0.116211f, -0.52832f, 0.24707f,
--0.52832f, 0.245605f, -0.517578f, 0.243896f, -0.50293f, 0.242188f, -0.488281f, 0.240234f,
--0.473145f, 0.238281f, -0.458008f, 0.236084f, -0.444092f, 0.233887f, -0.430176f,
-0.232422f, -0.42041f, 0.234375f, -0.42041f, 0.250977f, -0.450684f, 0.267334f, -0.4729f,
-0.283691f, -0.495117f, 0.301514f, -0.509521f, 0.319336f, -0.523926f, 0.3396f, -0.531006f,
-0.359863f, -0.538086f, 0.384277f, -0.538086f, 0.390137f, -0.538086f, 0.397217f, -0.537354f,
-0.404297f, -0.536621f, 0.411377f, -0.535645f, 0.418457f, -0.534668f, 0.424561f, -0.533447f,
-0.430664f, -0.532227f, 0.43457f, -0.53125f, 0.488281f, -0.163086f, 0.488281f, -0.119629f,
-0.471924f, -0.0871582f, 0.455566f, -0.0546875f, 0.424072f, -0.0332031f, 0.392578f,
--0.0117188f, 0.346924f, -0.000976562f, 0.30127f, 0.00976562f, 0.242676f, 0.00976562f,
-0.144531f, 0.00976562f, 0.0878906f, -0.0249023f, 0.03125f, -0.0595703f, 0.0112305f,
--0.132324f, 0.133789f, -0.149902f, 0.138672f, -0.132324f, 0.147461f, -0.119385f,
-0.15625f, -0.106445f, 0.17041f, -0.0979004f, 0.18457f, -0.0893555f, 0.204834f, -0.0852051f,
-0.225098f, -0.0810547f, 0.252441f, -0.0810547f, 0.276367f, -0.0810547f, 0.296143f,
--0.0847168f, 0.315918f, -0.0883789f, 0.330322f, -0.0964355f, 0.344727f, -0.104492f,
-0.352783f, -0.117188f, 0.36084f, -0.129883f, 0.36084f, -0.147461f, 0.36084f, -0.163086f,
-0.354248f, -0.173096f, 0.347656f, -0.183105f, 0.334229f, -0.190186f, 0.320801f, -0.197266f,
-0.300049f, -0.202881f, 0.279297f, -0.208496f, 0.251465f, -0.214355f, 0.212891f, -0.223145f,
-0.18042f, -0.235352f, 0.147949f, -0.247559f, 0.124512f, -0.266357f, 0.101074f, -0.285156f,
-0.0878906f, -0.311768f, 0.074707f, -0.338379f, 0.074707f, -0.375488f, 0.074707f,
--0.419434f, 0.0930176f, -0.449951f, 0.111328f, -0.480469f, 0.143311f, -0.499756f,
-0.175293f, -0.519043f, 0.218262f, -0.527832f, 0.26123f, -0.536621f, 0.311035f, -0.536621f,
-0.356445f, -0.536621f, 0.392822f, -0.529541f, 0.429199f, -0.522461f, 0.455566f, -0.505859f,
-0.481934f, -0.489258f, 0.498779f, -0.462402f, 0.515625f, -0.435547f, 0.521973f, -0.395996f,
-0.399414f, -0.381836f, 0.391113f, -0.415527f, 0.367188f, -0.430664f, 0.343262f, -0.445801f,
-0.301758f, -0.445801f, 0.280762f, -0.445801f, 0.262451f, -0.443115f, 0.244141f, -0.44043f,
-0.230713f, -0.433594f, 0.217285f, -0.426758f, 0.209473f, -0.415527f, 0.20166f, -0.404297f,
-0.20166f, -0.387207f, 0.20166f, -0.371582f, 0.210938f, -0.361084f, 0.220215f, -0.350586f,
-0.236816f, -0.343018f, 0.253418f, -0.335449f, 0.276367f, -0.329834f, 0.299316f, -0.324219f,
-0.326172f, -0.317871f, 0.360352f, -0.310059f, 0.389893f, -0.298828f, 0.419434f, -0.287598f,
-0.441406f, -0.269775f, 0.463379f, -0.251953f, 0.47583f, -0.226074f, 0.488281f, -0.200195f,
-0.488281f, -0.163086f, 0.273438f, -0.00390625f, 0.255371f, 0.00146484f, 0.232422f,
-0.00463867f, 0.209473f, 0.0078125f, 0.183594f, 0.0078125f, 0.154785f, 0.0078125f,
-0.131348f, 0.000976562f, 0.10791f, -0.00585938f, 0.0913086f, -0.0195312f, 0.074707f,
--0.0332031f, 0.0656738f, -0.0539551f, 0.0566406f, -0.074707f, 0.0566406f, -0.102051f,
-0.0566406f, -0.124023f, 0.0593262f, -0.144775f, 0.0620117f, -0.165527f, 0.0644531f,
--0.178711f, 0.114258f, -0.435547f, 0.0419922f, -0.435547f, 0.0600586f, -0.52832f,
-0.13916f, -0.52832f, 0.206055f, -0.652344f, 0.291992f, -0.652344f, 0.268555f, -0.52832f,
-0.367188f, -0.52832f, 0.350098f, -0.435547f, 0.25f, -0.435547f, 0.199219f, -0.174316f,
-0.197266f, -0.164551f, 0.195312f, -0.150635f, 0.193359f, -0.136719f, 0.193848f, -0.126953f,
-0.194824f, -0.106445f, 0.206299f, -0.0964355f, 0.217773f, -0.0864258f, 0.236328f,
--0.0864258f, 0.248047f, -0.0864258f, 0.26001f, -0.0881348f, 0.271973f, -0.0898438f,
-0.289062f, -0.0927734f, 0.25f, -0.52832f, 0.192383f, -0.237793f, 0.19043f, -0.228516f,
-0.188232f, -0.217285f, 0.186035f, -0.206055f, 0.184082f, -0.194824f, 0.182129f, -0.183594f,
-0.180908f, -0.173828f, 0.179688f, -0.164062f, 0.179688f, -0.157227f, 0.179688f, -0.126465f,
-0.198242f, -0.110352f, 0.216797f, -0.0942383f, 0.253906f, -0.0942383f, 0.276855f,
--0.0942383f, 0.300049f, -0.104004f, 0.323242f, -0.11377f, 0.343018f, -0.131836f,
-0.362793f, -0.149902f, 0.377441f, -0.175537f, 0.39209f, -0.201172f, 0.397949f, -0.232422f,
-0.455566f, -0.52832f, 0.593262f, -0.52832f, 0.512207f, -0.112793f, 0.508789f, -0.0961914f,
-0.505615f, -0.0778809f, 0.502441f, -0.0595703f, 0.5f, -0.0432129f, 0.497559f, -0.0268555f,
-0.49585f, -0.0151367f, 0.494141f, -0.00341797f, 0.493652f, 0, 0.362793f, 0, 0.362793f,
--0.00244141f, 0.364014f, -0.0131836f, 0.365234f, -0.0239258f, 0.366943f, -0.0378418f,
-0.368652f, -0.0517578f, 0.370605f, -0.0661621f, 0.372559f, -0.0805664f, 0.374512f,
--0.090332f, 0.373047f, -0.090332f, 0.358398f, -0.0698242f, 0.34082f, -0.0517578f,
-0.323242f, -0.0336914f, 0.30127f, -0.0200195f, 0.279297f, -0.00634766f, 0.251953f,
-0.00146484f, 0.224609f, 0.00927734f, 0.190918f, 0.00927734f, 0.116699f, 0.00927734f,
-0.0791016f, -0.0263672f, 0.0415039f, -0.0620117f, 0.0415039f, -0.129395f, 0.0415039f,
--0.138184f, 0.0427246f, -0.149414f, 0.0439453f, -0.160645f, 0.0454102f, -0.171631f,
-0.046875f, -0.182617f, 0.048584f, -0.192871f, 0.050293f, -0.203125f, 0.0517578f,
--0.209473f, 0.11377f, -0.52832f, 0.303711f, 0, 0.139648f, 0, 0.0537109f, -0.52832f,
-0.194824f, -0.52832f, 0.229492f, -0.23291f, 0.231445f, -0.218262f, 0.23291f, -0.200684f,
-0.234375f, -0.183105f, 0.23584f, -0.165527f, 0.237305f, -0.147949f, 0.238525f, -0.131348f,
-0.239746f, -0.114746f, 0.240234f, -0.101562f, 0.245605f, -0.114258f, 0.252686f, -0.130859f,
-0.259766f, -0.147461f, 0.267822f, -0.165039f, 0.275879f, -0.182617f, 0.28418f, -0.199707f,
-0.29248f, -0.216797f, 0.299805f, -0.231445f, 0.454102f, -0.52832f, 0.601562f, -0.52832f,
-0.589355f, 0, 0.444336f, 0, 0.42334f, -0.322266f, 0.422363f, -0.337402f, 0.422119f,
--0.356934f, 0.421875f, -0.376465f, 0.421387f, -0.393555f, 0.420898f, -0.413574f,
-0.420898f, -0.43457f, 0.413086f, -0.413574f, 0.404785f, -0.393555f, 0.397949f, -0.376465f,
-0.389893f, -0.356689f, 0.381836f, -0.336914f, 0.374512f, -0.321289f, 0.227051f, 0,
-0.0820312f, 0, 0.0483398f, -0.52832f, 0.174316f, -0.52832f, 0.180664f, -0.217773f,
-0.181152f, -0.20459f, 0.181152f, -0.188232f, 0.181152f, -0.171875f, 0.181152f, -0.157715f,
-0.181152f, -0.124512f, 0.1875f, -0.141113f, 0.194336f, -0.157715f, 0.200195f, -0.171875f,
-0.206787f, -0.188232f, 0.213379f, -0.20459f, 0.219727f, -0.217773f, 0.363281f, -0.52832f,
-0.510254f, -0.52832f, 0.530762f, -0.217773f, 0.531738f, -0.205078f, 0.531982f, -0.188965f,
-0.532227f, -0.172852f, 0.532715f, -0.158691f, 0.533203f, -0.14209f, 0.533203f, -0.124512f,
-0.540039f, -0.14209f, 0.546875f, -0.158691f, 0.552734f, -0.172852f, 0.559082f, -0.188965f,
-0.56543f, -0.205078f, 0.570801f, -0.217773f, 0.701172f, -0.52832f, 0.831055f, -0.52832f,
-0.353516f, 0, 0.262695f, -0.187012f, 0.103027f, 0, -0.0439453f, 0, 0.204102f, -0.274414f,
-0.0678711f, -0.52832f, 0.210449f, -0.52832f, 0.294922f, -0.358887f, 0.439453f, -0.52832f,
-0.589844f, -0.52832f, 0.354004f, -0.271973f, 0.497559f, 0, 0.27832f, 0.027832f, 0.250977f,
-0.0703125f, 0.226318f, 0.103516f, 0.20166f, 0.136719f, 0.174561f, 0.159912f, 0.147461f,
-0.183105f, 0.115723f, 0.195312f, 0.0839844f, 0.20752f, 0.0429688f, 0.20752f, 0.0175781f,
-0.20752f, -0.00268555f, 0.205322f, -0.0229492f, 0.203125f, -0.0415039f, 0.19873f,
--0.0229492f, 0.103027f, -0.0141602f, 0.10498f, -0.00219727f, 0.106201f, 0.00976562f,
-0.107422f, 0.0195312f, 0.107422f, 0.0380859f, 0.107422f, 0.0539551f, 0.102539f, 0.0698242f,
-0.0976562f, 0.0849609f, 0.0864258f, 0.100098f, 0.0751953f, 0.114746f, 0.0568848f,
-0.129395f, 0.0385742f, 0.144531f, 0.0117188f, 0.158203f, -0.0117188f, 0.0546875f,
--0.52832f, 0.196777f, -0.52832f, 0.231445f, -0.285645f, 0.232422f, -0.280273f, 0.234131f,
--0.267578f, 0.23584f, -0.254883f, 0.237549f, -0.238525f, 0.239258f, -0.222168f, 0.241211f,
--0.204102f, 0.243164f, -0.186035f, 0.244629f, -0.169678f, 0.246094f, -0.15332f, 0.247314f,
--0.140625f, 0.248535f, -0.12793f, 0.248535f, -0.122559f, 0.250977f, -0.12793f, 0.256592f,
--0.140381f, 0.262207f, -0.152832f, 0.269775f, -0.168701f, 0.277344f, -0.18457f, 0.285645f,
--0.202148f, 0.293945f, -0.219727f, 0.301514f, -0.23584f, 0.309082f, -0.251953f, 0.31543f,
--0.264893f, 0.321777f, -0.277832f, 0.324707f, -0.283691f, 0.451172f, -0.52832f, 0.597656f,
--0.52832f, -0.0170898f, 0, 0.00146484f, -0.097168f, 0.320312f, -0.429199f, 0.0859375f,
--0.429199f, 0.105469f, -0.52832f, 0.500488f, -0.52832f, 0.481445f, -0.430176f, 0.164062f,
--0.100098f, 0.440918f, -0.100098f, 0.421387f, 0
-};
-
-const unsigned char LiberationSanskBoldItalicVerbs[] = {
-6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6,
-0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 0, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1,
-1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 1,
-1, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 5, 0, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5,
-6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6,
-0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 1, 1,
-1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1,
-1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0,
-1, 1, 1, 5, 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5,
-6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
-2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6
-};
-
-const unsigned LiberationSanskBoldItalicCharCodes[] = {
-32, 33,
-44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58, 65, 66, 67, 68, 69, 70,
-71, 72, 73, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 91, 92,
-93, 95, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122
-};
-
-const SkFixed LiberationSanskBoldItalicWidths[] = {
-0x00004720, 0x00005540, 0x00004720, 0x00005540, 0x00004720, 0x00004720, 0x00008e60,
-0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60, 0x00008e60,
-0x00008e60, 0x00005540, 0x0000b8e0, 0x0000b8e0, 0x0000b8e0, 0x0000b8e0, 0x0000aac0,
-0x00009c60, 0x0000c720, 0x0000b8e0, 0x00004720, 0x0000b8e0, 0x00009c60, 0x0000d540,
-0x0000b8e0, 0x0000c720, 0x0000aac0, 0x0000c720, 0x0000b8e0, 0x0000aac0, 0x00009c60,
-0x0000b8e0, 0x0000f1a0, 0x0000aac0, 0x0000aac0, 0x00009c60, 0x00005540, 0x00004720,
-0x00005540, 0x00008e60, 0x00008e60, 0x00009c60, 0x00008e60, 0x00009c60, 0x00008e60,
-0x00005540, 0x00009c60, 0x00009c60, 0x00004720, 0x00004720, 0x00008e60, 0x00004720,
-0x0000e3a0, 0x00009c60, 0x00009c60, 0x00009c60, 0x00009c60, 0x000063a0, 0x00008e60,
-0x00005540, 0x00009c60, 0x00008e60, 0x0000c720, 0x00008e60, 0x00008e60, 0x00008000
-};
-
-const int LiberationSanskBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSanskBoldItalicCharCodes);
-
-const SkPaint::FontMetrics LiberationSanskBoldItalicMetrics = {
-0x00000003, -1.02979f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 1.3374f, 0, -0.208984f,
-1.12842f, 0.537598f, 0, 0.10498f, 0.105957f
-};
-
-const SkScalar HiraginoMaruGothicProkNormalPoints[] = {
-0.109f, -0.22f, 0.109f, -0.197f, 0.128f, -0.186f, 0.149f, -0.186f, 0.169f, -0.186f,
-0.188f, -0.197f, 0.189f, -0.22f, 0.203f, -0.732f, 0.204f, -0.76f, 0.182f, -0.778f,
-0.15f, -0.778f, 0.117f, -0.778f, 0.095f, -0.76f, 0.095f, -0.732f, 0.149f, -0.125f,
-0.11f, -0.125f, 0.08f, -0.098f, 0.08f, -0.056f, 0.08f, -0.014f, 0.11f, 0.013f, 0.149f,
-0.013f, 0.186f, 0.013f, 0.218f, -0.014f, 0.218f, -0.056f, 0.218f, -0.098f, 0.186f,
--0.125f, 0.149f, -0.125f, 0.291f, -0.684f, 0.291f, -0.028f, 0.291f, -0.001f, 0.312f,
-0.013f, 0.339f, 0.013f, 0.366f, 0.013f, 0.387f, -0.001f, 0.387f, -0.028f, 0.387f,
--0.684f, 0.614f, -0.684f, 0.637f, -0.684f, 0.652f, -0.704f, 0.652f, -0.727f, 0.652f,
--0.751f, 0.638f, -0.772f, 0.614f, -0.772f, 0.063f, -0.772f, 0.039f, -0.772f, 0.025f,
--0.751f, 0.025f, -0.727f, 0.025f, -0.704f, 0.039f, -0.684f, 0.064f, -0.684f, 0.409f,
--0.347f, 0.302f, -0.345f, 0.25f, -0.339f, 0.195f, -0.324f, 0.1f, -0.298f, 0.044f,
--0.238f, 0.044f, -0.144f, 0.044f, -0.041f, 0.111f, 0.021f, 0.221f, 0.021f, 0.32f,
-0.021f, 0.373f, -0.018f, 0.411f, -0.061f, 0.412f, -0.041f, 0.414f, -0.023f, 0.417f,
--0.011f, 0.421f, 0.007f, 0.439f, 0.013f, 0.459f, 0.013f, 0.462f, 0.013f, 0.465f,
-0.013f, 0.468f, 0.013f, 0.493f, 0.011f, 0.508f, -0.003f, 0.508f, -0.019f, 0.508f,
--0.022f, 0.507f, -0.026f, 0.506f, -0.029f, 0.5f, -0.048f, 0.495f, -0.082f, 0.495f,
--0.117f, 0.495f, -0.39f, 0.495f, -0.508f, 0.429f, -0.561f, 0.295f, -0.561f, 0.214f,
--0.561f, 0.169f, -0.544f, 0.134f, -0.517f, 0.111f, -0.499f, 0.085f, -0.47f, 0.075f,
--0.439f, 0.074f, -0.435f, 0.073f, -0.431f, 0.073f, -0.427f, 0.073f, -0.409f, 0.087f,
--0.395f, 0.106f, -0.389f, 0.113f, -0.386f, 0.121f, -0.385f, 0.129f, -0.385f, 0.146f,
--0.385f, 0.161f, -0.392f, 0.168f, -0.411f, 0.185f, -0.457f, 0.221f, -0.485f, 0.294f,
--0.485f, 0.373f, -0.485f, 0.409f, -0.456f, 0.409f, -0.39f, 0.409f, -0.208f, 0.409f,
--0.17f, 0.402f, -0.151f, 0.383f, -0.127f, 0.351f, -0.087f, 0.299f, -0.056f, 0.236f,
--0.056f, 0.176f, -0.056f, 0.136f, -0.091f, 0.136f, -0.143f, 0.136f, -0.191f, 0.157f,
--0.222f, 0.197f, -0.242f, 0.237f, -0.262f, 0.292f, -0.272f, 0.409f, -0.275f, 0.045f,
--0.268f, 0.045f, -0.096f, 0.136f, 0.023f, 0.298f, 0.023f, 0.434f, 0.023f, 0.487f,
--0.049f, 0.514f, -0.118f, 0.517f, -0.125f, 0.518f, -0.13f, 0.518f, -0.136f, 0.518f,
--0.154f, 0.504f, -0.166f, 0.486f, -0.17f, 0.479f, -0.173f, 0.472f, -0.174f, 0.465f,
--0.174f, 0.449f, -0.174f, 0.435f, -0.166f, 0.428f, -0.147f, 0.409f, -0.093f, 0.378f,
--0.055f, 0.3f, -0.055f, 0.194f, -0.055f, 0.138f, -0.138f, 0.138f, -0.269f, 0.138f,
--0.396f, 0.195f, -0.484f, 0.299f, -0.484f, 0.375f, -0.484f, 0.405f, -0.445f, 0.424f,
--0.394f, 0.431f, -0.377f, 0.444f, -0.371f, 0.459f, -0.371f, 0.466f, -0.371f, 0.474f,
--0.372f, 0.481f, -0.374f, 0.496f, -0.38f, 0.511f, -0.392f, 0.511f, -0.411f, 0.511f,
--0.415f, 0.51f, -0.421f, 0.508f, -0.426f, 0.483f, -0.489f, 0.429f, -0.562f, 0.297f,
--0.562f, 0.133f, -0.562f, 0.045f, -0.439f, 0.045f, -0.268f, 0.486f, -0.253f, 0.517f,
--0.253f, 0.536f, -0.272f, 0.536f, -0.308f, 0.536f, -0.311f, 0.536f, -0.313f, 0.536f,
--0.316f, 0.526f, -0.447f, 0.444f, -0.561f, 0.298f, -0.561f, 0.135f, -0.561f, 0.045f,
--0.44f, 0.045f, -0.267f, 0.045f, -0.094f, 0.14f, 0.022f, 0.304f, 0.022f, 0.434f,
-0.022f, 0.492f, -0.044f, 0.524f, -0.11f, 0.528f, -0.116f, 0.529f, -0.122f, 0.529f,
--0.128f, 0.529f, -0.146f, 0.515f, -0.158f, 0.498f, -0.163f, 0.491f, -0.165f, 0.484f,
--0.167f, 0.477f, -0.167f, 0.463f, -0.167f, 0.45f, -0.16f, 0.441f, -0.142f, 0.417f,
--0.089f, 0.377f, -0.053f, 0.305f, -0.053f, 0.197f, -0.053f, 0.136f, -0.13f, 0.134f,
--0.253f, 0.137f, -0.326f, 0.15f, -0.424f, 0.202f, -0.488f, 0.298f, -0.488f, 0.39f,
--0.488f, 0.433f, -0.415f, 0.445f, -0.344f, 0.445f, -0.342f, 0.445f, -0.34f, 0.445f,
--0.339f, 0.445f, -0.33f, 0.441f, -0.326f, 0.43f, -0.326f, 0.138f, -0.547f, 0.053f,
--0.547f, 0.028f, -0.547f, 0.017f, -0.529f, 0.017f, -0.506f, 0.017f, -0.483f, 0.029f,
--0.468f, 0.053f, -0.468f, 0.138f, -0.468f, 0.138f, -0.027f, 0.138f, 0, 0.156f, 0.013f,
-0.183f, 0.013f, 0.209f, 0.013f, 0.228f, 0, 0.228f, -0.027f, 0.228f, -0.468f, 0.348f,
--0.468f, 0.372f, -0.468f, 0.385f, -0.483f, 0.385f, -0.506f, 0.385f, -0.53f, 0.373f,
--0.547f, 0.348f, -0.547f, 0.228f, -0.547f, 0.228f, -0.608f, 0.228f, -0.68f, 0.256f,
--0.7f, 0.293f, -0.7f, 0.314f, -0.7f, 0.331f, -0.697f, 0.348f, -0.69f, 0.354f, -0.688f,
-0.359f, -0.687f, 0.364f, -0.687f, 0.382f, -0.687f, 0.396f, -0.7f, 0.402f, -0.717f,
-0.405f, -0.723f, 0.406f, -0.729f, 0.406f, -0.736f, 0.406f, -0.751f, 0.398f, -0.766f,
-0.379f, -0.772f, 0.351f, -0.781f, 0.326f, -0.783f, 0.293f, -0.783f, 0.217f, -0.783f,
-0.138f, -0.748f, 0.138f, -0.619f, 0.531f, -0.366f, 0.531f, -0.489f, 0.467f, -0.561f,
-0.348f, -0.561f, 0.253f, -0.561f, 0.193f, -0.516f, 0.158f, -0.445f, 0.159f, -0.464f,
-0.162f, -0.474f, 0.162f, -0.487f, 0.162f, -0.514f, 0.162f, -0.54f, 0.144f, -0.553f,
-0.118f, -0.553f, 0.09f, -0.553f, 0.071f, -0.54f, 0.071f, -0.514f, 0.071f, -0.027f,
-0.071f, 0, 0.089f, 0.013f, 0.117f, 0.013f, 0.143f, 0.013f, 0.162f, 0, 0.162f, -0.027f,
-0.162f, -0.307f, 0.162f, -0.346f, 0.172f, -0.375f, 0.197f, -0.409f, 0.231f, -0.456f,
-0.276f, -0.48f, 0.33f, -0.48f, 0.405f, -0.48f, 0.439f, -0.432f, 0.439f, -0.347f,
-0.439f, -0.027f, 0.439f, 0, 0.458f, 0.013f, 0.485f, 0.013f, 0.511f, 0.013f, 0.531f,
-0, 0.531f, -0.027f, 0.16f, -0.036f, 0.16f, -0.054f, 0.159f, -0.075f, 0.155f, -0.094f,
-0.189f, -0.024f, 0.246f, 0.022f, 0.339f, 0.022f, 0.488f, 0.022f, 0.578f, -0.096f,
-0.578f, -0.274f, 0.578f, -0.452f, 0.493f, -0.561f, 0.343f, -0.561f, 0.246f, -0.561f,
-0.191f, -0.514f, 0.156f, -0.443f, 0.159f, -0.46f, 0.16f, -0.484f, 0.16f, -0.498f,
-0.16f, -0.516f, 0.16f, -0.541f, 0.141f, -0.553f, 0.116f, -0.553f, 0.088f, -0.553f,
-0.071f, -0.54f, 0.071f, -0.514f, 0.071f, 0.184f, 0.071f, 0.209f, 0.088f, 0.223f,
-0.116f, 0.223f, 0.143f, 0.223f, 0.16f, 0.209f, 0.16f, 0.184f, 0.33f, -0.483f, 0.431f,
--0.483f, 0.486f, -0.402f, 0.486f, -0.272f, 0.486f, -0.143f, 0.429f, -0.057f, 0.328f,
--0.057f, 0.223f, -0.057f, 0.158f, -0.147f, 0.158f, -0.271f, 0.158f, -0.394f, 0.22f,
--0.483f, 0.33f, -0.483f, 0.085f, -0.027f, 0.085f, 0, 0.104f, 0.013f, 0.132f, 0.013f,
-0.157f, 0.013f, 0.177f, 0, 0.177f, -0.027f, 0.177f, -0.303f, 0.178f, -0.345f, 0.193f,
--0.382f, 0.219f, -0.414f, 0.244f, -0.446f, 0.277f, -0.468f, 0.32f, -0.469f, 0.341f,
--0.469f, 0.354f, -0.466f, 0.368f, -0.463f, 0.371f, -0.462f, 0.374f, -0.462f, 0.377f,
--0.462f, 0.398f, -0.462f, 0.412f, -0.48f, 0.416f, -0.501f, 0.417f, -0.507f, 0.418f,
--0.513f, 0.418f, -0.518f, 0.418f, -0.537f, 0.409f, -0.551f, 0.386f, -0.554f, 0.372f,
--0.557f, 0.361f, -0.559f, 0.346f, -0.559f, 0.339f, -0.559f, 0.332f, -0.559f, 0.324f,
--0.558f, 0.238f, -0.555f, 0.187f, -0.493f, 0.171f, -0.445f, 0.173f, -0.461f, 0.177f,
--0.478f, 0.177f, -0.492f, 0.177f, -0.514f, 0.177f, -0.54f, 0.157f, -0.553f, 0.132f,
--0.553f, 0.104f, -0.553f, 0.085f, -0.54f, 0.085f, -0.514f, 0.286f, -0.236f, 0.377f,
--0.218f, 0.403f, -0.191f, 0.403f, -0.142f, 0.403f, -0.091f, 0.351f, -0.056f, 0.271f,
--0.056f, 0.192f, -0.056f, 0.151f, -0.085f, 0.133f, -0.143f, 0.127f, -0.162f, 0.109f,
--0.17f, 0.09f, -0.17f, 0.086f, -0.17f, 0.081f, -0.169f, 0.076f, -0.168f, 0.057f,
--0.164f, 0.04f, -0.15f, 0.04f, -0.13f, 0.04f, -0.126f, 0.041f, -0.122f, 0.042f, -0.117f,
-0.068f, -0.028f, 0.143f, 0.023f, 0.271f, 0.023f, 0.411f, 0.023f, 0.493f, -0.048f,
-0.493f, -0.144f, 0.493f, -0.249f, 0.441f, -0.287f, 0.311f, -0.314f, 0.249f, -0.327f,
-0.165f, -0.345f, 0.146f, -0.365f, 0.146f, -0.411f, 0.146f, -0.453f, 0.184f, -0.486f,
-0.265f, -0.486f, 0.322f, -0.486f, 0.366f, -0.463f, 0.379f, -0.418f, 0.384f, -0.399f,
-0.402f, -0.391f, 0.42f, -0.391f, 0.425f, -0.391f, 0.431f, -0.392f, 0.436f, -0.393f,
-0.454f, -0.398f, 0.471f, -0.411f, 0.471f, -0.43f, 0.471f, -0.434f, 0.47f, -0.438f,
-0.469f, -0.442f, 0.444f, -0.515f, 0.373f, -0.562f, 0.262f, -0.562f, 0.133f, -0.562f,
-0.055f, -0.5f, 0.055f, -0.409f, 0.055f, -0.314f, 0.106f, -0.271f, 0.229f, -0.247f,
-0.068f, -0.174f, 0.068f, -0.052f, 0.133f, 0.022f, 0.251f, 0.022f, 0.351f, 0.022f,
-0.409f, -0.029f, 0.44f, -0.099f, 0.437f, -0.083f, 0.434f, -0.063f, 0.434f, -0.052f,
-0.434f, -0.024f, 0.434f, 0.001f, 0.453f, 0.013f, 0.48f, 0.013f, 0.506f, 0.013f, 0.524f,
-0, 0.524f, -0.027f, 0.524f, -0.513f, 0.524f, -0.54f, 0.505f, -0.553f, 0.479f, -0.553f,
-0.452f, -0.553f, 0.433f, -0.54f, 0.433f, -0.513f, 0.433f, -0.235f, 0.433f, -0.196f,
-0.423f, -0.165f, 0.399f, -0.131f, 0.365f, -0.084f, 0.322f, -0.059f, 0.269f, -0.059f,
-0.195f, -0.059f, 0.16f, -0.107f, 0.16f, -0.193f, 0.16f, -0.513f, 0.16f, -0.54f, 0.141f,
--0.553f, 0.114f, -0.553f, 0.087f, -0.553f, 0.068f, -0.54f, 0.068f, -0.513f, 0.307f,
--0.194f, 0.296f, -0.165f, 0.282f, -0.127f, 0.274f, -0.096f, 0.265f, -0.127f, 0.256f,
--0.164f, 0.244f, -0.196f, 0.118f, -0.528f, 0.111f, -0.546f, 0.096f, -0.553f, 0.08f,
--0.553f, 0.073f, -0.553f, 0.066f, -0.552f, 0.059f, -0.55f, 0.041f, -0.544f, 0.026f,
--0.529f, 0.026f, -0.511f, 0.026f, -0.506f, 0.027f, -0.5f, 0.029f, -0.495f, 0.231f,
--0.005f, 0.203f, 0.065f, 0.185f, 0.111f, 0.164f, 0.149f, 0.121f, 0.149f, 0.103f,
-0.149f, 0.085f, 0.142f, 0.071f, 0.136f, 0.064f, 0.133f, 0.058f, 0.132f, 0.052f, 0.132f,
-0.035f, 0.132f, 0.022f, 0.143f, 0.015f, 0.16f, 0.012f, 0.168f, 0.01f, 0.175f, 0.01f,
-0.183f, 0.01f, 0.198f, 0.018f, 0.212f, 0.038f, 0.219f, 0.061f, 0.228f, 0.085f, 0.232f,
-0.11f, 0.232f, 0.208f, 0.232f, 0.249f, 0.175f, 0.284f, 0.089f, 0.52f, -0.496f, 0.522f,
--0.502f, 0.523f, -0.508f, 0.523f, -0.513f, 0.523f, -0.531f, 0.509f, -0.545f, 0.49f,
--0.55f, 0.484f, -0.551f, 0.478f, -0.552f, 0.472f, -0.552f, 0.455f, -0.552f, 0.44f,
--0.545f, 0.433f, -0.526f, 0.88f, -0.329f, 0.905f, -0.329f, 0.919f, -0.345f, 0.919f,
--0.372f, 0.919f, -0.398f, 0.905f, -0.417f, 0.879f, -0.417f, 0.12f, -0.417f, 0.094f,
--0.417f, 0.08f, -0.398f, 0.08f, -0.372f, 0.08f, -0.345f, 0.094f, -0.329f, 0.119f,
--0.329f
-};
-
-const unsigned char HiraginoMaruGothicProkNormalVerbs[] = {
-6, 0, 4, 4, 1, 4, 4, 5, 0, 4, 4, 4, 4, 5, 6, 0, 1, 4, 4, 1, 1, 4, 4, 1, 4, 4, 5,
-6, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 0, 4, 4, 4,
-4, 4, 5, 6, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 0, 4, 4, 4,
-4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 0, 4, 4, 4, 4, 5, 6, 0, 1, 4, 4, 1, 1, 4, 4, 1, 1,
-4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 0, 4, 4, 4, 1, 4, 4, 1, 4, 4, 1, 4, 4,
-4, 1, 4, 4, 5, 6, 0, 4, 4, 4, 4, 4, 4, 1, 4, 4, 1, 4, 4, 5, 0, 4, 4, 4, 4, 5, 6,
-0, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 5, 6, 0, 4, 4, 4, 4, 4, 4,
-4, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 0, 4, 4, 4, 1, 4, 4, 1, 4, 4,
-1, 4, 4, 4, 1, 4, 4, 5, 6, 0, 4, 4, 1, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4,
-1, 4, 4, 4, 4, 5, 6, 0, 4, 4, 1, 4, 4, 5, 6
-};
-
-const unsigned HiraginoMaruGothicProkNormalCharCodes[] = {
-32, 33, 84, 97, 99, 101, 102, 110, 112,
-114, 115, 117, 121, 12540
-};
-
-const SkFixed HiraginoMaruGothicProkNormalWidths[] = {
-0x0000553f, 0x00004d4f, 0x0000ad0e, 0x000092b0, 0x00008dd2, 0x000092f1, 0x00006666,
-0x00009999, 0x00009fbe, 0x00006e97, 0x000088f5, 0x000098d4, 0x00008d0e, 0x00010000
-};
-
-const int HiraginoMaruGothicProkNormalCharCodesCount = (int) SK_ARRAY_COUNT(HiraginoMaruGothicProkNormalCharCodes);
-
-const SkPaint::FontMetrics HiraginoMaruGothicProkNormalMetrics = {
-0x00004f0f, -1.273f, -0.880002f, 0.12f, 0.4f, 0.500001f, 1.673f, 7.89174e-34f, -0.393f,
-1.28f, 0.576f, 5.17319e-29f, 0.077f, 0.06f
-};
-
-const SkScalar PapyruskNormalPoints[] = {
-0.172852f, -0.257812f, 0.166016f, -0.250977f, 0.155762f, -0.228027f, 0.152344f, -0.221191f,
-0.13623f, -0.210938f, 0.126953f, -0.21582f, 0.103027f, -0.213867f, 0.0952148f, -0.219238f,
-0.0859375f, -0.223145f, 0.0859375f, -0.230957f, 0.0869141f, -0.234863f, 0.105957f,
--0.26416f, 0.11084f, -0.312988f, 0.11377f, -0.332031f, 0.125f, -0.332031f, 0.128906f,
--0.338379f, 0.128906f, -0.344238f, 0.128906f, -0.349609f, 0.124023f, -0.356934f,
-0.11084f, -0.354004f, 0.10791f, -0.395996f, 0.119141f, -0.428223f, 0.115234f, -0.440918f,
-0.11084f, -0.449219f, 0.108887f, -0.506836f, 0.10791f, -0.52002f, 0.103027f, -0.520996f,
-0.103027f, -0.530762f, 0.118164f, -0.529785f, 0.12207f, -0.535156f, 0.116211f, -0.544434f,
-0.103027f, -0.546875f, 0.103027f, -0.551758f, 0.104004f, -0.583008f, 0.0991211f,
--0.61084f, 0.101074f, -0.623047f, 0.0888672f, -0.631836f, 0.0834961f, -0.639648f,
-0.078125f, -0.647461f, 0.078125f, -0.657227f, 0.078125f, -0.675781f, 0.100586f, -0.691895f,
-0.123047f, -0.708008f, 0.146973f, -0.708008f, 0.155762f, -0.707031f, 0.161133f, -0.713867f,
-0.171387f, -0.708008f, 0.172852f, -0.703125f, 0.169922f, -0.688965f, 0.167969f, -0.666016f,
-0.163086f, -0.654785f, 0.167969f, -0.626953f, 0.160156f, -0.625f, 0.163086f, -0.601074f,
-0.166992f, -0.596191f, 0.166992f, -0.584961f, 0.168945f, -0.570801f, 0.166016f, -0.546875f,
-0.167969f, -0.535156f, 0.160156f, -0.509766f, 0.161133f, -0.503906f, 0.164062f, -0.500977f,
-0.163086f, -0.490234f, 0.15918f, -0.421875f, 0.154785f, -0.404785f, 0.155762f, -0.391113f,
-0.165039f, -0.374023f, 0.164062f, -0.355957f, 0.163086f, -0.333008f, 0.161621f, -0.330566f,
-0.154785f, -0.324219f, 0.167969f, -0.294922f, 0.170898f, -0.268066f, 0.194824f, -0.0390625f,
-0.190918f, -0.0322266f, 0.183105f, -0.0170898f, 0.152832f, 0.00390625f, 0.14502f,
-0.0141602f, 0.129883f, 0.00683594f, 0.117188f, -0.00976562f, 0.0981445f, -0.0268555f,
-0.0878906f, -0.0439453f, 0.0854492f, -0.0454102f, 0.0771484f, -0.046875f, 0.0668945f,
--0.0498047f, 0.0683594f, -0.059082f, 0.0742188f, -0.0620117f, 0.10498f, -0.0810547f,
-0.12207f, -0.097168f, 0.12793f, -0.100098f, 0.132812f, -0.101074f, 0.145996f, -0.0888672f,
-0.181152f, -0.0639648f, 0.192383f, -0.0566406f, 0.194824f, -0.0390625f, 0.698242f,
--0.0458984f, 0.672852f, -0.0239258f, 0.665039f, -0.0078125f, 0.658203f, -0.012207f,
-0.651855f, -0.00878906f, 0.645996f, 0.00195312f, 0.619141f, 0.0141602f, 0.617188f,
-0.012207f, 0.605957f, 0.00878906f, 0.60498f, -0.00390625f, 0.606934f, -0.0161133f,
-0.616211f, -0.0332031f, 0.612793f, -0.0478516f, 0.615234f, -0.0600586f, 0.620117f,
--0.0888672f, 0.626953f, -0.11377f, 0.623047f, -0.145996f, 0.62207f, -0.155762f, 0.634766f,
--0.165039f, 0.635254f, -0.169922f, 0.635254f, -0.177246f, 0.635254f, -0.191406f,
-0.62793f, -0.208008f, 0.63623f, -0.233887f, 0.625977f, -0.243164f, 0.631836f, -0.269043f,
-0.626953f, -0.271973f, 0.629883f, -0.354004f, 0.624023f, -0.358887f, 0.619141f, -0.378906f,
-0.615234f, -0.375f, 0.606445f, -0.375f, 0.603271f, -0.373535f, 0.600098f, -0.37207f,
-0.594238f, -0.365234f, 0.582031f, -0.352051f, 0.562988f, -0.359863f, 0.543457f, -0.354004f,
-0.540039f, -0.354004f, 0.540527f, -0.354004f, 0.527832f, -0.355957f, 0.514648f, -0.366211f,
-0.504883f, -0.366211f, 0.503418f, -0.366211f, 0.502686f, -0.365967f, 0.501953f, -0.365723f,
-0.500977f, -0.365234f, 0.450195f, -0.36084f, 0.398926f, -0.367188f, 0.356934f, -0.36377f,
-0.335938f, -0.369141f, 0.304199f, -0.359863f, 0.254883f, -0.365234f, 0.242188f, -0.36377f,
-0.227051f, -0.375f, 0.222168f, -0.362793f, 0.162109f, -0.36377f, 0.149902f, -0.352051f,
-0.149902f, -0.341797f, 0.155762f, -0.303223f, 0.157227f, -0.297852f, 0.157227f, -0.287109f,
-0.157227f, -0.277344f, 0.151855f, -0.268066f, 0.154785f, -0.237793f, 0.147949f, -0.233398f,
-0.146484f, -0.229248f, 0.14502f, -0.225098f, 0.14502f, -0.216797f, 0.148926f, -0.210449f,
-0.15918f, -0.208008f, 0.160156f, -0.187012f, 0.160156f, -0.123047f, 0.160156f, -0.120117f,
-0.161133f, -0.10791f, 0.161133f, -0.103516f, 0.154785f, -0.0991211f, 0.155762f, -0.0888672f,
-0.163086f, -0.059082f, 0.164062f, -0.0488281f, 0.164062f, -0.0273438f, 0.144043f,
--0.0170898f, 0.119141f, -0.00488281f, 0.097168f, 0.0078125f, 0.0839844f, 0.0141602f,
-0.0810547f, 0.00976562f, 0.0761719f, 0.00976562f, 0.0708008f, -0.000976562f, 0.0708008f,
--0.00976562f, 0.0708008f, -0.0200195f, 0.0732422f, -0.0239258f, 0.0839844f, -0.0488281f,
-0.0888672f, -0.065918f, 0.0961914f, -0.0688477f, 0.097168f, -0.0849609f, 0.0888672f,
--0.0927734f, 0.0961914f, -0.106445f, 0.0961914f, -0.108887f, 0.0961914f, -0.111328f,
-0.0888672f, -0.124023f, 0.0878906f, -0.132812f, 0.0917969f, -0.213867f, 0.0869141f,
--0.23584f, 0.0869141f, -0.24707f, 0.0952148f, -0.25293f, 0.102051f, -0.258789f, 0.104492f,
--0.26123f, 0.105957f, -0.27002f, 0.0908203f, -0.275391f, 0.0908203f, -0.288086f,
-0.0908203f, -0.290039f, 0.0942383f, -0.327148f, 0.0878906f, -0.342773f, 0.0878906f,
--0.398926f, 0.0859375f, -0.426758f, 0.0869141f, -0.441895f, 0.0791016f, -0.440918f,
-0.0771484f, -0.438965f, 0.0732422f, -0.452148f, 0.0771484f, -0.448242f, 0.0791016f,
--0.466797f, 0.097168f, -0.477051f, 0.097168f, -0.487793f, 0.097168f, -0.50293f, 0.0771484f,
--0.505859f, 0.0698242f, -0.540039f, 0.0698242f, -0.547852f, 0.0668945f, -0.586914f,
-0.0668945f, -0.618164f, 0.0791016f, -0.623047f, 0.0952148f, -0.634766f, 0.121094f,
--0.646973f, 0.140137f, -0.654785f, 0.154785f, -0.648926f, 0.154785f, -0.639648f,
-0.161133f, -0.628906f, 0.153809f, -0.621094f, 0.152588f, -0.616211f, 0.151367f, -0.611328f,
-0.149902f, -0.591797f, 0.148926f, -0.580078f, 0.158203f, -0.545898f, 0.160156f, -0.525879f,
-0.155762f, -0.525879f, 0.146973f, -0.50293f, 0.153809f, -0.495117f, 0.151855f, -0.484863f,
-0.146973f, -0.476074f, 0.14209f, -0.46582f, 0.144043f, -0.455078f, 0.147949f, -0.446777f,
-0.151855f, -0.438965f, 0.151855f, -0.415039f, 0.163086f, -0.412109f, 0.25f, -0.407227f,
-0.263184f, -0.397949f, 0.295898f, -0.394043f, 0.306152f, -0.39502f, 0.309082f, -0.399902f,
-0.342773f, -0.397949f, 0.347168f, -0.396973f, 0.354004f, -0.402832f, 0.36084f, -0.402832f,
-0.371094f, -0.401855f, 0.371094f, -0.397949f, 0.376953f, -0.394043f, 0.388184f, -0.39502f,
-0.441895f, -0.395996f, 0.461914f, -0.397949f, 0.47998f, -0.39209f, 0.48877f, -0.404785f,
-0.500977f, -0.404785f, 0.50293f, -0.404785f, 0.527832f, -0.402832f, 0.575195f, -0.407227f,
-0.603027f, -0.405762f, 0.612793f, -0.408203f, 0.616211f, -0.418945f, 0.625f, -0.440918f,
-0.623047f, -0.49707f, 0.625f, -0.508789f, 0.618164f, -0.52002f, 0.605957f, -0.532227f,
-0.605957f, -0.553223f, 0.603027f, -0.575195f, 0.608887f, -0.585938f, 0.603027f, -0.605957f,
-0.603027f, -0.617188f, 0.603027f, -0.626465f, 0.608887f, -0.62793f, 0.62207f, -0.629883f,
-0.637207f, -0.641113f, 0.648926f, -0.641113f, 0.65625f, -0.643066f, 0.667969f, -0.654785f,
-0.682129f, -0.647949f, 0.687012f, -0.625f, 0.690918f, -0.611816f, 0.676758f, -0.560059f,
-0.680176f, -0.533203f, 0.678223f, -0.521973f, 0.672852f, -0.521973f, 0.666016f, -0.521973f,
-0.666016f, -0.512207f, 0.668457f, -0.506348f, 0.675781f, -0.50293f, 0.685059f, -0.498047f,
-0.687988f, -0.484863f, 0.690918f, -0.464844f, 0.689941f, -0.458984f, 0.682129f, -0.443848f,
-0.684082f, -0.35498f, 0.682129f, -0.278809f, 0.689941f, -0.26709f, 0.686035f, -0.249512f,
-0.686035f, -0.240234f, 0.686035f, -0.23877f, 0.686035f, -0.236816f, 0.686035f, -0.230957f,
-0.686035f, -0.219238f, 0.675781f, -0.208496f, 0.675781f, -0.204102f, 0.675781f, -0.202148f,
-0.676758f, -0.202148f, 0.689941f, -0.179199f, 0.687012f, -0.112793f, 0.688965f, -0.632812f,
-0.680176f, -0.625977f, 0.667969f, -0.60498f, 0.628906f, -0.589844f, 0.61084f, -0.578125f,
-0.60498f, -0.575195f, 0.599121f, -0.575195f, 0.598145f, -0.575195f, 0.569824f, -0.580078f,
-0.503906f, -0.582031f, 0.458008f, -0.586914f, 0.414062f, -0.583984f, 0.396973f, -0.586914f,
-0.390137f, -0.585938f, 0.384766f, -0.562988f, 0.387207f, -0.550781f, 0.388184f, -0.535156f,
-0.388184f, -0.530762f, 0.382812f, -0.507812f, 0.383789f, -0.490234f, 0.381836f, -0.475098f,
-0.384766f, -0.463867f, 0.373047f, -0.462891f, 0.369873f, -0.459961f, 0.366699f, -0.457031f,
-0.366211f, -0.445801f, 0.382324f, -0.443359f, 0.383789f, -0.437012f, 0.381836f, -0.401855f,
-0.381836f, -0.378906f, 0.381836f, -0.364258f, 0.362793f, -0.347168f, 0.365234f, -0.342773f,
-0.367188f, -0.340088f, 0.369141f, -0.337402f, 0.373291f, -0.335938f, 0.377441f, -0.334473f,
-0.381836f, -0.333984f, 0.384766f, -0.328125f, 0.378418f, -0.324219f, 0.376221f, -0.320312f,
-0.374023f, -0.316406f, 0.373047f, -0.307129f, 0.384766f, -0.293945f, 0.384766f, -0.27002f,
-0.384766f, -0.249023f, 0.384766f, -0.241211f, 0.37793f, -0.233887f, 0.382812f, -0.222168f,
-0.380859f, -0.208984f, 0.384766f, -0.190918f, 0.382812f, -0.176758f, 0.383789f, -0.165039f,
-0.384766f, -0.14502f, 0.366211f, -0.137207f, 0.366211f, -0.123047f, 0.366211f, -0.111328f,
-0.383789f, -0.102051f, 0.391113f, -0.0200195f, 0.383789f, -0.0141602f, 0.375f, -0.00976562f,
-0.349121f, 0.012207f, 0.339844f, 0.0131836f, 0.333008f, 0.0131836f, 0.327148f, 0.0200195f,
-0.321289f, 0.0161133f, 0.317871f, 0.0161133f, 0.317871f, 0.0161133f, 0.312012f, 0.0180664f,
-0.306152f, 0.00488281f, 0.307129f, 0.00195312f, 0.307373f, 0.000244141f, 0.307617f,
--0.00146484f, 0.308105f, -0.00292969f, 0.312012f, -0.0249023f, 0.308105f, -0.0507812f,
-0.312012f, -0.0888672f, 0.314941f, -0.14502f, 0.319824f, -0.187012f, 0.319824f, -0.198242f,
-0.329102f, -0.209961f, 0.316895f, -0.254883f, 0.321777f, -0.286133f, 0.318848f, -0.327148f,
-0.316895f, -0.35498f, 0.315918f, -0.355957f, 0.315918f, -0.36377f, 0.325195f, -0.390137f,
-0.321777f, -0.400879f, 0.311035f, -0.427734f, 0.311035f, -0.437988f, 0.311035f, -0.438965f,
-0.312012f, -0.453125f, 0.306152f, -0.478027f, 0.307129f, -0.492188f, 0.300781f, -0.527832f,
-0.298828f, -0.540039f, 0.313965f, -0.569824f, 0.324219f, -0.575684f, 0.324219f, -0.581055f,
-0.324219f, -0.585938f, 0.323242f, -0.588867f, 0.295898f, -0.594238f, 0.287109f, -0.594238f,
-0.276855f, -0.595215f, 0.254883f, -0.604004f, 0.210938f, -0.600098f, 0.144043f, -0.606934f,
-0.0717773f, -0.603027f, 0.0600586f, -0.60498f, 0.0478516f, -0.59082f, 0.0380859f,
--0.59082f, 0.0351562f, -0.59082f, 0.0209961f, -0.592773f, 0.00683594f, -0.595215f,
-0.00732422f, -0.609863f, 0.010498f, -0.615967f, 0.0136719f, -0.62207f, 0.0219727f,
--0.628906f, 0.0581055f, -0.657227f, 0.0732422f, -0.664062f, 0.100586f, -0.664062f,
-0.11377f, -0.664062f, 0.119629f, -0.649902f, 0.129883f, -0.649902f, 0.139648f, -0.649902f,
-0.152832f, -0.661133f, 0.174805f, -0.65918f, 0.217773f, -0.64502f, 0.253906f, -0.646973f,
-0.282227f, -0.640137f, 0.338867f, -0.637207f, 0.362793f, -0.624023f, 0.374023f, -0.623047f,
-0.375f, -0.626953f, 0.387207f, -0.625977f, 0.417969f, -0.623535f, 0.425537f, -0.62207f,
-0.433105f, -0.620605f, 0.440918f, -0.61377f, 0.458008f, -0.609863f, 0.466797f, -0.616211f,
-0.48291f, -0.617188f, 0.503906f, -0.625977f, 0.540039f, -0.625f, 0.563965f, -0.629883f,
-0.579102f, -0.625f, 0.588867f, -0.625f, 0.63623f, -0.625f, 0.680176f, -0.646973f,
-0.686035f, -0.644043f, 0.48877f, -0.0332031f, 0.483887f, -0.0239258f, 0.476074f,
--0.012207f, 0.461914f, -0.00683594f, 0.441895f, 0.00390625f, 0.422852f, 0.00976562f,
-0.404785f, 0.0170898f, 0.401855f, 0.0170898f, 0.398438f, 0.0170898f, 0.395264f, 0.0134277f,
-0.39209f, 0.00976562f, 0.39209f, 0.00683594f, 0.39209f, 0.00195312f, 0.396973f, -0.0151367f,
-0.399414f, -0.0200195f, 0.400879f, -0.0322266f, 0.391113f, -0.0258789f, 0.347168f,
--0.0112305f, 0.333984f, -0.00488281f, 0.320801f, -0.00488281f, 0.319824f, -0.00488281f,
-0.300781f, -0.00488281f, 0.277832f, 0.00585938f, 0.262207f, 0.0078125f, 0.216797f,
-0.0170898f, 0.198242f, 0.0141602f, 0.185059f, 0.019043f, 0.175781f, 0.0209961f, 0.161133f,
-0.0200195f, 0.128906f, 0.0131836f, 0.106934f, 0.0112305f, 0.0844727f, 0.00830078f,
-0.0681152f, -0.00415039f, 0.0517578f, -0.0166016f, 0.0439453f, -0.0361328f, 0.0307617f,
--0.0410156f, 0.027832f, -0.0532227f, 0.0268555f, -0.0620117f, 0.0200195f, -0.0849609f,
-0.0380859f, -0.121094f, 0.0439453f, -0.137207f, 0.046875f, -0.143555f, 0.0620117f,
--0.155762f, 0.100098f, -0.187012f, 0.116211f, -0.192871f, 0.143066f, -0.204102f,
-0.143555f, -0.204102f, 0.14502f, -0.203857f, 0.146484f, -0.203613f, 0.147949f, -0.203125f,
-0.157715f, -0.224121f, 0.185059f, -0.224121f, 0.187988f, -0.227051f, 0.198242f, -0.227051f,
-0.20459f, -0.234863f, 0.210938f, -0.237793f, 0.217285f, -0.240723f, 0.234863f, -0.244141f,
-0.295898f, -0.254883f, 0.313965f, -0.25293f, 0.336914f, -0.257812f, 0.37793f, -0.262207f,
-0.398926f, -0.26709f, 0.398926f, -0.282227f, 0.398926f, -0.28418f, 0.397949f, -0.285156f,
-0.393066f, -0.307129f, 0.396973f, -0.338867f, 0.395508f, -0.349121f, 0.389648f, -0.35376f,
-0.383789f, -0.358398f, 0.37207f, -0.359863f, 0.365234f, -0.371094f, 0.354492f, -0.388672f,
-0.347656f, -0.393799f, 0.34082f, -0.398926f, 0.321777f, -0.402832f, 0.293945f, -0.40918f,
-0.26709f, -0.410156f, 0.253906f, -0.408203f, 0.249512f, -0.410156f, 0.24707f, -0.413086f,
-0.244629f, -0.416016f, 0.243164f, -0.421875f, 0.22998f, -0.416016f, 0.214844f, -0.401855f,
-0.166992f, -0.37793f, 0.151855f, -0.369629f, 0.146973f, -0.361816f, 0.140137f, -0.352051f,
-0.135254f, -0.344238f, 0.126953f, -0.344238f, 0.117188f, -0.346191f, 0.103027f, -0.353027f,
-0.0878906f, -0.355957f, 0.0805664f, -0.358398f, 0.0732422f, -0.364258f, 0.065918f,
--0.370117f, 0.065918f, -0.375f, 0.065918f, -0.37793f, 0.0668945f, -0.37793f, 0.0751953f,
--0.383789f, 0.0908203f, -0.395996f, 0.10791f, -0.398926f, 0.133789f, -0.412109f,
-0.166016f, -0.422852f, 0.174805f, -0.424805f, 0.195801f, -0.436035f, 0.212891f, -0.433105f,
-0.271973f, -0.445801f, 0.296875f, -0.444824f, 0.315918f, -0.444824f, 0.335938f, -0.437988f,
-0.394043f, -0.426758f, 0.402832f, -0.421875f, 0.402832f, -0.415039f, 0.395996f, -0.411133f,
-0.398926f, -0.394043f, 0.408203f, -0.394043f, 0.40918f, -0.394531f, 0.409668f, -0.394775f,
-0.410156f, -0.39502f, 0.411133f, -0.39502f, 0.424805f, -0.400879f, 0.426758f, -0.400879f,
-0.431641f, -0.400879f, 0.433105f, -0.395996f, 0.442871f, -0.37793f, 0.453125f, -0.370117f,
-0.453125f, -0.358887f, 0.451172f, -0.333984f, 0.451172f, -0.317871f, 0.466797f, -0.306152f,
-0.473145f, -0.233887f, 0.459961f, -0.21582f, 0.475098f, -0.198242f, 0.476074f, -0.191895f,
-0.473145f, -0.145996f, 0.477051f, -0.11084f, 0.477051f, -0.103027f, 0.477051f, -0.0917969f,
-0.470215f, -0.0898438f, 0.471191f, -0.0776367f, 0.47168f, -0.0742188f, 0.472168f,
--0.0708008f, 0.475098f, -0.064209f, 0.478027f, -0.0576172f, 0.481934f, -0.0488281f,
-0.411133f, -0.118164f, 0.403809f, -0.124512f, 0.401855f, -0.128906f, 0.403809f, -0.148926f,
-0.399902f, -0.193848f, 0.405762f, -0.207031f, 0.390137f, -0.21582f, 0.381836f, -0.213867f,
-0.336914f, -0.216797f, 0.315918f, -0.21582f, 0.299805f, -0.227051f, 0.290039f, -0.221191f,
-0.263184f, -0.220215f, 0.244141f, -0.212891f, 0.23291f, -0.219238f, 0.219238f, -0.210938f,
-0.145996f, -0.175781f, 0.129883f, -0.164062f, 0.117188f, -0.14502f, 0.100098f, -0.134766f,
-0.0961914f, -0.130859f, 0.0961914f, -0.125977f, 0.0961914f, -0.125977f, 0.0964355f,
--0.125488f, 0.0966797f, -0.125f, 0.097168f, -0.124023f, 0.101074f, -0.118164f, 0.100098f,
--0.11377f, 0.11084f, -0.0698242f, 0.100098f, -0.0419922f, 0.10791f, -0.0322266f,
-0.121094f, -0.0478516f, 0.12793f, -0.0419922f, 0.133789f, -0.0380859f, 0.139648f,
--0.0341797f, 0.147949f, -0.0314941f, 0.15625f, -0.0288086f, 0.168945f, -0.0258789f,
-0.179199f, -0.012207f, 0.212891f, -0.00878906f, 0.222168f, -0.0180664f, 0.231934f,
--0.0131836f, 0.23877f, -0.0170898f, 0.244141f, -0.0200195f, 0.255859f, -0.0161133f,
-0.257812f, -0.0161133f, 0.272461f, -0.0161133f, 0.295898f, -0.0297852f, 0.297363f,
--0.0307617f, 0.299805f, -0.0319824f, 0.302246f, -0.0332031f, 0.307129f, -0.0361328f,
-0.351074f, -0.0361328f, 0.365234f, -0.0541992f, 0.375f, -0.0668945f, 0.398926f, -0.0869141f,
-0.399902f, -0.0927734f, 0.398926f, -0.0991211f, 0.40625f, -0.101562f, 0.408203f,
--0.10498f, 0.410156f, -0.108398f, 0.411133f, -0.118164f, 0.484863f, -0.0927734f,
-0.484863f, -0.0898438f, 0.483887f, -0.0878906f, 0.478027f, -0.0629883f, 0.478027f,
--0.0625f, 0.478271f, -0.0615234f, 0.478516f, -0.0605469f, 0.479004f, -0.059082f,
-0.458008f, -0.0332031f, 0.445801f, -0.0297852f, 0.426758f, -0.0170898f, 0.418945f,
--0.0151367f, 0.396973f, -0.00390625f, 0.39502f, -0.00390625f, 0.36377f, -0.00488281f,
-0.355469f, -0.00488281f, 0.34082f, 0.00195312f, 0.315918f, 0.0161133f, 0.276855f,
-0.019043f, 0.237793f, 0.0161133f, 0.229004f, 0.00878906f, 0.200195f, 0.00488281f,
-0.167969f, -0.00390625f, 0.123047f, -0.0141602f, 0.102051f, -0.0322266f, 0.0830078f,
--0.0517578f, 0.0888672f, -0.0688477f, 0.0795898f, -0.0649414f, 0.0717773f, -0.0649414f,
-0.0678711f, -0.0649414f, 0.059082f, -0.0751953f, 0.046875f, -0.0961914f, 0.0400391f,
--0.10498f, 0.0371094f, -0.132812f, 0.0410156f, -0.146973f, 0.0371094f, -0.154785f,
-0.0268555f, -0.166016f, 0.0332031f, -0.190918f, 0.0307617f, -0.23584f, 0.0478516f,
--0.265137f, 0.0688477f, -0.308105f, 0.0961914f, -0.331055f, 0.14502f, -0.37793f,
-0.15918f, -0.388184f, 0.178223f, -0.401855f, 0.187012f, -0.404785f, 0.207031f, -0.419922f,
-0.27002f, -0.439941f, 0.285156f, -0.443848f, 0.286133f, -0.443848f, 0.286865f, -0.443604f,
-0.287598f, -0.443359f, 0.288086f, -0.442871f, 0.312988f, -0.432129f, 0.337891f, -0.438965f,
-0.384766f, -0.431152f, 0.424805f, -0.437012f, 0.432129f, -0.435059f, 0.440918f, -0.431152f,
-0.437012f, -0.415527f, 0.432373f, -0.4104f, 0.427734f, -0.405273f, 0.413086f, -0.398926f,
-0.412109f, -0.388184f, 0.39209f, -0.375977f, 0.37793f, -0.369141f, 0.375977f, -0.369141f,
-0.362793f, -0.371094f, 0.346191f, -0.369141f, 0.270996f, -0.380859f, 0.26709f, -0.381836f,
-0.259766f, -0.381836f, 0.25293f, -0.381836f, 0.25f, -0.380859f, 0.208984f, -0.373047f,
-0.195801f, -0.373047f, 0.179199f, -0.370117f, 0.163086f, -0.347168f, 0.14209f, -0.339844f,
-0.132812f, -0.319824f, 0.116211f, -0.316895f, 0.118164f, -0.312988f, 0.118164f, -0.310059f,
-0.0981445f, -0.270996f, 0.0961914f, -0.253906f, 0.097168f, -0.224121f, 0.0976562f,
--0.202637f, 0.100586f, -0.188477f, 0.103516f, -0.174316f, 0.11084f, -0.160156f, 0.106934f,
--0.148926f, 0.102051f, -0.140625f, 0.102051f, -0.138184f, 0.102051f, -0.135254f,
-0.10498f, -0.130859f, 0.119629f, -0.126953f, 0.119141f, -0.126953f, 0.123535f, -0.123535f,
-0.133789f, -0.108887f, 0.146973f, -0.0908203f, 0.147949f, -0.0888672f, 0.148926f,
--0.0864258f, 0.149902f, -0.0839844f, 0.151855f, -0.0800781f, 0.163086f, -0.0800781f,
-0.168945f, -0.0717773f, 0.201172f, -0.0488281f, 0.214844f, -0.0371094f, 0.230957f,
--0.0322266f, 0.245117f, -0.0268555f, 0.26709f, -0.0258789f, 0.323242f, -0.0200195f,
-0.324219f, -0.0195312f, 0.324707f, -0.0192871f, 0.325195f, -0.019043f, 0.325195f,
--0.019043f, 0.333496f, -0.019043f, 0.359863f, -0.0332031f, 0.369141f, -0.0297852f,
-0.402832f, -0.0532227f, 0.416016f, -0.0551758f, 0.428711f, -0.0639648f, 0.441406f,
--0.0727539f, 0.462891f, -0.0952148f, 0.469238f, -0.103027f, 0.475098f, -0.103027f,
-0.479004f, -0.103027f, 0.481934f, -0.100098f, 0.484863f, -0.097168f, 0.484863f, -0.0927734f,
-0.51123f, -0.100098f, 0.51123f, -0.09375f, 0.508789f, -0.0888672f, 0.499023f, -0.0717773f,
-0.476074f, -0.0322266f, 0.455078f, -0.0307617f, 0.441895f, -0.0200195f, 0.4375f,
--0.015625f, 0.426758f, -0.0141602f, 0.338867f, 0.00292969f, 0.325195f, 0.0078125f,
-0.293945f, 0.00488281f, 0.249023f, 0.00878906f, 0.198242f, 0.00585938f, 0.184082f,
-0.00585938f, 0.17334f, -0.00244141f, 0.170898f, -0.00390625f, 0.123047f, -0.0209961f,
-0.106934f, -0.0361328f, 0.0751953f, -0.0581055f, 0.0498047f, -0.0917969f, 0.0400391f,
--0.100098f, 0.0458984f, -0.111816f, 0.0458984f, -0.121094f, 0.0458984f, -0.125f,
-0.0439453f, -0.126953f, 0.0307617f, -0.147949f, 0.027832f, -0.175781f, 0.0268555f,
--0.198242f, 0.0268555f, -0.209473f, 0.0322266f, -0.228027f, 0.0405273f, -0.257324f,
-0.0458984f, -0.263184f, 0.0639648f, -0.286133f, 0.0732422f, -0.307129f, 0.0961914f,
--0.329102f, 0.121094f, -0.361816f, 0.143066f, -0.374023f, 0.174805f, -0.395996f,
-0.195801f, -0.410156f, 0.203125f, -0.415039f, 0.217773f, -0.417969f, 0.262207f, -0.432129f,
-0.296875f, -0.436035f, 0.317871f, -0.444824f, 0.328125f, -0.445801f, 0.353027f, -0.445801f,
-0.370117f, -0.418945f, 0.379395f, -0.419922f, 0.383789f, -0.429199f, 0.396973f, -0.417969f,
-0.415039f, -0.408203f, 0.456055f, -0.368164f, 0.463867f, -0.358398f, 0.468018f, -0.351318f,
-0.472168f, -0.344238f, 0.476318f, -0.336426f, 0.480469f, -0.328613f, 0.483643f, -0.319336f,
-0.486816f, -0.310059f, 0.493164f, -0.291016f, 0.49707f, -0.278809f, 0.492188f, -0.276855f,
-0.473145f, -0.280762f, 0.452148f, -0.273926f, 0.436035f, -0.276855f, 0.417969f, -0.271973f,
-0.383789f, -0.275879f, 0.351074f, -0.273926f, 0.316895f, -0.279785f, 0.26123f, -0.278809f,
-0.233887f, -0.279785f, 0.167969f, -0.270996f, 0.144043f, -0.271973f, 0.11084f, -0.262207f,
-0.0991211f, -0.259766f, 0.097168f, -0.248047f, 0.0961914f, -0.23584f, 0.09375f, -0.231445f,
-0.0913086f, -0.227051f, 0.0830078f, -0.221191f, 0.0839844f, -0.211914f, 0.100098f,
--0.199707f, 0.101074f, -0.196777f, 0.11377f, -0.146973f, 0.120117f, -0.134766f, 0.115234f,
--0.129883f, 0.115234f, -0.125977f, 0.115234f, -0.125977f, 0.115479f, -0.125488f,
-0.115723f, -0.125f, 0.116211f, -0.124023f, 0.134766f, -0.118164f, 0.13916f, -0.105957f,
-0.144043f, -0.0888672f, 0.151855f, -0.0849609f, 0.178223f, -0.0742188f, 0.187012f,
--0.0551758f, 0.193848f, -0.0517578f, 0.208984f, -0.0498047f, 0.21582f, -0.0371094f,
-0.230957f, -0.0351562f, 0.272949f, -0.0200195f, 0.308105f, -0.0268555f, 0.400879f,
--0.0419922f, 0.420898f, -0.0541992f, 0.452148f, -0.0732422f, 0.478027f, -0.106934f,
-0.484863f, -0.115234f, 0.494141f, -0.115234f, 0.51123f, -0.115234f, 0.51123f, -0.100098f,
-0.395996f, -0.330078f, 0.395996f, -0.337891f, 0.37793f, -0.362793f, 0.344238f, -0.387207f,
-0.333008f, -0.398926f, 0.316895f, -0.399902f, 0.279785f, -0.402832f, 0.270996f, -0.400879f,
-0.25f, -0.38916f, 0.223145f, -0.382812f, 0.188965f, -0.370117f, 0.175781f, -0.365234f,
-0.160156f, -0.341797f, 0.145508f, -0.331543f, 0.144043f, -0.329102f, 0.14209f, -0.323242f,
-0.202148f, -0.318848f, 0.208984f, -0.319824f, 0.220215f, -0.323242f, 0.230957f, -0.320801f,
-0.259766f, -0.314941f, 0.26123f, -0.314941f, 0.293945f, -0.320801f, 0.304199f, -0.323242f,
-0.312012f, -0.312012f, 0.323242f, -0.312012f, 0.366211f, -0.320801f, 0.383789f, -0.318848f,
-0.395996f, -0.320312f, 0.395996f, -0.330078f, 0.433105f, -0.911133f, 0.428223f, -0.899902f,
-0.413086f, -0.883789f, 0.401855f, -0.870117f, 0.38916f, -0.861816f, 0.375977f, -0.85498f,
-0.333984f, -0.875977f, 0.310547f, -0.888184f, 0.296875f, -0.888184f, 0.28418f, -0.888184f,
-0.254883f, -0.875977f, 0.224121f, -0.864746f, 0.210938f, -0.829102f, 0.196777f, -0.790039f,
-0.186035f, -0.76709f, 0.179199f, -0.734863f, 0.170898f, -0.724121f, 0.173828f, -0.709961f,
-0.179199f, -0.707031f, 0.176758f, -0.604004f, 0.166992f, -0.591797f, 0.166992f, -0.578125f,
-0.166016f, -0.566895f, 0.178223f, -0.538086f, 0.173828f, -0.518066f, 0.178223f, -0.470215f,
-0.178223f, -0.467773f, 0.178223f, -0.456543f, 0.162109f, -0.443848f, 0.164062f, -0.434082f,
-0.180664f, -0.42627f, 0.182129f, -0.421875f, 0.185059f, -0.402832f, 0.185059f, -0.395996f,
-0.196777f, -0.395996f, 0.211914f, -0.39502f, 0.265137f, -0.39209f, 0.304199f, -0.397949f,
-0.346191f, -0.401855f, 0.368164f, -0.408203f, 0.379883f, -0.40918f, 0.398926f, -0.40918f,
-0.411133f, -0.38916f, 0.399902f, -0.381836f, 0.36377f, -0.358887f, 0.345215f, -0.342773f,
-0.295898f, -0.350098f, 0.245117f, -0.345215f, 0.234863f, -0.345215f, 0.226074f, -0.348145f,
-0.201172f, -0.35498f, 0.195801f, -0.35498f, 0.188965f, -0.35498f, 0.183594f, -0.347168f,
-0.178223f, -0.339355f, 0.178223f, -0.331055f, 0.178223f, -0.328125f, 0.186035f, -0.254883f,
-0.186035f, -0.253906f, 0.186035f, -0.249023f, 0.173828f, -0.243164f, 0.171875f, -0.232422f,
-0.171875f, -0.233887f, 0.171875f, -0.226562f, 0.182129f, -0.214844f, 0.185059f, -0.201172f,
-0.187988f, -0.144043f, 0.191895f, -0.124023f, 0.186035f, -0.118164f, 0.181152f, -0.118164f,
-0.179199f, -0.119141f, 0.171387f, -0.114746f, 0.169922f, -0.105957f, 0.174805f, -0.105957f,
-0.173828f, -0.102051f, 0.187988f, -0.0839844f, 0.187988f, -0.0717773f, 0.186035f,
--0.0581055f, 0.187988f, -0.0458984f, 0.190918f, -0.0341797f, 0.182129f, -0.0297852f,
-0.182129f, -0.0161133f, 0.138184f, 0.00292969f, 0.0991211f, 0.0078125f, 0.0927734f,
-0.00292969f, 0.0927734f, -0.00195312f, 0.0981445f, -0.0131836f, 0.102051f, -0.046875f,
-0.109863f, -0.0678711f, 0.112793f, -0.0898438f, 0.109863f, -0.115234f, 0.123047f,
--0.128906f, 0.123047f, -0.141113f, 0.12207f, -0.147949f, 0.111816f, -0.182129f, 0.111816f,
--0.185059f, 0.112793f, -0.22998f, 0.115234f, -0.315918f, 0.117188f, -0.328125f, 0.140137f,
--0.331055f, 0.140137f, -0.341797f, 0.140137f, -0.348145f, 0.134766f, -0.348145f,
-0.116211f, -0.350098f, 0.100098f, -0.356934f, 0.0771484f, -0.356934f, 0.0610352f,
--0.358887f, 0.0507812f, -0.359863f, 0.0419922f, -0.359863f, 0.0361328f, -0.356934f,
-0.0205078f, -0.352051f, 0.0180664f, -0.352051f, 0.00976562f, -0.352051f, 0.00976562f,
--0.36084f, 0.00976562f, -0.364746f, 0.012207f, -0.367188f, 0.0219727f, -0.380859f,
-0.0400391f, -0.403809f, 0.046875f, -0.410156f, 0.059082f, -0.410156f, 0.0673828f,
--0.410156f, 0.0820312f, -0.405762f, 0.10791f, -0.419922f, 0.106934f, -0.425781f,
-0.111816f, -0.458008f, 0.109863f, -0.509766f, 0.111328f, -0.524414f, 0.121094f, -0.53418f,
-0.10498f, -0.557129f, 0.105957f, -0.567871f, 0.103027f, -0.675781f, 0.103027f, -0.690918f,
-0.11084f, -0.704102f, 0.12793f, -0.73291f, 0.12793f, -0.737305f, 0.117188f, -0.745117f,
-0.12207f, -0.779785f, 0.14917f, -0.81958f, 0.17627f, -0.859375f, 0.208008f, -0.87793f,
-0.269043f, -0.915039f, 0.282227f, -0.923828f, 0.298828f, -0.925781f, 0.331055f, -0.934082f,
-0.347168f, -0.929199f, 0.383789f, -0.930176f, 0.393066f, -0.929688f, 0.400635f, -0.925293f,
-0.408203f, -0.920898f, 0.418945f, -0.910156f, 0.422852f, -0.914062f, 0.425781f, -0.914062f,
-0.428711f, -0.914062f, 0.433105f, -0.911133f, 0.160156f, -0.0869141f, 0.158203f,
--0.0610352f, 0.15918f, -0.0410156f, 0.15918f, -0.0336914f, 0.151855f, -0.0288086f,
-0.154785f, -0.0170898f, 0.144043f, -0.0151367f, 0.111816f, 0.00488281f, 0.0991211f,
-0.00683594f, 0.0839844f, 0.0161133f, 0.0820312f, 0.0161133f, 0.0805664f, 0.0163574f,
-0.0791016f, 0.0166016f, 0.0771484f, 0.0170898f, 0.0678711f, 0.0170898f, 0.0678711f,
-0.0112305f, 0.0678711f, -0.000976562f, 0.0649414f, -0.0229492f, 0.0717773f, -0.0761719f,
-0.0742188f, -0.144043f, 0.0756836f, -0.168945f, 0.0849609f, -0.185059f, 0.0791016f,
--0.200195f, 0.0708008f, -0.215332f, 0.0708008f, -0.217773f, 0.0708008f, -0.225586f,
-0.0830078f, -0.246094f, 0.0878906f, -0.253418f, 0.0878906f, -0.262207f, 0.0878906f,
--0.269043f, 0.0732422f, -0.274902f, 0.0751953f, -0.283203f, 0.0708008f, -0.285156f,
-0.0708008f, -0.291992f, 0.0708008f, -0.299805f, 0.0791016f, -0.333984f, 0.0791016f,
--0.417969f, 0.0888672f, -0.457031f, 0.0888672f, -0.464844f, 0.0771484f, -0.474121f,
-0.0771484f, -0.49707f, 0.0751953f, -0.584961f, 0.0751953f, -0.594727f, 0.0878906f,
--0.618164f, 0.0952148f, -0.630859f, 0.0771484f, -0.63916f, 0.0771484f, -0.645996f,
-0.0771484f, -0.644043f, 0.0800781f, -0.665039f, 0.0698242f, -0.673828f, 0.0698242f,
--0.692871f, 0.0678711f, -0.71582f, 0.0678711f, -0.720215f, 0.0761719f, -0.745117f,
-0.0678711f, -0.779785f, 0.0698242f, -0.796875f, 0.0600586f, -0.854004f, 0.0600586f,
--0.858887f, 0.0600586f, -0.861816f, 0.0639648f, -0.87793f, 0.0668945f, -0.897949f,
-0.11084f, -0.921875f, 0.130859f, -0.937012f, 0.13916f, -0.938965f, 0.145996f, -0.928223f,
-0.146973f, -0.907227f, 0.150879f, -0.893066f, 0.151855f, -0.884766f, 0.151855f, -0.873047f,
-0.148926f, -0.836914f, 0.148926f, -0.833984f, 0.149902f, -0.816895f, 0.149902f, -0.808105f,
-0.147949f, -0.804199f, 0.13623f, -0.778809f, 0.134766f, -0.769043f, 0.144531f, -0.768555f,
-0.147217f, -0.765869f, 0.149902f, -0.763184f, 0.149902f, -0.751953f, 0.149902f, -0.741211f,
-0.149902f, -0.731445f, 0.138184f, -0.725098f, 0.138184f, -0.712891f, 0.137207f, -0.703125f,
-0.137207f, -0.699219f, 0.145996f, -0.685059f, 0.14209f, -0.591797f, 0.14209f, -0.524902f,
-0.128906f, -0.499023f, 0.13623f, -0.461914f, 0.125977f, -0.437988f, 0.127441f, -0.433594f,
-0.134766f, -0.426758f, 0.143066f, -0.417969f, 0.146973f, -0.259766f, 0.134766f, -0.246094f,
-0.13623f, -0.236816f, 0.13623f, -0.226074f, 0.13623f, -0.208984f, 0.131836f, -0.193848f,
-0.13623f, -0.183105f, 0.149902f, -0.183105f, 0.149902f, -0.165039f, 0.496094f, -0.0332031f,
-0.491211f, -0.019043f, 0.423828f, 0.0131836f, 0.410156f, -0.00439453f, 0.410156f,
--0.00878906f, 0.410156f, -0.0112305f, 0.421875f, -0.0581055f, 0.422852f, -0.0791016f,
-0.426758f, -0.078125f, 0.435059f, -0.0878906f, 0.431641f, -0.0957031f, 0.428467f,
--0.0981445f, 0.425293f, -0.100586f, 0.416992f, -0.104004f, 0.415039f, -0.111816f,
-0.422852f, -0.203125f, 0.417969f, -0.21582f, 0.418945f, -0.231934f, 0.418945f, -0.269043f,
-0.424805f, -0.287109f, 0.416016f, -0.295898f, 0.416992f, -0.325195f, 0.411621f, -0.341309f,
-0.398926f, -0.355957f, 0.398926f, -0.36084f, 0.398926f, -0.367188f, 0.39502f, -0.370117f,
-0.382812f, -0.371094f, 0.35791f, -0.38623f, 0.317871f, -0.383789f, 0.271973f, -0.387207f,
-0.266113f, -0.384277f, 0.258789f, -0.375f, 0.25f, -0.376953f, 0.211914f, -0.370117f,
-0.198242f, -0.367188f, 0.181152f, -0.354004f, 0.15918f, -0.344238f, 0.143066f, -0.336426f,
-0.141113f, -0.320801f, 0.140137f, -0.272949f, 0.133789f, -0.243164f, 0.144043f, -0.213867f,
-0.144043f, -0.198242f, 0.143066f, -0.140137f, 0.133789f, -0.120117f, 0.132812f, -0.112793f,
-0.132812f, -0.109863f, 0.14209f, -0.0942383f, 0.14502f, -0.0410156f, 0.148926f, -0.0239258f,
-0.148926f, -0.0209961f, 0.145996f, -0.0163574f, 0.143066f, -0.0117188f, 0.138184f,
--0.00976562f, 0.105957f, -0.00195312f, 0.097168f, 0, 0.0893555f, 0.0131836f, 0.0820312f,
-0.0131836f, 0.0771484f, 0.0131836f, 0.0717773f, 0.0078125f, 0.0712891f, 0.00683594f,
-0.0705566f, 0.00585938f, 0.0698242f, 0.00488281f, 0.0688477f, 0.00390625f, 0.0668945f,
-0, 0.0668945f, 0.000976562f, 0.0742188f, -0.0351562f, 0.0732422f, -0.0761719f, 0.078125f,
--0.0927734f, 0.0742188f, -0.120117f, 0.0761719f, -0.149902f, 0.0771484f, -0.212891f,
-0.0771484f, -0.225586f, 0.0942383f, -0.227051f, 0.0927734f, -0.237793f, 0.0891113f,
--0.240479f, 0.0854492f, -0.243164f, 0.0732422f, -0.243164f, 0.0742188f, -0.331055f,
-0.0849609f, -0.337891f, 0.0791016f, -0.348145f, 0.065918f, -0.383789f, 0.0571289f,
--0.39502f, 0.0629883f, -0.405762f, 0.0732422f, -0.417969f, 0.0908203f, -0.425781f,
-0.10791f, -0.438965f, 0.115234f, -0.444824f, 0.125977f, -0.444824f, 0.132324f, -0.444824f,
-0.138184f, -0.441162f, 0.144043f, -0.4375f, 0.14502f, -0.433105f, 0.145996f, -0.387207f,
-0.147949f, -0.37207f, 0.157227f, -0.375f, 0.174805f, -0.396484f, 0.198486f, -0.415283f,
-0.222168f, -0.434082f, 0.233887f, -0.434082f, 0.240234f, -0.434082f, 0.244141f, -0.423828f,
-0.253906f, -0.426758f, 0.26709f, -0.435059f, 0.28125f, -0.442871f, 0.291016f, -0.442871f,
-0.293945f, -0.442871f, 0.333984f, -0.438965f, 0.349121f, -0.443848f, 0.394043f, -0.437988f,
-0.416992f, -0.435059f, 0.430176f, -0.421875f, 0.437012f, -0.422852f, 0.452637f, -0.422852f,
-0.462891f, -0.40918f, 0.470215f, -0.396973f, 0.47998f, -0.380859f, 0.486816f, -0.372559f,
-0.486816f, -0.345215f, 0.486816f, -0.317871f, 0.48877f, -0.306152f, 0.477051f, -0.291016f,
-0.480957f, -0.278809f, 0.486816f, -0.268066f, 0.486816f, -0.256836f, 0.486816f, -0.248047f,
-0.486816f, -0.244141f, 0.48584f, -0.242188f, 0.479004f, -0.228027f, 0.477051f, -0.224121f,
-0.477051f, -0.213867f, 0.486816f, -0.201172f, 0.48584f, -0.187012f, 0.484863f, -0.152832f,
-0.484863f, -0.148926f, 0.492188f, -0.129883f, 0.493164f, -0.0859375f, 0.571777f,
--0.248047f, 0.561035f, -0.25f, 0.562988f, -0.23877f, 0.551758f, -0.230957f, 0.554199f,
--0.222168f, 0.555908f, -0.220215f, 0.557617f, -0.218262f, 0.564941f, -0.213867f,
-0.565918f, -0.204102f, 0.565918f, -0.150879f, 0.524902f, -0.0888672f, 0.515625f,
--0.0751953f, 0.501953f, -0.0600586f, 0.488281f, -0.0449219f, 0.484863f, -0.0400391f,
-0.470215f, -0.0361328f, 0.37793f, 0.00683594f, 0.327148f, 0.00878906f, 0.290039f,
-0.0180664f, 0.246094f, 0.0170898f, 0.230957f, 0.0209961f, 0.187012f, 0.0131836f,
-0.168945f, 0.012207f, 0.15918f, 0.000976562f, 0.131836f, -0.00292969f, 0.119141f,
--0.00976562f, 0.102539f, -0.0224609f, 0.0913086f, -0.0310059f, 0.0800781f, -0.0395508f,
-0.0769043f, -0.0422363f, 0.0737305f, -0.0449219f, 0.0717773f, -0.0478516f, 0.0610352f,
--0.0688477f, 0.0458984f, -0.0810547f, 0.0341797f, -0.111816f, 0.0297852f, -0.124023f,
-0.0351562f, -0.12793f, 0.0351562f, -0.134766f, 0.0371094f, -0.137207f, 0.0390625f,
--0.139648f, 0.0458984f, -0.14209f, 0.0429688f, -0.149902f, 0.0268555f, -0.160156f,
-0.0268555f, -0.180176f, 0.0268555f, -0.201172f, 0.0317383f, -0.22168f, 0.0366211f,
--0.242188f, 0.0488281f, -0.269043f, 0.0678711f, -0.312012f, 0.0771484f, -0.317871f,
-0.097168f, -0.331055f, 0.10791f, -0.350098f, 0.11377f, -0.360352f, 0.12207f, -0.36377f,
-0.167969f, -0.388184f, 0.193848f, -0.40918f, 0.225098f, -0.420898f, 0.279785f, -0.439941f,
-0.325195f, -0.443848f, 0.36084f, -0.444824f, 0.391113f, -0.444824f, 0.391113f, -0.428223f,
-0.399414f, -0.420898f, 0.401855f, -0.420898f, 0.40918f, -0.420898f, 0.417969f, -0.435059f,
-0.430176f, -0.432129f, 0.461914f, -0.420898f, 0.475098f, -0.410156f, 0.493164f, -0.398926f,
-0.51123f, -0.371094f, 0.518555f, -0.361816f, 0.540039f, -0.361816f, 0.554199f, -0.344238f,
-0.559082f, -0.327148f, 0.563965f, -0.310059f, 0.569824f, -0.26416f, 0.500977f, -0.23584f,
-0.48291f, -0.291992f, 0.47998f, -0.316895f, 0.475098f, -0.326172f, 0.472168f, -0.326172f,
-0.468262f, -0.326172f, 0.46582f, -0.327637f, 0.463379f, -0.329102f, 0.459961f, -0.333008f,
-0.436035f, -0.362793f, 0.428223f, -0.375f, 0.387207f, -0.394043f, 0.381348f, -0.403809f,
-0.377197f, -0.408447f, 0.373047f, -0.413086f, 0.367188f, -0.413086f, 0.36084f, -0.413086f,
-0.347168f, -0.408203f, 0.333496f, -0.414062f, 0.327148f, -0.414062f, 0.312988f, -0.412109f,
-0.289062f, -0.411133f, 0.255859f, -0.398926f, 0.248047f, -0.405762f, 0.242188f, -0.397949f,
-0.208984f, -0.37793f, 0.147949f, -0.325195f, 0.13623f, -0.314941f, 0.132324f, -0.290039f,
-0.11377f, -0.257812f, 0.106934f, -0.246094f, 0.106934f, -0.242188f, 0.106934f, -0.231445f,
-0.103516f, -0.228027f, 0.100098f, -0.224609f, 0.0898438f, -0.223145f, 0.0878906f,
--0.215332f, 0.0878906f, -0.21582f, 0.0883789f, -0.214844f, 0.088623f, -0.214111f,
-0.0888672f, -0.213379f, 0.0888672f, -0.212891f, 0.104004f, -0.195801f, 0.105957f,
--0.185059f, 0.0908203f, -0.172363f, 0.0908203f, -0.167969f, 0.0908203f, -0.167969f,
-0.0927734f, -0.162109f, 0.097168f, -0.166992f, 0.101074f, -0.166992f, 0.105469f,
--0.166992f, 0.106934f, -0.164062f, 0.118164f, -0.12793f, 0.143066f, -0.0869141f,
-0.140137f, -0.0620117f, 0.144043f, -0.0581055f, 0.148926f, -0.0581055f, 0.154785f,
--0.0581055f, 0.161133f, -0.0639648f, 0.170898f, -0.0610352f, 0.22998f, -0.0249023f,
-0.290039f, -0.019043f, 0.324219f, -0.0141602f, 0.362793f, -0.0209961f, 0.388184f,
--0.0268555f, 0.419922f, -0.059082f, 0.442871f, -0.065918f, 0.454102f, -0.078125f,
-0.47998f, -0.131836f, 0.493164f, -0.143066f, 0.5f, -0.149902f, 0.5f, -0.154785f,
-0.5f, -0.157227f, 0.492188f, -0.180176f, 0.587891f, -0.201172f, 0.578125f, -0.174805f,
-0.573242f, -0.163086f, 0.559082f, -0.14502f, 0.548828f, -0.125977f, 0.536133f, -0.112793f,
-0.526855f, -0.101074f, 0.52002f, -0.0991211f, 0.506836f, -0.102051f, 0.501953f, -0.0927734f,
-0.489258f, -0.0698242f, 0.482666f, -0.0639648f, 0.476074f, -0.0581055f, 0.458984f,
--0.0581055f, 0.458008f, -0.0581055f, 0.450195f, -0.059082f, 0.448242f, -0.0424805f,
-0.436279f, -0.0310059f, 0.424316f, -0.0195312f, 0.396973f, -0.00976562f, 0.370117f,
--0.000976562f, 0.348145f, 0.00683594f, 0.304199f, 0.0078125f, 0.291992f, 0.00976562f,
-0.279785f, 0.0180664f, 0.269043f, 0.012207f, 0.26416f, 0.0117188f, 0.259277f, 0.0112305f,
-0.23291f, 0.00878906f, 0.221191f, 0.0078125f, 0.223145f, -0.00390625f, 0.211914f,
--0.00585938f, 0.202148f, 0, 0.193848f, 0.00390625f, 0.180176f, 0.00390625f, 0.158203f,
-0.00390625f, 0.148926f, 0.000976562f, 0.145996f, 0.0131836f, 0.147949f, 0.0859375f,
-0.141113f, 0.119141f, 0.140137f, 0.132812f, 0.147949f, 0.132812f, 0.150879f, 0.223145f,
-0.13916f, 0.225098f, 0.13623f, 0.23291f, 0.138184f, 0.245117f, 0.144043f, 0.270996f,
-0.141113f, 0.282227f, 0.147949f, 0.276855f, 0.152832f, 0.279785f, 0.153809f, 0.312988f,
-0.157227f, 0.345215f, 0.15918f, 0.367188f, 0.15918f, 0.376465f, 0.144043f, 0.37793f,
-0.141113f, 0.384766f, 0.158203f, 0.38916f, 0.157227f, 0.398926f, 0.162109f, 0.422852f,
-0.164062f, 0.438965f, 0.158203f, 0.448242f, 0.145996f, 0.458008f, 0.13623f, 0.474121f,
-0.124023f, 0.478027f, 0.0981445f, 0.490234f, 0.0898438f, 0.491211f, 0.0717773f, 0.490234f,
-0.0708008f, 0.472168f, 0.0717773f, 0.456055f, 0.0751953f, 0.415039f, 0.0742188f,
-0.374023f, 0.074707f, 0.367676f, 0.0766602f, 0.36377f, 0.0786133f, 0.359863f, 0.0849609f,
-0.35498f, 0.0800781f, 0.323242f, 0.0893555f, 0.313965f, 0.0915527f, 0.310059f, 0.09375f,
-0.306152f, 0.0942383f, 0.296875f, 0.0859375f, 0.293945f, 0.083252f, 0.291016f, 0.0805664f,
-0.288086f, 0.0791016f, 0.282227f, 0.0830078f, 0.26416f, 0.0810547f, 0.250977f, 0.0800781f,
-0.199219f, 0.078125f, 0.160156f, 0.0830078f, 0.11377f, 0.0839844f, 0.101074f, 0.0952148f,
-0.090332f, 0.0952148f, 0.0800781f, 0.0952148f, 0.0717773f, 0.0908203f, 0.0541992f,
-0.0800781f, 0.0507812f, 0.0751953f, 0.0341797f, 0.0751953f, 0.0268555f, 0.0810547f,
--0.13623f, 0.0869141f, -0.153809f, 0.0849609f, -0.171875f, 0.0830078f, -0.185059f,
-0.0742188f, -0.187988f, 0.0742188f, -0.201172f, 0.0717773f, -0.272949f, 0.0717773f,
--0.280762f, 0.0751953f, -0.300781f, 0.0698242f, -0.341797f, 0.0698242f, -0.358887f,
-0.067627f, -0.363037f, 0.0654297f, -0.367188f, 0.0532227f, -0.374023f, 0.0546875f,
--0.389648f, 0.059082f, -0.394043f, 0.0688477f, -0.399902f, 0.0917969f, -0.425781f,
-0.112793f, -0.437988f, 0.125f, -0.443848f, 0.134277f, -0.442871f, 0.147949f, -0.431152f,
-0.145996f, -0.421875f, 0.144043f, -0.407227f, 0.14502f, -0.398926f, 0.153809f, -0.397949f,
-0.170898f, -0.407227f, 0.200684f, -0.422363f, 0.2146f, -0.427246f, 0.228516f, -0.432129f,
-0.244141f, -0.432129f, 0.252441f, -0.432129f, 0.25708f, -0.429932f, 0.261719f, -0.427734f,
-0.266113f, -0.422852f, 0.274902f, -0.429199f, 0.279785f, -0.435059f, 0.291992f, -0.437988f,
-0.312012f, -0.441895f, 0.367188f, -0.440918f, 0.414062f, -0.441895f, 0.42334f, -0.441895f,
-0.436035f, -0.426758f, 0.437988f, -0.427246f, 0.439941f, -0.427734f, 0.441895f, -0.428223f,
-0.442871f, -0.428223f, 0.446777f, -0.428223f, 0.459961f, -0.420898f, 0.496094f, -0.402832f,
-0.505859f, -0.398926f, 0.508789f, -0.394043f, 0.51709f, -0.375f, 0.519531f, -0.371094f,
-0.525879f, -0.371094f, 0.531738f, -0.371094f, 0.539062f, -0.374023f, 0.553711f, -0.362793f,
-0.563965f, -0.345215f, 0.570801f, -0.333008f, 0.578857f, -0.301514f, 0.586914f, -0.27002f,
-0.586914f, -0.253906f, 0.586914f, -0.251953f, 0.583984f, -0.23584f, 0.583008f, -0.222168f,
-0.524902f, -0.245117f, 0.506836f, -0.254395f, 0.50293f, -0.26709f, 0.495117f, -0.290039f,
-0.470215f, -0.327148f, 0.467773f, -0.347168f, 0.460938f, -0.354004f, 0.435059f, -0.353027f,
-0.395996f, -0.378906f, 0.368164f, -0.381836f, 0.341797f, -0.391113f, 0.270996f, -0.390137f,
-0.259766f, -0.390137f, 0.246094f, -0.388184f, 0.206055f, -0.376953f, 0.186035f, -0.373047f,
-0.169922f, -0.366211f, 0.158203f, -0.362793f, 0.146973f, -0.358887f, 0.146973f, -0.333984f,
-0.146973f, -0.328125f, 0.132812f, -0.297852f, 0.132812f, -0.294922f, 0.132812f, -0.291992f,
-0.133789f, -0.291016f, 0.13623f, -0.287109f, 0.145996f, -0.283203f, 0.144043f, -0.258789f,
-0.145996f, -0.203125f, 0.145996f, -0.196777f, 0.137207f, -0.181152f, 0.147949f, -0.157227f,
-0.147949f, -0.140137f, 0.145996f, -0.0952148f, 0.14502f, -0.078125f, 0.15918f, -0.0708008f,
-0.184082f, -0.0600586f, 0.204102f, -0.0449219f, 0.209961f, -0.0532227f, 0.223145f,
--0.0478516f, 0.265137f, -0.0449219f, 0.300781f, -0.0307617f, 0.34082f, -0.0371094f,
-0.366211f, -0.0361328f, 0.384766f, -0.0439453f, 0.404785f, -0.0532227f, 0.429199f,
--0.0708008f, 0.448242f, -0.0830078f, 0.46582f, -0.10498f, 0.486816f, -0.120117f,
-0.504883f, -0.131836f, 0.506836f, -0.144043f, 0.508789f, -0.163086f, 0.520996f, -0.187012f,
-0.521484f, -0.187988f, 0.521729f, -0.188721f, 0.521973f, -0.189453f, 0.521973f, -0.189941f,
-0.52002f, -0.229004f, 0.519043f, -0.240234f, 0.405762f, -0.40918f, 0.405762f, -0.406738f,
-0.403809f, -0.404785f, 0.375977f, -0.382812f, 0.36084f, -0.367188f, 0.352051f, -0.36377f,
-0.338867f, -0.37207f, 0.330078f, -0.380859f, 0.300781f, -0.381836f, 0.272949f, -0.393066f,
-0.262207f, -0.395996f, 0.255859f, -0.385254f, 0.249023f, -0.382568f, 0.242188f, -0.379883f,
-0.221191f, -0.379883f, 0.205078f, -0.373047f, 0.192871f, -0.376953f, 0.183105f, -0.369141f,
-0.144043f, -0.338867f, 0.134277f, -0.326172f, 0.132812f, -0.291992f, 0.131836f, -0.254883f,
-0.121094f, -0.248047f, 0.130859f, -0.231445f, 0.130859f, -0.21582f, 0.138184f, -0.21582f,
-0.13916f, -0.202148f, 0.141113f, -0.13916f, 0.14209f, -0.105957f, 0.140137f, -0.0761719f,
-0.125f, -0.0673828f, 0.125f, -0.0620117f, 0.125f, -0.0610352f, 0.128906f, -0.0532227f,
-0.14209f, -0.0561523f, 0.141113f, -0.0517578f, 0.14502f, -0.0322266f, 0.14502f, -0.0297852f,
-0.14502f, -0.0224609f, 0.137207f, -0.0146484f, 0.129395f, -0.00683594f, 0.121094f,
--0.00585938f, 0.102051f, -0.00390625f, 0.0732422f, 0.0112305f, 0.0610352f, 0.00390625f,
-0.0629883f, -0.00585938f, 0.0698242f, -0.0341797f, 0.0668945f, -0.0717773f, 0.0698242f,
--0.0771484f, 0.0800781f, -0.0771484f, 0.0800781f, -0.0830078f, 0.0791016f, -0.0917969f,
-0.0732422f, -0.105957f, 0.0717773f, -0.125977f, 0.0678711f, -0.143066f, 0.0678711f,
--0.144043f, 0.0678711f, -0.157227f, 0.0688477f, -0.172852f, 0.0708008f, -0.175293f,
-0.072998f, -0.177979f, 0.0751953f, -0.180664f, 0.0788574f, -0.186035f, 0.0825195f,
--0.191406f, 0.0869141f, -0.199219f, 0.0917969f, -0.210938f, 0.0908203f, -0.21582f,
-0.0678711f, -0.21582f, 0.0678711f, -0.226074f, 0.0698242f, -0.263184f, 0.0668945f,
--0.299805f, 0.0683594f, -0.304688f, 0.0732422f, -0.309082f, 0.0732422f, -0.323242f,
-0.0668945f, -0.329102f, 0.0649414f, -0.34082f, 0.0639648f, -0.367188f, 0.0532227f,
--0.388184f, 0.0566406f, -0.405762f, 0.0688477f, -0.417969f, 0.0991211f, -0.434082f,
-0.117188f, -0.445801f, 0.130859f, -0.441895f, 0.135986f, -0.436523f, 0.141113f, -0.431152f,
-0.141113f, -0.418945f, 0.141113f, -0.416016f, 0.141113f, -0.402832f, 0.141113f, -0.384766f,
-0.148926f, -0.384766f, 0.150879f, -0.384766f, 0.175781f, -0.397949f, 0.200195f, -0.407227f,
-0.242188f, -0.430176f, 0.255859f, -0.436035f, 0.26709f, -0.433105f, 0.289062f, -0.439941f,
-0.308105f, -0.445801f, 0.317871f, -0.445801f, 0.338867f, -0.443848f, 0.348633f, -0.430176f,
-0.35498f, -0.430176f, 0.355957f, -0.430664f, 0.356445f, -0.430908f, 0.356934f, -0.431152f,
-0.35791f, -0.431152f, 0.369141f, -0.437012f, 0.373047f, -0.438965f, 0.375f, -0.438965f,
-0.387207f, -0.438965f, 0.397949f, -0.425781f, 0.405762f, -0.416504f, 0.405762f, -0.40918f,
-0.440918f, -0.143066f, 0.440918f, -0.123535f, 0.433838f, -0.110352f, 0.426758f, -0.097168f,
-0.416992f, -0.097168f, 0.415039f, -0.097168f, 0.407227f, -0.0991211f, 0.400879f,
--0.0878906f, 0.39209f, -0.0639648f, 0.370117f, -0.0400391f, 0.359863f, -0.0258789f,
-0.346191f, -0.0249023f, 0.300781f, -0.00195312f, 0.279785f, 0.000976562f, 0.244141f,
-0.0131836f, 0.21582f, 0.0078125f, 0.172852f, 0.0180664f, 0.168457f, 0.0180664f, 0.125f,
-0.00878906f, 0.104492f, 0.00439453f, 0.0991211f, 0, 0.0800781f, -0.012207f, 0.0561523f,
--0.0258789f, 0.0410156f, -0.0356445f, 0.0314941f, -0.0510254f, 0.0219727f, -0.0664062f,
-0.0219727f, -0.0791016f, 0.0219727f, -0.0869141f, 0.0385742f, -0.100342f, 0.0551758f,
--0.11377f, 0.0751953f, -0.123047f, 0.0859375f, -0.108887f, 0.0952148f, -0.065918f,
-0.112793f, -0.0551758f, 0.141113f, -0.0332031f, 0.154785f, -0.0288086f, 0.181152f,
--0.0161133f, 0.199219f, -0.0161133f, 0.210938f, -0.0141602f, 0.234863f, -0.0209961f,
-0.274902f, -0.0249023f, 0.294922f, -0.0351562f, 0.313965f, -0.0419922f, 0.332031f,
--0.0527344f, 0.349121f, -0.0861816f, 0.366211f, -0.119629f, 0.366211f, -0.146973f,
-0.366211f, -0.157227f, 0.359863f, -0.165039f, 0.34082f, -0.191895f, 0.335938f, -0.204102f,
-0.324219f, -0.209961f, 0.317871f, -0.202148f, 0.307129f, -0.203125f, 0.280762f, -0.207031f,
-0.25f, -0.207031f, 0.242188f, -0.207031f, 0.229004f, -0.226074f, 0.21875f, -0.214355f,
-0.212402f, -0.211182f, 0.206055f, -0.208008f, 0.187988f, -0.205078f, 0.170898f, -0.202148f,
-0.161133f, -0.207031f, 0.148926f, -0.207031f, 0.13623f, -0.216797f, 0.120117f, -0.213867f,
-0.10498f, -0.221191f, 0.0839844f, -0.228027f, 0.0717773f, -0.231934f, 0.0629883f,
--0.24707f, 0.0541992f, -0.262207f, 0.0541992f, -0.277832f, 0.0541992f, -0.301758f,
-0.0708008f, -0.328613f, 0.0874023f, -0.355469f, 0.117188f, -0.37793f, 0.140137f,
--0.395508f, 0.171875f, -0.412598f, 0.203613f, -0.429688f, 0.231689f, -0.438965f,
-0.259766f, -0.448242f, 0.277832f, -0.448242f, 0.283203f, -0.448242f, 0.314941f, -0.437988f,
-0.329102f, -0.433105f, 0.362305f, -0.438965f, 0.37207f, -0.438965f, 0.385742f, -0.438965f,
-0.393799f, -0.43457f, 0.401855f, -0.430176f, 0.401855f, -0.423828f, 0.401855f, -0.41748f,
-0.387939f, -0.406006f, 0.374023f, -0.394531f, 0.353027f, -0.384766f, 0.337891f, -0.37793f,
-0.325195f, -0.378906f, 0.300781f, -0.379883f, 0.282227f, -0.384766f, 0.273926f, -0.401855f,
-0.26709f, -0.401855f, 0.258789f, -0.393066f, 0.244141f, -0.393066f, 0.22998f, -0.393066f,
-0.209961f, -0.390137f, 0.194824f, -0.394043f, 0.187012f, -0.388184f, 0.155762f, -0.370117f,
-0.123047f, -0.341797f, 0.123047f, -0.318848f, 0.123047f, -0.302734f, 0.132812f, -0.297852f,
-0.165039f, -0.283203f, 0.174805f, -0.277832f, 0.174805f, -0.266113f, 0.189941f, -0.257812f,
-0.206055f, -0.272949f, 0.213867f, -0.271973f, 0.295898f, -0.277832f, 0.334961f, -0.269043f,
-0.353027f, -0.271973f, 0.375977f, -0.256836f, 0.410156f, -0.237793f, 0.42041f, -0.230957f,
-0.428223f, -0.207031f, 0.432129f, -0.193848f, 0.440918f, -0.163086f, 0.440918f, -0.143066f,
-0.504883f, -0.0297852f, 0.501465f, -0.0170898f, 0.490234f, -0.012207f, 0.434082f,
-0.012207f, 0.418945f, 0.00341797f, 0.418945f, -0.0161133f, 0.419922f, -0.0439453f,
-0.411133f, -0.0458984f, 0.378906f, -0.0307617f, 0.333984f, -0.00878906f, 0.315918f,
-0, 0.256836f, 0.0112305f, 0.237793f, 0.0170898f, 0.23291f, 0.0170898f, 0.228027f,
-0.0170898f, 0.226074f, 0.0161133f, 0.208008f, 0.00878906f, 0.186035f, 0.0151367f,
-0.166016f, -0.00195312f, 0.126953f, 0.00390625f, 0.121094f, 0.00146484f, 0.109863f,
--0.00488281f, 0.0986328f, -0.0112305f, 0.0908203f, -0.019043f, 0.0688477f, -0.043457f,
-0.0688477f, -0.0688477f, 0.0688477f, -0.0766602f, 0.0791016f, -0.0849609f, 0.0629883f,
--0.0908203f, 0.0620117f, -0.109863f, 0.0610352f, -0.13623f, 0.0610352f, -0.147949f,
-0.0649414f, -0.155762f, 0.0742188f, -0.172852f, 0.0649414f, -0.200195f, 0.065918f,
--0.229004f, 0.0649414f, -0.262207f, 0.0654297f, -0.265137f, 0.0751953f, -0.295898f,
-0.0751953f, -0.303223f, 0.065918f, -0.298828f, 0.0600586f, -0.305176f, 0.0600586f,
--0.314941f, 0.0610352f, -0.374023f, 0.0610352f, -0.387695f, 0.0581055f, -0.39502f,
-0.0541992f, -0.400879f, 0.0541992f, -0.401855f, 0.0539551f, -0.402588f, 0.0537109f,
--0.40332f, 0.0532227f, -0.403809f, 0.0532227f, -0.412109f, 0.0649414f, -0.418945f,
-0.0708008f, -0.421875f, 0.106934f, -0.437012f, 0.124512f, -0.443848f, 0.130859f,
--0.443848f, 0.138184f, -0.443848f, 0.144043f, -0.430176f, 0.148926f, -0.418945f,
-0.13916f, -0.391602f, 0.13916f, -0.368164f, 0.14209f, -0.339844f, 0.141113f, -0.328125f,
-0.132812f, -0.304199f, 0.132324f, -0.291016f, 0.131836f, -0.285889f, 0.131348f, -0.280762f,
-0.130859f, -0.276855f, 0.130859f, -0.269531f, 0.133789f, -0.262207f, 0.14209f, -0.248047f,
-0.130859f, -0.210938f, 0.134766f, -0.199219f, 0.130859f, -0.178223f, 0.126953f, -0.149902f,
-0.126953f, -0.145996f, 0.12793f, -0.144043f, 0.134766f, -0.131836f, 0.138184f, -0.0800781f,
-0.141113f, -0.065918f, 0.150635f, -0.0600586f, 0.160156f, -0.0541992f, 0.189941f,
--0.0449219f, 0.226074f, -0.0351562f, 0.23584f, -0.0332031f, 0.258789f, -0.0332031f,
-0.275391f, -0.0332031f, 0.283203f, -0.0361328f, 0.311035f, -0.046875f, 0.34082f,
--0.0390625f, 0.348633f, -0.0415039f, 0.351074f, -0.0551758f, 0.367188f, -0.0639648f,
-0.38916f, -0.0942383f, 0.407227f, -0.108887f, 0.414551f, -0.118652f, 0.416016f, -0.13623f,
-0.419922f, -0.186035f, 0.423828f, -0.196777f, 0.413086f, -0.208008f, 0.414062f, -0.226074f,
-0.416016f, -0.303223f, 0.413086f, -0.329102f, 0.408203f, -0.358887f, 0.408203f, -0.366211f,
-0.416992f, -0.375f, 0.415039f, -0.383789f, 0.407227f, -0.384766f, 0.404785f, -0.399902f,
-0.404785f, -0.403809f, 0.40918f, -0.418945f, 0.40918f, -0.429199f, 0.416992f, -0.426758f,
-0.471191f, -0.445801f, 0.47168f, -0.445801f, 0.472168f, -0.446289f, 0.472656f, -0.446777f,
-0.473145f, -0.446777f, 0.478516f, -0.446777f, 0.482178f, -0.437744f, 0.48584f, -0.428711f,
-0.48584f, -0.414062f, 0.481934f, -0.314941f, 0.475098f, -0.23877f, 0.461914f, -0.244141f,
-0.456055f, -0.230469f, 0.456055f, -0.225098f, 0.458984f, -0.214844f, 0.464844f, -0.216797f,
-0.467773f, -0.216797f, 0.472168f, -0.216797f, 0.475098f, -0.214355f, 0.478027f, -0.211914f,
-0.478027f, -0.208008f, 0.473145f, -0.116211f, 0.48291f, -0.0991211f, 0.487793f, -0.0517578f,
-0.490234f, -0.0488281f, 0.494385f, -0.0441895f, 0.498535f, -0.0395508f, 0.504883f,
--0.0297852f, 0.48584f, -0.103027f, 0.469238f, -0.0571289f, 0.469238f, -0.0551758f,
-0.471191f, -0.0478516f, 0.480957f, -0.0361328f, 0.477051f, -0.00976562f, 0.479004f,
-0.027832f, 0.474121f, 0.0400391f, 0.475098f, 0.0917969f, 0.467773f, 0.108887f, 0.462891f,
-0.132812f, 0.455078f, 0.148926f, 0.456055f, 0.173828f, 0.438965f, 0.21582f, 0.435059f,
-0.227051f, 0.420898f, 0.23584f, 0.383789f, 0.283203f, 0.361816f, 0.315918f, 0.349609f,
-0.334961f, 0.336914f, 0.34082f, 0.324219f, 0.348145f, 0.312012f, 0.36084f, 0.296875f,
-0.370117f, 0.288086f, 0.37793f, 0.26709f, 0.383789f, 0.266602f, 0.383789f, 0.23584f,
-0.397949f, 0.205078f, 0.40918f, 0.161133f, 0.421875f, 0.115234f, 0.416992f, 0.0908203f,
-0.414062f, 0.0732422f, 0.412598f, 0.0610352f, 0.405762f, 0.027832f, 0.384766f, 0.0112305f,
-0.380859f, -0.00195312f, 0.362793f, -0.027832f, 0.347168f, -0.0371094f, 0.339355f,
--0.0371094f, 0.319824f, -0.0371094f, 0.299316f, -0.0229492f, 0.280762f, -0.0185547f,
-0.275391f, -0.00390625f, 0.273926f, 0.00195312f, 0.288086f, 0.00683594f, 0.301758f,
-0.0258789f, 0.328125f, 0.0449219f, 0.35791f, 0.0551758f, 0.368164f, 0.0600586f, 0.368164f,
-0.0610352f, 0.368164f, 0.0678711f, 0.367188f, 0.108887f, 0.383789f, 0.143066f, 0.38623f,
-0.149414f, 0.391113f, 0.155762f, 0.391113f, 0.160645f, 0.391113f, 0.168945f, 0.384766f,
-0.180176f, 0.38623f, 0.200684f, 0.38623f, 0.23877f, 0.369141f, 0.272461f, 0.352539f,
-0.279785f, 0.344238f, 0.316895f, 0.306152f, 0.339844f, 0.291992f, 0.352539f, 0.282227f,
-0.36084f, 0.255859f, 0.373047f, 0.21582f, 0.391113f, 0.187988f, 0.388184f, 0.166992f,
-0.396973f, 0.12793f, 0.397949f, 0.0878906f, 0.397949f, 0.0673828f, 0.407227f, 0.046875f,
-0.415039f, 0.0200195f, 0.40918f, -0.00292969f, 0.403809f, -0.0708008f, 0.402832f,
--0.0820312f, 0.402832f, -0.0869141f, 0.411133f, -0.112793f, 0.405762f, -0.120117f,
-0.391113f, -0.112793f, 0.374023f, -0.103027f, 0.359863f, -0.0878906f, 0.312988f,
--0.0581055f, 0.289062f, -0.0351562f, 0.251953f, -0.0078125f, 0.236328f, 0.00292969f,
-0.228027f, 0.00585938f, 0.195801f, 0.0112305f, 0.178223f, 0.0180664f, 0.16748f, 0.0209961f,
-0.162109f, 0.0209961f, 0.143066f, 0.0209961f, 0.111328f, 0.00878906f, 0.0795898f,
--0.00341797f, 0.0678711f, -0.0161133f, 0.0488281f, -0.0351562f, 0.0488281f, -0.0649414f,
-0.0498047f, -0.0751953f, 0.0600586f, -0.0820312f, 0.0600586f, -0.0878906f, 0.0600586f,
--0.0888672f, 0.0598145f, -0.0895996f, 0.0595703f, -0.090332f, 0.059082f, -0.0908203f,
-0.0488281f, -0.10498f, 0.0478516f, -0.119141f, 0.0507812f, -0.131836f, 0.0698242f,
--0.175781f, 0.065918f, -0.192871f, 0.065918f, -0.199219f, 0.065918f, -0.20459f, 0.0698242f,
--0.223145f, 0.0791016f, -0.258789f, 0.0820312f, -0.271484f, 0.0839844f, -0.283203f,
-0.0849609f, -0.320801f, 0.0942383f, -0.358887f, 0.0942383f, -0.365723f, 0.0869141f,
--0.375977f, 0.0732422f, -0.37793f, 0.0717773f, -0.38623f, 0.0898438f, -0.407227f,
-0.101074f, -0.411133f, 0.118164f, -0.416016f, 0.166992f, -0.443848f, 0.169922f, -0.443848f,
-0.177246f, -0.443848f, 0.181641f, -0.437988f, 0.186035f, -0.432129f, 0.186035f, -0.422852f,
-0.186035f, -0.419922f, 0.170898f, -0.382812f, 0.164062f, -0.346191f, 0.151855f, -0.290039f,
-0.148926f, -0.256836f, 0.146484f, -0.249512f, 0.141113f, -0.248047f, 0.125977f, -0.244141f,
-0.118164f, -0.241211f, 0.118164f, -0.23291f, 0.118164f, -0.221191f, 0.138184f, -0.221191f,
-0.124023f, -0.120117f, 0.120117f, -0.0908203f, 0.123047f, -0.0830078f, 0.129883f,
--0.0742188f, 0.144043f, -0.0507812f, 0.171875f, -0.0400391f, 0.185059f, -0.0249023f,
-0.191895f, -0.0219727f, 0.195801f, -0.0219727f, 0.211914f, -0.0332031f, 0.258789f,
--0.0488281f, 0.278809f, -0.0629883f, 0.312988f, -0.0869141f, 0.345215f, -0.118164f,
-0.366211f, -0.130859f, 0.375f, -0.13623f, 0.393066f, -0.183105f, 0.395996f, -0.185059f,
-0.397949f, -0.193848f, 0.408203f, -0.206055f, 0.403809f, -0.23291f, 0.408203f, -0.240234f,
-0.405762f, -0.26123f, 0.40918f, -0.271973f, 0.400879f, -0.314941f, 0.396973f, -0.374023f,
-0.382812f, -0.402832f, 0.381836f, -0.404785f, 0.381836f, -0.40918f, 0.381836f, -0.416992f,
-0.402832f, -0.423828f, 0.417969f, -0.437988f, 0.446777f, -0.441895f, 0.458008f, -0.444824f,
-0.472168f, -0.435059f, 0.472168f, -0.428223f, 0.472168f, -0.425781f, 0.469238f, -0.408203f,
-0.471191f, -0.373047f, 0.466797f, -0.358887f, 0.466797f, -0.346191f, 0.460938f, -0.324219f,
-0.461914f, -0.316895f, 0.469238f, -0.299316f, 0.473145f, -0.290527f, 0.477051f, -0.281738f,
-0.477051f, -0.276855f, 0.477051f, -0.26416f, 0.479004f, -0.23291f, 0.472168f, -0.21582f,
-0.470215f, -0.209961f, 0.470215f, -0.207031f, 0.470215f, -0.193359f, 0.48584f, -0.179199f,
-0.484863f, -0.166992f
-};
-
-const unsigned char PapyruskNormalVerbs[] = {
-6, 0, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 2, 1, 1, 5, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1,
-2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1,
-1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2,
-2, 1, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2,
-2, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
-1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1,
-2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1,
-5, 6, 0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1,
-1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
-1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2,
-2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1,
-2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
-2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 5, 0, 2, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 5, 6, 0, 2, 1, 2, 2, 1, 1, 1, 1,
-1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1,
-1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 5, 6, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,
-1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1,
-1, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 5, 0, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 0, 1, 1, 1,
-1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 2, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1,
-2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2,
-1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2,
-1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 1, 2, 2,
-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2,
-2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 5, 0, 1, 1, 1, 1,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 5, 6, 0, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1,
-1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 5, 0, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 5, 6, 0, 2, 1, 1, 1, 1, 1,
-1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1,
-1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 5,
-6, 0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 5, 6, 0, 2, 1, 2, 1, 1, 1,
-1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1,
-1, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2,
-2, 1, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
-2, 2, 2, 2, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,
-2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1,
-1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
-1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 5, 6
-};
-
-const unsigned PapyruskNormalCharCodes[] = {
-32, 33, 72, 84, 97,
-99, 101, 102, 108, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed PapyruskNormalWidths[] = {
-0x00003a20, 0x000042e0, 0x0000c3e0, 0x0000b1e0, 0x00008940, 0x00007f80, 0x000087e0,
-0x000064a0, 0x00003860, 0x00008c80, 0x00009920, 0x00009d20, 0x000062e0, 0x000078e0,
-0x00008f20, 0x00008a40
-};
-
-const int PapyruskNormalCharCodesCount = (int) SK_ARRAY_COUNT(PapyruskNormalCharCodes);
-
-const SkPaint::FontMetrics PapyruskNormalMetrics = {
-0x00000003, -0.944824f, -0.939941f, 0.603027f, 0.603027f, 0, 2.51855f, 0, -0.5625f,
-1.95605f, 0.464355f, 0, 0.0673828f, 0.166504f
-};
-
-const SkScalar TimesNewRomankNormalPoints[] = {
-0.175781f, -0.175293f, 0.157227f, -0.175293f, 0.114258f, -0.570801f, 0.111328f, -0.59668f,
-0.111328f, -0.609375f, 0.111328f, -0.640137f, 0.127686f, -0.658691f, 0.144043f, -0.677246f,
-0.166992f, -0.677246f, 0.189941f, -0.677246f, 0.205811f, -0.658691f, 0.22168f, -0.640137f,
-0.22168f, -0.603516f, 0.22168f, -0.591797f, 0.219727f, -0.570801f, 0.166016f, -0.0942383f,
-0.188477f, -0.0942383f, 0.204346f, -0.0783691f, 0.220215f, -0.0625f, 0.220215f, -0.0405273f,
-0.220215f, -0.0180664f, 0.204346f, -0.00219727f, 0.188477f, 0.0136719f, 0.166016f,
-0.0136719f, 0.143555f, 0.0136719f, 0.127686f, -0.00219727f, 0.111816f, -0.0180664f,
-0.111816f, -0.0405273f, 0.111816f, -0.0625f, 0.127686f, -0.0783691f, 0.143555f, -0.0942383f,
-0.166016f, -0.0942383f, 0.28125f, -0.39209f, 0.254883f, -0.534668f, 0.244141f, -0.59375f,
-0.243164f, -0.605957f, 0.243164f, -0.618164f, 0.243164f, -0.648926f, 0.256836f, -0.663086f,
-0.270508f, -0.677246f, 0.292969f, -0.677246f, 0.313965f, -0.677246f, 0.327881f, -0.663086f,
-0.341797f, -0.648926f, 0.341797f, -0.625f, 0.341797f, -0.583496f, 0.33252f, -0.535156f,
-0.304688f, -0.39209f, 0.102539f, -0.39209f, 0.0756836f, -0.536621f, 0.0649414f, -0.596191f,
-0.0649414f, -0.617676f, 0.0649414f, -0.648926f, 0.0778809f, -0.663086f, 0.0908203f,
--0.677246f, 0.112793f, -0.677246f, 0.134277f, -0.677246f, 0.148438f, -0.662842f,
-0.162598f, -0.648438f, 0.162598f, -0.624512f, 0.162598f, -0.605469f, 0.149902f, -0.536133f,
-0.123535f, -0.39209f, 0.0561523f, 0.0136719f, 0.101562f, -0.208496f, 0.0180664f,
--0.208496f, 0.0180664f, -0.248535f, 0.109375f, -0.248535f, 0.143066f, -0.416016f,
-0.0180664f, -0.416016f, 0.0180664f, -0.455078f, 0.152344f, -0.455078f, 0.196777f,
--0.677246f, 0.237305f, -0.677246f, 0.192871f, -0.455078f, 0.357422f, -0.455078f,
-0.404785f, -0.677246f, 0.445312f, -0.677246f, 0.398926f, -0.455078f, 0.481934f, -0.455078f,
-0.481934f, -0.416016f, 0.391602f, -0.416016f, 0.357422f, -0.248535f, 0.481934f, -0.248535f,
-0.481934f, -0.208496f, 0.349121f, -0.208496f, 0.303711f, 0.0136719f, 0.26416f, 0.0136719f,
-0.308594f, -0.208496f, 0.143066f, -0.208496f, 0.0966797f, 0.0136719f, 0.150391f,
--0.248535f, 0.315918f, -0.248535f, 0.351074f, -0.416016f, 0.18457f, -0.416016f, 0.0527344f,
--0.163086f, 0.0742188f, -0.163086f, 0.0795898f, -0.0961914f, 0.116211f, -0.0605469f,
-0.152832f, -0.0249023f, 0.225586f, -0.0180664f, 0.225586f, -0.303223f, 0.115723f,
--0.371094f, 0.0791016f, -0.42334f, 0.0532227f, -0.460449f, 0.0532227f, -0.513672f,
-0.0532227f, -0.57373f, 0.0979004f, -0.618652f, 0.142578f, -0.663574f, 0.225586f,
--0.672852f, 0.225586f, -0.717773f, 0.256836f, -0.717773f, 0.256836f, -0.672852f,
-0.296875f, -0.67041f, 0.324219f, -0.663574f, 0.338379f, -0.660156f, 0.417969f, -0.629883f,
-0.417969f, -0.483887f, 0.398926f, -0.483887f, 0.392578f, -0.561523f, 0.358643f, -0.597412f,
-0.324707f, -0.633301f, 0.256836f, -0.640137f, 0.256836f, -0.39209f, 0.379883f, -0.306152f,
-0.414795f, -0.265381f, 0.449707f, -0.224609f, 0.449707f, -0.164062f, 0.449707f, -0.0966797f,
-0.398682f, -0.0454102f, 0.347656f, 0.00585938f, 0.256836f, 0.0136719f, 0.256836f,
-0.0761719f, 0.225586f, 0.0761719f, 0.225586f, 0.0136719f, 0.179688f, 0.0117188f,
-0.140137f, 0.00317383f, 0.100586f, -0.00537109f, 0.0527344f, -0.0249023f, 0.225586f,
--0.412598f, 0.225586f, -0.639648f, 0.176758f, -0.633789f, 0.153076f, -0.608643f,
-0.129395f, -0.583496f, 0.129395f, -0.54541f, 0.129395f, -0.509766f, 0.150879f, -0.47876f,
-0.172363f, -0.447754f, 0.225586f, -0.412598f, 0.256836f, -0.0180664f, 0.293457f,
--0.0244141f, 0.312988f, -0.0361328f, 0.340332f, -0.0532227f, 0.356201f, -0.0808105f,
-0.37207f, -0.108398f, 0.37207f, -0.139648f, 0.37207f, -0.171875f, 0.352783f, -0.200684f,
-0.333496f, -0.229492f, 0.256836f, -0.282227f, 0.679688f, -0.677246f, 0.197266f, 0.0273438f,
-0.153809f, 0.0273438f, 0.63623f, -0.677246f, 0.177734f, -0.677246f, 0.243652f, -0.677246f,
-0.280029f, -0.622559f, 0.316406f, -0.567871f, 0.316406f, -0.49707f, 0.316406f, -0.412109f,
-0.275391f, -0.365723f, 0.234375f, -0.319336f, 0.176758f, -0.319336f, 0.138184f, -0.319336f,
-0.105957f, -0.340576f, 0.0737305f, -0.361816f, 0.0544434f, -0.403809f, 0.0351562f,
--0.445801f, 0.0351562f, -0.49707f, 0.0351562f, -0.54834f, 0.0546875f, -0.591553f,
-0.0742188f, -0.634766f, 0.108154f, -0.656006f, 0.14209f, -0.677246f, 0.177734f, -0.677246f,
-0.17627f, -0.649902f, 0.151367f, -0.649902f, 0.13208f, -0.620605f, 0.112793f, -0.591309f,
-0.112793f, -0.497559f, 0.112793f, -0.429688f, 0.123535f, -0.394043f, 0.131836f, -0.367188f,
-0.149414f, -0.352539f, 0.159668f, -0.34375f, 0.174805f, -0.34375f, 0.198242f, -0.34375f,
-0.214844f, -0.369141f, 0.239258f, -0.406738f, 0.239258f, -0.494629f, 0.239258f, -0.587402f,
-0.215332f, -0.625f, 0.199707f, -0.649902f, 0.17627f, -0.649902f, 0.657227f, -0.328613f,
-0.691895f, -0.328613f, 0.726318f, -0.306641f, 0.760742f, -0.284668f, 0.779541f, -0.242676f,
-0.79834f, -0.200684f, 0.79834f, -0.150391f, 0.79834f, -0.0639648f, 0.756836f, -0.0183105f,
-0.715332f, 0.0273438f, 0.658691f, 0.0273438f, 0.623047f, 0.0273438f, 0.5896f, 0.00537109f,
-0.556152f, -0.0166016f, 0.536865f, -0.057373f, 0.517578f, -0.0981445f, 0.517578f,
--0.150391f, 0.517578f, -0.20166f, 0.536865f, -0.244141f, 0.556152f, -0.286621f, 0.5896f,
--0.307617f, 0.623047f, -0.328613f, 0.657227f, -0.328613f, 0.657715f, -0.302734f,
-0.634277f, -0.302734f, 0.617188f, -0.276367f, 0.595215f, -0.242188f, 0.595215f, -0.146973f,
-0.595215f, -0.0595703f, 0.617676f, -0.0249023f, 0.634277f, 0, 0.657715f, 0, 0.680176f,
-0, 0.697754f, -0.0268555f, 0.721191f, -0.0625f, 0.721191f, -0.149414f, 0.721191f,
--0.241211f, 0.697754f, -0.277832f, 0.681641f, -0.302734f, 0.657715f, -0.302734f,
-0.510254f, -0.42627f, 0.715332f, -0.42627f, 0.715332f, -0.408203f, 0.672852f, -0.404785f,
-0.652588f, -0.389404f, 0.632324f, -0.374023f, 0.589355f, -0.296387f, 0.546387f, -0.21875f,
-0.492676f, -0.151367f, 0.536133f, -0.100586f, 0.570312f, -0.0803223f, 0.604492f,
--0.0600586f, 0.63916f, -0.0600586f, 0.672852f, -0.0600586f, 0.696289f, -0.0783691f,
-0.719727f, -0.0966797f, 0.729492f, -0.132324f, 0.747559f, -0.119141f, 0.729492f,
--0.050293f, 0.689453f, -0.0175781f, 0.649414f, 0.0151367f, 0.596191f, 0.0151367f,
-0.556152f, 0.0151367f, 0.514893f, -0.0065918f, 0.473633f, -0.0283203f, 0.424805f,
--0.0800781f, 0.364258f, -0.0263672f, 0.315674f, -0.00561523f, 0.26709f, 0.0151367f,
-0.211914f, 0.0151367f, 0.131348f, 0.0151367f, 0.0839844f, -0.027832f, 0.0366211f,
--0.0708008f, 0.0366211f, -0.130371f, 0.0366211f, -0.189453f, 0.0791016f, -0.248291f,
-0.121582f, -0.307129f, 0.23877f, -0.370117f, 0.21582f, -0.420898f, 0.20752f, -0.453369f,
-0.199219f, -0.48584f, 0.199219f, -0.515625f, 0.199219f, -0.599121f, 0.260742f, -0.643066f,
-0.308594f, -0.677246f, 0.369629f, -0.677246f, 0.427734f, -0.677246f, 0.464355f, -0.642822f,
-0.500977f, -0.608398f, 0.500977f, -0.558105f, 0.500977f, -0.506348f, 0.465576f, -0.467285f,
-0.430176f, -0.428223f, 0.340332f, -0.381836f, 0.402344f, -0.271484f, 0.469727f, -0.179688f,
-0.555664f, -0.282227f, 0.555664f, -0.352539f, 0.555664f, -0.375f, 0.541016f, -0.392578f,
-0.530273f, -0.405762f, 0.510254f, -0.408203f, 0.32373f, -0.413574f, 0.384277f, -0.442383f,
-0.414307f, -0.479004f, 0.444336f, -0.515625f, 0.444336f, -0.560547f, 0.444336f, -0.595703f,
-0.422607f, -0.618652f, 0.400879f, -0.641602f, 0.368652f, -0.641602f, 0.326172f, -0.641602f,
-0.304443f, -0.612061f, 0.282715f, -0.58252f, 0.282715f, -0.554199f, 0.282715f, -0.530273f,
-0.291016f, -0.500732f, 0.299316f, -0.471191f, 0.32373f, -0.413574f, 0.399414f, -0.108398f,
-0.334961f, -0.196289f, 0.310059f, -0.236816f, 0.285156f, -0.277344f, 0.255371f, -0.337402f,
-0.196777f, -0.303711f, 0.167236f, -0.263184f, 0.137695f, -0.222656f, 0.137695f, -0.175293f,
-0.137695f, -0.123047f, 0.171387f, -0.0834961f, 0.205078f, -0.0439453f, 0.262207f,
--0.0439453f, 0.292969f, -0.0439453f, 0.321533f, -0.0561523f, 0.350098f, -0.0683594f,
-0.399414f, -0.108398f, 0.0771484f, -0.39209f, 0.0507812f, -0.536621f, 0.0395508f,
--0.59668f, 0.0395508f, -0.617676f, 0.0395508f, -0.648926f, 0.0522461f, -0.663086f,
-0.0649414f, -0.677246f, 0.0869141f, -0.677246f, 0.108887f, -0.677246f, 0.123291f,
--0.662842f, 0.137695f, -0.648438f, 0.137695f, -0.625f, 0.137695f, -0.606934f, 0.125f,
--0.536133f, 0.0986328f, -0.39209f, 0.310547f, 0.195801f, 0.310547f, 0.213867f, 0.236816f,
-0.176758f, 0.1875f, 0.126953f, 0.117188f, 0.0561523f, 0.0791016f, -0.0400391f, 0.0410156f,
--0.13623f, 0.0410156f, -0.239746f, 0.0410156f, -0.391113f, 0.115723f, -0.515869f,
-0.19043f, -0.640625f, 0.310547f, -0.694336f, 0.310547f, -0.673828f, 0.250488f, -0.640625f,
-0.211914f, -0.583008f, 0.17334f, -0.525391f, 0.154297f, -0.437012f, 0.135254f, -0.348633f,
-0.135254f, -0.252441f, 0.135254f, -0.147949f, 0.151367f, -0.0625f, 0.164062f, 0.00488281f,
-0.182129f, 0.0456543f, 0.200195f, 0.0864258f, 0.230713f, 0.124023f, 0.26123f, 0.161621f,
-0.310547f, 0.195801f, 0.0224609f, -0.673828f, 0.0224609f, -0.694336f, 0.0966797f,
--0.657715f, 0.145996f, -0.60791f, 0.21582f, -0.536621f, 0.253906f, -0.440674f, 0.291992f,
--0.344727f, 0.291992f, -0.240723f, 0.291992f, -0.0893555f, 0.217529f, 0.0354004f,
-0.143066f, 0.160156f, 0.0224609f, 0.213867f, 0.0224609f, 0.195801f, 0.0825195f, 0.162109f,
-0.121338f, 0.104736f, 0.160156f, 0.0473633f, 0.178955f, -0.0412598f, 0.197754f, -0.129883f,
-0.197754f, -0.226074f, 0.197754f, -0.330078f, 0.181641f, -0.416016f, 0.169434f, -0.483398f,
-0.151123f, -0.523926f, 0.132812f, -0.564453f, 0.102539f, -0.602051f, 0.0722656f,
--0.639648f, 0.0224609f, -0.673828f, 0.241211f, -0.509766f, 0.239258f, -0.543457f,
-0.227539f, -0.57666f, 0.210938f, -0.624512f, 0.210938f, -0.642578f, 0.210938f, -0.667969f,
-0.2229f, -0.681152f, 0.234863f, -0.694336f, 0.252441f, -0.694336f, 0.267578f, -0.694336f,
-0.278809f, -0.681152f, 0.290039f, -0.667969f, 0.290039f, -0.643555f, 0.290039f, -0.621582f,
-0.2771f, -0.582275f, 0.26416f, -0.542969f, 0.26123f, -0.509766f, 0.288086f, -0.526855f,
-0.30957f, -0.55127f, 0.342773f, -0.589844f, 0.358887f, -0.599121f, 0.375f, -0.608398f,
-0.391602f, -0.608398f, 0.407715f, -0.608398f, 0.418701f, -0.597412f, 0.429688f, -0.586426f,
-0.429688f, -0.571289f, 0.429688f, -0.553223f, 0.413574f, -0.539062f, 0.397461f, -0.524902f,
-0.333008f, -0.510742f, 0.29541f, -0.502441f, 0.270508f, -0.491699f, 0.295898f, -0.478516f,
-0.33252f, -0.47168f, 0.391602f, -0.460938f, 0.409912f, -0.444824f, 0.428223f, -0.428711f,
-0.428223f, -0.409668f, 0.428223f, -0.39502f, 0.417236f, -0.384277f, 0.40625f, -0.373535f,
-0.391602f, -0.373535f, 0.376953f, -0.373535f, 0.359131f, -0.383789f, 0.341309f, -0.394043f,
-0.311035f, -0.429688f, 0.291016f, -0.453613f, 0.26123f, -0.474609f, 0.262207f, -0.446777f,
-0.272461f, -0.414062f, 0.290039f, -0.356445f, 0.290039f, -0.335449f, 0.290039f, -0.315918f,
-0.27832f, -0.30249f, 0.266602f, -0.289062f, 0.253418f, -0.289062f, 0.235352f, -0.289062f,
-0.220703f, -0.303223f, 0.210449f, -0.313477f, 0.210449f, -0.335938f, 0.210449f, -0.359375f,
-0.22168f, -0.392334f, 0.23291f, -0.425293f, 0.23584f, -0.437744f, 0.23877f, -0.450195f,
-0.241211f, -0.474609f, 0.212402f, -0.455566f, 0.190918f, -0.432129f, 0.155273f, -0.39209f,
-0.137207f, -0.381348f, 0.124512f, -0.373535f, 0.11084f, -0.373535f, 0.0942383f, -0.373535f,
-0.0825195f, -0.384766f, 0.0708008f, -0.395996f, 0.0708008f, -0.409668f, 0.0708008f,
--0.421875f, 0.0808105f, -0.435303f, 0.0908203f, -0.44873f, 0.11084f, -0.45752f, 0.124023f,
--0.463379f, 0.170898f, -0.473145f, 0.201172f, -0.479492f, 0.22998f, -0.491699f, 0.203613f,
--0.504883f, 0.166992f, -0.512207f, 0.106934f, -0.524902f, 0.0927734f, -0.535156f,
-0.0708008f, -0.55127f, 0.0708008f, -0.574219f, 0.0708008f, -0.587402f, 0.0817871f,
--0.598389f, 0.0927734f, -0.609375f, 0.107422f, -0.609375f, 0.123535f, -0.609375f,
-0.141602f, -0.599121f, 0.159668f, -0.588867f, 0.186523f, -0.557861f, 0.213379f, -0.526855f,
-0.241211f, -0.509766f, 0.26123f, -0.0688477f, 0.26123f, -0.3125f, 0.0180664f, -0.3125f,
-0.0180664f, -0.352539f, 0.26123f, -0.352539f, 0.26123f, -0.595215f, 0.300293f, -0.595215f,
-0.300293f, -0.352539f, 0.544434f, -0.352539f, 0.544434f, -0.3125f, 0.300293f, -0.3125f,
-0.300293f, -0.0688477f, 0.0537109f, 0.166504f, 0.0537109f, 0.14502f, 0.104004f, 0.128418f,
-0.131592f, 0.0935059f, 0.15918f, 0.0585938f, 0.15918f, 0.0195312f, 0.15918f, 0.0102539f,
-0.154785f, 0.00390625f, 0.151367f, -0.000488281f, 0.147949f, -0.000488281f, 0.142578f,
--0.000488281f, 0.124512f, 0.00927734f, 0.115723f, 0.0136719f, 0.105957f, 0.0136719f,
-0.0820312f, 0.0136719f, 0.0678711f, -0.000488281f, 0.0537109f, -0.0146484f, 0.0537109f,
--0.0395508f, 0.0537109f, -0.0634766f, 0.0720215f, -0.0805664f, 0.090332f, -0.0976562f,
-0.116699f, -0.0976562f, 0.148926f, -0.0976562f, 0.174072f, -0.0695801f, 0.199219f,
--0.0415039f, 0.199219f, 0.00488281f, 0.199219f, 0.0551758f, 0.164307f, 0.0983887f,
-0.129395f, 0.141602f, 0.0537109f, 0.166504f, 0.0405273f, -0.26123f, 0.292969f, -0.26123f,
-0.292969f, -0.1875f, 0.0405273f, -0.1875f, 0.125f, -0.0947266f, 0.147949f, -0.0947266f,
-0.163574f, -0.0788574f, 0.179199f, -0.0629883f, 0.179199f, -0.0405273f, 0.179199f,
--0.0180664f, 0.16333f, -0.00219727f, 0.147461f, 0.0136719f, 0.125f, 0.0136719f, 0.102539f,
-0.0136719f, 0.0866699f, -0.00219727f, 0.0708008f, -0.0180664f, 0.0708008f, -0.0405273f,
-0.0708008f, -0.0634766f, 0.0866699f, -0.0791016f, 0.102539f, -0.0947266f, 0.125f,
--0.0947266f, 0.280273f, -0.694336f, 0.0405273f, 0.0136719f, 0.00146484f, 0.0136719f,
-0.241211f, -0.694336f, 0.117188f, -0.597168f, 0.27832f, -0.675781f, 0.294434f, -0.675781f,
-0.294434f, -0.116699f, 0.294434f, -0.0610352f, 0.299072f, -0.0473633f, 0.303711f,
--0.0336914f, 0.318359f, -0.0263672f, 0.333008f, -0.019043f, 0.37793f, -0.0180664f,
-0.37793f, 0, 0.128906f, 0, 0.128906f, -0.0180664f, 0.175781f, -0.019043f, 0.189453f,
--0.026123f, 0.203125f, -0.0332031f, 0.208496f, -0.045166f, 0.213867f, -0.0571289f,
-0.213867f, -0.116699f, 0.213867f, -0.474121f, 0.213867f, -0.546387f, 0.208984f, -0.566895f,
-0.205566f, -0.58252f, 0.196533f, -0.589844f, 0.1875f, -0.597168f, 0.174805f, -0.597168f,
-0.156738f, -0.597168f, 0.124512f, -0.582031f, 0.458496f, -0.127441f, 0.412109f, 0,
-0.0214844f, 0, 0.0214844f, -0.0180664f, 0.193848f, -0.175293f, 0.26416f, -0.274902f,
-0.334473f, -0.374512f, 0.334473f, -0.457031f, 0.334473f, -0.52002f, 0.295898f, -0.560547f,
-0.257324f, -0.601074f, 0.203613f, -0.601074f, 0.154785f, -0.601074f, 0.115967f, -0.57251f,
-0.0771484f, -0.543945f, 0.0585938f, -0.48877f, 0.0405273f, -0.48877f, 0.0527344f,
--0.579102f, 0.103271f, -0.627441f, 0.153809f, -0.675781f, 0.229492f, -0.675781f,
-0.310059f, -0.675781f, 0.364014f, -0.624023f, 0.417969f, -0.572266f, 0.417969f, -0.501953f,
-0.417969f, -0.45166f, 0.394531f, -0.401367f, 0.358398f, -0.322266f, 0.277344f, -0.233887f,
-0.155762f, -0.101074f, 0.125488f, -0.0737305f, 0.29834f, -0.0737305f, 0.351074f,
--0.0737305f, 0.372314f, -0.0776367f, 0.393555f, -0.081543f, 0.410645f, -0.0935059f,
-0.427734f, -0.105469f, 0.44043f, -0.127441f, 0.0507812f, -0.536133f, 0.0791016f,
--0.603027f, 0.122314f, -0.639404f, 0.165527f, -0.675781f, 0.22998f, -0.675781f, 0.30957f,
--0.675781f, 0.352051f, -0.624023f, 0.384277f, -0.585449f, 0.384277f, -0.541504f,
-0.384277f, -0.469238f, 0.293457f, -0.39209f, 0.354492f, -0.368164f, 0.385742f, -0.32373f,
-0.416992f, -0.279297f, 0.416992f, -0.219238f, 0.416992f, -0.133301f, 0.362305f, -0.0703125f,
-0.291016f, 0.0117188f, 0.155762f, 0.0117188f, 0.0888672f, 0.0117188f, 0.0646973f,
--0.00488281f, 0.0405273f, -0.0214844f, 0.0405273f, -0.0405273f, 0.0405273f, -0.0546875f,
-0.052002f, -0.0654297f, 0.0634766f, -0.0761719f, 0.0795898f, -0.0761719f, 0.0917969f,
--0.0761719f, 0.104492f, -0.0722656f, 0.112793f, -0.0698242f, 0.14209f, -0.0544434f,
-0.171387f, -0.0390625f, 0.182617f, -0.0361328f, 0.200684f, -0.0307617f, 0.221191f,
--0.0307617f, 0.270996f, -0.0307617f, 0.307861f, -0.0693359f, 0.344727f, -0.10791f,
-0.344727f, -0.160645f, 0.344727f, -0.199219f, 0.327637f, -0.23584f, 0.314941f, -0.263184f,
-0.299805f, -0.277344f, 0.278809f, -0.296875f, 0.242188f, -0.312744f, 0.205566f, -0.328613f,
-0.16748f, -0.328613f, 0.151855f, -0.328613f, 0.151855f, -0.343262f, 0.19043f, -0.348145f,
-0.229248f, -0.371094f, 0.268066f, -0.394043f, 0.285645f, -0.42627f, 0.303223f, -0.458496f,
-0.303223f, -0.49707f, 0.303223f, -0.547363f, 0.271729f, -0.578369f, 0.240234f, -0.609375f,
-0.193359f, -0.609375f, 0.117676f, -0.609375f, 0.0668945f, -0.52832f, 0.465332f, -0.244141f,
-0.465332f, -0.174805f, 0.376465f, -0.174805f, 0.376465f, 0, 0.295898f, 0, 0.295898f,
--0.174805f, 0.015625f, -0.174805f, 0.015625f, -0.237305f, 0.322754f, -0.675781f,
-0.376465f, -0.675781f, 0.376465f, -0.244141f, 0.295898f, -0.244141f, 0.295898f, -0.572754f,
-0.0634766f, -0.244141f, 0.434082f, -0.662109f, 0.395996f, -0.579102f, 0.196777f,
--0.579102f, 0.15332f, -0.490234f, 0.282715f, -0.471191f, 0.358398f, -0.394043f, 0.42334f,
--0.327637f, 0.42334f, -0.237793f, 0.42334f, -0.185547f, 0.4021f, -0.141113f, 0.380859f,
--0.0966797f, 0.348633f, -0.0654297f, 0.316406f, -0.0341797f, 0.276855f, -0.0151367f,
-0.220703f, 0.0117188f, 0.161621f, 0.0117188f, 0.102051f, 0.0117188f, 0.0749512f,
--0.00854492f, 0.0478516f, -0.0288086f, 0.0478516f, -0.0532227f, 0.0478516f, -0.0668945f,
-0.059082f, -0.0773926f, 0.0703125f, -0.0878906f, 0.0874023f, -0.0878906f, 0.100098f,
--0.0878906f, 0.109619f, -0.0839844f, 0.119141f, -0.0800781f, 0.14209f, -0.0639648f,
-0.178711f, -0.0385742f, 0.216309f, -0.0385742f, 0.273438f, -0.0385742f, 0.31665f,
--0.0817871f, 0.359863f, -0.125f, 0.359863f, -0.187012f, 0.359863f, -0.24707f, 0.321289f,
--0.299072f, 0.282715f, -0.351074f, 0.214844f, -0.379395f, 0.161621f, -0.401367f,
-0.0698242f, -0.404785f, 0.196777f, -0.662109f, 0.448242f, -0.675781f, 0.448242f,
--0.657715f, 0.383789f, -0.651367f, 0.343018f, -0.63208f, 0.302246f, -0.612793f, 0.262451f,
--0.573242f, 0.222656f, -0.533691f, 0.196533f, -0.485107f, 0.17041f, -0.436523f, 0.152832f,
--0.369629f, 0.223145f, -0.417969f, 0.293945f, -0.417969f, 0.361816f, -0.417969f,
-0.411621f, -0.363281f, 0.461426f, -0.308594f, 0.461426f, -0.222656f, 0.461426f, -0.139648f,
-0.411133f, -0.0712891f, 0.350586f, 0.0117188f, 0.250977f, 0.0117188f, 0.183105f,
-0.0117188f, 0.135742f, -0.0332031f, 0.0429688f, -0.120605f, 0.0429688f, -0.259766f,
-0.0429688f, -0.348633f, 0.0786133f, -0.428711f, 0.114258f, -0.508789f, 0.18042f,
--0.570801f, 0.246582f, -0.632812f, 0.307129f, -0.654297f, 0.367676f, -0.675781f,
-0.419922f, -0.675781f, 0.144531f, -0.333984f, 0.135742f, -0.268066f, 0.135742f, -0.227539f,
-0.135742f, -0.180664f, 0.153076f, -0.125732f, 0.17041f, -0.0708008f, 0.20459f, -0.0385742f,
-0.229492f, -0.015625f, 0.265137f, -0.015625f, 0.307617f, -0.015625f, 0.341064f, -0.0556641f,
-0.374512f, -0.0957031f, 0.374512f, -0.169922f, 0.374512f, -0.253418f, 0.341309f,
--0.314453f, 0.308105f, -0.375488f, 0.24707f, -0.375488f, 0.228516f, -0.375488f, 0.207275f,
--0.367676f, 0.186035f, -0.359863f, 0.144531f, -0.333984f, 0.100586f, -0.662109f,
-0.455566f, -0.662109f, 0.455566f, -0.643555f, 0.234863f, 0.0136719f, 0.180176f, 0.0136719f,
-0.37793f, -0.58252f, 0.195801f, -0.58252f, 0.140625f, -0.58252f, 0.117188f, -0.569336f,
-0.0761719f, -0.546875f, 0.0512695f, -0.5f, 0.0371094f, -0.505371f, 0.191895f, -0.333496f,
-0.113281f, -0.397949f, 0.0905762f, -0.437012f, 0.0678711f, -0.476074f, 0.0678711f,
--0.518066f, 0.0678711f, -0.58252f, 0.117676f, -0.62915f, 0.16748f, -0.675781f, 0.25f,
--0.675781f, 0.330078f, -0.675781f, 0.378906f, -0.632324f, 0.427734f, -0.588867f,
-0.427734f, -0.533203f, 0.427734f, -0.496094f, 0.401367f, -0.45752f, 0.375f, -0.418945f,
-0.291504f, -0.366699f, 0.377441f, -0.300293f, 0.405273f, -0.262207f, 0.442383f, -0.212402f,
-0.442383f, -0.157227f, 0.442383f, -0.0874023f, 0.38916f, -0.0378418f, 0.335938f,
-0.0117188f, 0.249512f, 0.0117188f, 0.155273f, 0.0117188f, 0.102539f, -0.0473633f,
-0.0605469f, -0.0947266f, 0.0605469f, -0.150879f, 0.0605469f, -0.194824f, 0.0900879f,
--0.238037f, 0.119629f, -0.28125f, 0.191895f, -0.333496f, 0.268555f, -0.385742f, 0.327148f,
--0.438477f, 0.342773f, -0.468994f, 0.358398f, -0.499512f, 0.358398f, -0.538086f,
-0.358398f, -0.589355f, 0.32959f, -0.618408f, 0.300781f, -0.647461f, 0.250977f, -0.647461f,
-0.201172f, -0.647461f, 0.169922f, -0.618652f, 0.138672f, -0.589844f, 0.138672f, -0.55127f,
-0.138672f, -0.525879f, 0.151611f, -0.500488f, 0.164551f, -0.475098f, 0.188477f, -0.452148f,
-0.214844f, -0.314941f, 0.174316f, -0.280762f, 0.154785f, -0.240479f, 0.135254f, -0.200195f,
-0.135254f, -0.15332f, 0.135254f, -0.090332f, 0.169678f, -0.0524902f, 0.204102f, -0.0146484f,
-0.257324f, -0.0146484f, 0.310059f, -0.0146484f, 0.341797f, -0.0444336f, 0.373535f,
--0.0742188f, 0.373535f, -0.116699f, 0.373535f, -0.151855f, 0.35498f, -0.179688f,
-0.320312f, -0.231445f, 0.214844f, -0.314941f, 0.0527344f, 0.0136719f, 0.0527344f,
--0.00439453f, 0.116211f, -0.00537109f, 0.170898f, -0.0339355f, 0.225586f, -0.0625f,
-0.276611f, -0.133789f, 0.327637f, -0.205078f, 0.347656f, -0.290527f, 0.270996f, -0.241211f,
-0.208984f, -0.241211f, 0.13916f, -0.241211f, 0.0893555f, -0.295166f, 0.0395508f,
--0.349121f, 0.0395508f, -0.438477f, 0.0395508f, -0.525391f, 0.0893555f, -0.593262f,
-0.149414f, -0.675781f, 0.246094f, -0.675781f, 0.327637f, -0.675781f, 0.385742f, -0.608398f,
-0.457031f, -0.524902f, 0.457031f, -0.402344f, 0.457031f, -0.291992f, 0.402832f, -0.196533f,
-0.348633f, -0.101074f, 0.251953f, -0.0380859f, 0.17334f, 0.0136719f, 0.0805664f,
-0.0136719f, 0.355469f, -0.32666f, 0.364258f, -0.390137f, 0.364258f, -0.428223f, 0.364258f,
--0.475586f, 0.348145f, -0.530518f, 0.332031f, -0.585449f, 0.30249f, -0.614746f, 0.272949f,
--0.644043f, 0.235352f, -0.644043f, 0.191895f, -0.644043f, 0.15918f, -0.60498f, 0.126465f,
--0.565918f, 0.126465f, -0.48877f, 0.126465f, -0.385742f, 0.169922f, -0.327637f, 0.20166f,
--0.285645f, 0.248047f, -0.285645f, 0.270508f, -0.285645f, 0.30127f, -0.296387f, 0.332031f,
--0.307129f, 0.355469f, -0.32666f, 0.137695f, -0.461426f, 0.160156f, -0.461426f, 0.176025f,
--0.445801f, 0.191895f, -0.430176f, 0.191895f, -0.407715f, 0.191895f, -0.385254f,
-0.176025f, -0.369385f, 0.160156f, -0.353516f, 0.137695f, -0.353516f, 0.115234f, -0.353516f,
-0.0993652f, -0.369385f, 0.0834961f, -0.385254f, 0.0834961f, -0.407715f, 0.0834961f,
--0.430176f, 0.0993652f, -0.445801f, 0.115234f, -0.461426f, 0.137695f, -0.461426f,
-0.0693359f, 0.166504f, 0.0693359f, 0.14502f, 0.119629f, 0.128418f, 0.147217f, 0.0935059f,
-0.174805f, 0.0585938f, 0.174805f, 0.0195312f, 0.174805f, 0.0102539f, 0.17041f, 0.00390625f,
-0.166992f, -0.000488281f, 0.163574f, -0.000488281f, 0.158203f, -0.000488281f, 0.140137f,
-0.00927734f, 0.131348f, 0.0136719f, 0.121582f, 0.0136719f, 0.0976562f, 0.0136719f,
-0.0834961f, -0.000488281f, 0.0693359f, -0.0146484f, 0.0693359f, -0.0395508f, 0.0693359f,
--0.0634766f, 0.0876465f, -0.0805664f, 0.105957f, -0.0976562f, 0.132324f, -0.0976562f,
-0.164551f, -0.0976562f, 0.189697f, -0.0695801f, 0.214844f, -0.0415039f, 0.214844f,
-0.00488281f, 0.214844f, 0.0551758f, 0.179932f, 0.0983887f, 0.14502f, 0.141602f, 0.0693359f,
-0.166504f, 0.0180664f, -0.344727f, 0.543457f, -0.572266f, 0.543457f, -0.529785f,
-0.0913086f, -0.333496f, 0.543457f, -0.135254f, 0.543457f, -0.0913086f, 0.0180664f,
--0.320801f, 0.0180664f, -0.431152f, 0.544922f, -0.431152f, 0.544922f, -0.391113f,
-0.0180664f, -0.391113f, 0.0180664f, -0.271973f, 0.544922f, -0.271973f, 0.544922f,
--0.231934f, 0.0180664f, -0.231934f, 0.543457f, -0.318848f, 0.0180664f, -0.0913086f,
-0.0180664f, -0.133301f, 0.470703f, -0.32959f, 0.0180664f, -0.527832f, 0.0180664f,
--0.572266f, 0.543457f, -0.342773f, 0.22168f, -0.15625f, 0.20166f, -0.15625f, 0.205078f,
--0.217773f, 0.217041f, -0.258057f, 0.229004f, -0.29834f, 0.266602f, -0.370117f, 0.295898f,
--0.425293f, 0.304688f, -0.454834f, 0.313477f, -0.484375f, 0.313477f, -0.514648f,
-0.313477f, -0.57666f, 0.280518f, -0.613281f, 0.247559f, -0.649902f, 0.199707f, -0.649902f,
-0.157227f, -0.649902f, 0.132812f, -0.629883f, 0.108398f, -0.609863f, 0.108398f, -0.586426f,
-0.108398f, -0.568359f, 0.123047f, -0.541992f, 0.137695f, -0.515625f, 0.137695f, -0.501953f,
-0.137695f, -0.484375f, 0.126465f, -0.472412f, 0.115234f, -0.460449f, 0.0991211f,
--0.460449f, 0.0786133f, -0.460449f, 0.0617676f, -0.480713f, 0.0449219f, -0.500977f,
-0.0449219f, -0.537109f, 0.0449219f, -0.592285f, 0.0922852f, -0.634766f, 0.139648f,
--0.677246f, 0.220703f, -0.677246f, 0.321289f, -0.677246f, 0.368652f, -0.618652f,
-0.403809f, -0.575684f, 0.403809f, -0.523438f, 0.403809f, -0.487793f, 0.387939f, -0.450195f,
-0.37207f, -0.412598f, 0.327637f, -0.361816f, 0.256836f, -0.281738f, 0.240967f, -0.248291f,
-0.225098f, -0.214844f, 0.22168f, -0.15625f, 0.214844f, -0.0957031f, 0.237793f, -0.0957031f,
-0.253662f, -0.079834f, 0.269531f, -0.0639648f, 0.269531f, -0.0410156f, 0.269531f,
--0.0185547f, 0.253418f, -0.00268555f, 0.237305f, 0.0131836f, 0.214844f, 0.0131836f,
-0.192383f, 0.0131836f, 0.176514f, -0.00268555f, 0.160645f, -0.0185547f, 0.160645f,
--0.0410156f, 0.160645f, -0.0639648f, 0.176514f, -0.079834f, 0.192383f, -0.0957031f,
-0.214844f, -0.0957031f, 0.6875f, -0.467773f, 0.630371f, -0.272949f, 0.598633f, -0.163574f,
-0.591797f, -0.134277f, 0.584961f, -0.10498f, 0.584961f, -0.0874023f, 0.584961f, -0.0717773f,
-0.595459f, -0.0610352f, 0.605957f, -0.050293f, 0.621582f, -0.050293f, 0.657227f,
--0.050293f, 0.707275f, -0.0859375f, 0.757324f, -0.121582f, 0.792969f, -0.20166f,
-0.828613f, -0.281738f, 0.828613f, -0.368652f, 0.828613f, -0.452148f, 0.78833f, -0.522949f,
-0.748047f, -0.59375f, 0.674561f, -0.631592f, 0.601074f, -0.669434f, 0.512207f, -0.669434f,
-0.399414f, -0.669434f, 0.302734f, -0.609619f, 0.206055f, -0.549805f, 0.149658f, -0.4375f,
-0.0932617f, -0.325195f, 0.0932617f, -0.204102f, 0.0932617f, -0.0917969f, 0.142822f,
-0, 0.192383f, 0.0917969f, 0.282227f, 0.138916f, 0.37207f, 0.186035f, 0.475586f, 0.186035f,
-0.604004f, 0.186035f, 0.707764f, 0.117188f, 0.811523f, 0.0483398f, 0.868164f, -0.0839844f,
-0.896484f, -0.0839844f, 0.852539f, 0.0498047f, 0.736816f, 0.132812f, 0.621094f, 0.21582f,
-0.473145f, 0.21582f, 0.356934f, 0.21582f, 0.257324f, 0.160889f, 0.157715f, 0.105957f,
-0.102539f, 0.00512695f, 0.0473633f, -0.0957031f, 0.0473633f, -0.216797f, 0.0473633f,
--0.345703f, 0.10791f, -0.457275f, 0.168457f, -0.568848f, 0.277588f, -0.631592f, 0.386719f,
--0.694336f, 0.509277f, -0.694336f, 0.610352f, -0.694336f, 0.69165f, -0.652588f, 0.772949f,
--0.61084f, 0.81543f, -0.530518f, 0.85791f, -0.450195f, 0.85791f, -0.359863f, 0.85791f,
--0.270508f, 0.818115f, -0.182861f, 0.77832f, -0.0952148f, 0.716797f, -0.0551758f,
-0.655273f, -0.0151367f, 0.588379f, -0.0151367f, 0.55127f, -0.0151367f, 0.532471f,
--0.0327148f, 0.513672f, -0.050293f, 0.513672f, -0.0820312f, 0.513672f, -0.109375f,
-0.522461f, -0.153809f, 0.450195f, -0.0664062f, 0.406738f, -0.0405273f, 0.363281f,
--0.0146484f, 0.330078f, -0.0146484f, 0.29541f, -0.0146484f, 0.268555f, -0.0456543f,
-0.241699f, -0.0766602f, 0.241699f, -0.128418f, 0.241699f, -0.199219f, 0.287842f,
--0.287109f, 0.333984f, -0.375f, 0.410156f, -0.430176f, 0.466309f, -0.470703f, 0.510742f,
--0.470703f, 0.543457f, -0.470703f, 0.565186f, -0.453857f, 0.586914f, -0.437012f,
-0.594727f, -0.40332f, 0.61084f, -0.457031f, 0.516113f, -0.447754f, 0.479492f, -0.447754f,
-0.441895f, -0.40918f, 0.386719f, -0.352539f, 0.347656f, -0.256348f, 0.318848f, -0.186035f,
-0.318848f, -0.143066f, 0.318848f, -0.112305f, 0.336182f, -0.0930176f, 0.353516f,
--0.0737305f, 0.375f, -0.0737305f, 0.40332f, -0.0737305f, 0.43457f, -0.0952148f, 0.46582f,
--0.116699f, 0.5f, -0.161377f, 0.53418f, -0.206055f, 0.549805f, -0.250977f, 0.577148f,
--0.328613f, 0.577148f, -0.377441f, 0.577148f, -0.409668f, 0.559326f, -0.428711f,
-0.541504f, -0.447754f, 0.516113f, -0.447754f, 0.45752f, -0.22168f, 0.201172f, -0.22168f,
-0.15625f, -0.117188f, 0.139648f, -0.0786133f, 0.139648f, -0.0595703f, 0.139648f,
--0.0444336f, 0.154053f, -0.032959f, 0.168457f, -0.0214844f, 0.216309f, -0.0180664f,
-0.216309f, 0, 0.0078125f, 0, 0.0078125f, -0.0180664f, 0.0493164f, -0.0253906f, 0.0615234f,
--0.0371094f, 0.0864258f, -0.0605469f, 0.116699f, -0.132324f, 0.349609f, -0.677246f,
-0.366699f, -0.677246f, 0.597168f, -0.126465f, 0.625f, -0.0600586f, 0.647705f, -0.0402832f,
-0.67041f, -0.0205078f, 0.710938f, -0.0180664f, 0.710938f, 0, 0.449707f, 0, 0.449707f,
--0.0180664f, 0.489258f, -0.0200195f, 0.503174f, -0.03125f, 0.51709f, -0.0424805f,
-0.51709f, -0.0585938f, 0.51709f, -0.0800781f, 0.497559f, -0.126465f, 0.443848f, -0.257812f,
-0.331543f, -0.525391f, 0.216309f, -0.257812f, 0.461914f, -0.337891f, 0.530762f, -0.323242f,
-0.564941f, -0.291016f, 0.612305f, -0.246094f, 0.612305f, -0.181152f, 0.612305f, -0.131836f,
-0.581055f, -0.0866699f, 0.549805f, -0.0415039f, 0.495361f, -0.020752f, 0.440918f,
-0, 0.329102f, 0, 0.0166016f, 0, 0.0166016f, -0.0180664f, 0.0415039f, -0.0180664f,
-0.0830078f, -0.0180664f, 0.101074f, -0.0444336f, 0.112305f, -0.0615234f, 0.112305f,
--0.117188f, 0.112305f, -0.544922f, 0.112305f, -0.606445f, 0.0981445f, -0.622559f,
-0.0791016f, -0.644043f, 0.0415039f, -0.644043f, 0.0166016f, -0.644043f, 0.0166016f,
--0.662109f, 0.302734f, -0.662109f, 0.382812f, -0.662109f, 0.431152f, -0.650391f,
-0.504395f, -0.632812f, 0.542969f, -0.588135f, 0.581543f, -0.543457f, 0.581543f, -0.485352f,
-0.581543f, -0.435547f, 0.55127f, -0.39624f, 0.520996f, -0.356934f, 0.461914f, -0.337891f,
-0.206055f, -0.364258f, 0.224121f, -0.36084f, 0.247314f, -0.359131f, 0.270508f, -0.357422f,
-0.29834f, -0.357422f, 0.369629f, -0.357422f, 0.405518f, -0.372803f, 0.441406f, -0.388184f,
-0.460449f, -0.419922f, 0.479492f, -0.45166f, 0.479492f, -0.489258f, 0.479492f, -0.547363f,
-0.432129f, -0.588379f, 0.384766f, -0.629395f, 0.293945f, -0.629395f, 0.245117f, -0.629395f,
-0.206055f, -0.618652f, 0.206055f, -0.0478516f, 0.262695f, -0.034668f, 0.317871f,
--0.034668f, 0.40625f, -0.034668f, 0.452637f, -0.0744629f, 0.499023f, -0.114258f,
-0.499023f, -0.172852f, 0.499023f, -0.211426f, 0.478027f, -0.24707f, 0.457031f, -0.282715f,
-0.409668f, -0.303223f, 0.362305f, -0.32373f, 0.29248f, -0.32373f, 0.262207f, -0.32373f,
-0.240723f, -0.322754f, 0.219238f, -0.321777f, 0.206055f, -0.319336f, 0.602051f, -0.677246f,
-0.617188f, -0.452148f, 0.602051f, -0.452148f, 0.571777f, -0.553223f, 0.515625f, -0.597656f,
-0.459473f, -0.64209f, 0.380859f, -0.64209f, 0.314941f, -0.64209f, 0.261719f, -0.608643f,
-0.208496f, -0.575195f, 0.177979f, -0.501953f, 0.147461f, -0.428711f, 0.147461f, -0.319824f,
-0.147461f, -0.22998f, 0.17627f, -0.164062f, 0.205078f, -0.0981445f, 0.262939f, -0.0629883f,
-0.320801f, -0.027832f, 0.39502f, -0.027832f, 0.459473f, -0.027832f, 0.508789f, -0.0554199f,
-0.558105f, -0.0830078f, 0.617188f, -0.165039f, 0.632324f, -0.155273f, 0.58252f, -0.0668945f,
-0.516113f, -0.0258789f, 0.449707f, 0.0151367f, 0.358398f, 0.0151367f, 0.193848f,
-0.0151367f, 0.103516f, -0.106934f, 0.0361328f, -0.197754f, 0.0361328f, -0.320801f,
-0.0361328f, -0.419922f, 0.0805664f, -0.50293f, 0.125f, -0.585938f, 0.202881f, -0.631592f,
-0.280762f, -0.677246f, 0.373047f, -0.677246f, 0.444824f, -0.677246f, 0.514648f, -0.64209f,
-0.535156f, -0.631348f, 0.543945f, -0.631348f, 0.557129f, -0.631348f, 0.566895f, -0.640625f,
-0.57959f, -0.653809f, 0.584961f, -0.677246f, 0.0170898f, 0, 0.0170898f, -0.0180664f,
-0.0419922f, -0.0180664f, 0.0839844f, -0.0180664f, 0.101562f, -0.0449219f, 0.112305f,
--0.0610352f, 0.112305f, -0.117188f, 0.112305f, -0.544922f, 0.112305f, -0.606934f,
-0.0986328f, -0.622559f, 0.0795898f, -0.644043f, 0.0419922f, -0.644043f, 0.0170898f,
--0.644043f, 0.0170898f, -0.662109f, 0.286621f, -0.662109f, 0.435059f, -0.662109f,
-0.512451f, -0.628418f, 0.589844f, -0.594727f, 0.636963f, -0.516113f, 0.684082f, -0.4375f,
-0.684082f, -0.334473f, 0.684082f, -0.196289f, 0.600098f, -0.103516f, 0.505859f, 0,
-0.312988f, 0, 0.206055f, -0.0478516f, 0.268066f, -0.0341797f, 0.310059f, -0.0341797f,
-0.42334f, -0.0341797f, 0.498047f, -0.11377f, 0.572754f, -0.193359f, 0.572754f, -0.32959f,
-0.572754f, -0.466797f, 0.498047f, -0.545898f, 0.42334f, -0.625f, 0.306152f, -0.625f,
-0.262207f, -0.625f, 0.206055f, -0.61084f, 0.208984f, -0.625977f, 0.208984f, -0.364258f,
-0.354492f, -0.364258f, 0.411133f, -0.364258f, 0.430176f, -0.381348f, 0.455566f, -0.403809f,
-0.458496f, -0.460449f, 0.476562f, -0.460449f, 0.476562f, -0.22998f, 0.458496f, -0.22998f,
-0.45166f, -0.27832f, 0.444824f, -0.291992f, 0.436035f, -0.309082f, 0.416016f, -0.318848f,
-0.395996f, -0.328613f, 0.354492f, -0.328613f, 0.208984f, -0.328613f, 0.208984f, -0.110352f,
-0.208984f, -0.0664062f, 0.212891f, -0.0568848f, 0.216797f, -0.0473633f, 0.226562f,
--0.041748f, 0.236328f, -0.0361328f, 0.263672f, -0.0361328f, 0.375977f, -0.0361328f,
-0.432129f, -0.0361328f, 0.45752f, -0.0439453f, 0.48291f, -0.0517578f, 0.506348f,
--0.074707f, 0.536621f, -0.10498f, 0.568359f, -0.166016f, 0.587891f, -0.166016f, 0.530762f,
-0, 0.0205078f, 0, 0.0205078f, -0.0180664f, 0.0439453f, -0.0180664f, 0.0673828f, -0.0180664f,
-0.0883789f, -0.0292969f, 0.104004f, -0.0371094f, 0.109619f, -0.0527344f, 0.115234f,
--0.0683594f, 0.115234f, -0.116699f, 0.115234f, -0.546875f, 0.115234f, -0.609863f,
-0.102539f, -0.624512f, 0.0849609f, -0.644043f, 0.0439453f, -0.644043f, 0.0205078f,
--0.644043f, 0.0205078f, -0.662109f, 0.530762f, -0.662109f, 0.538086f, -0.51709f,
-0.519043f, -0.51709f, 0.508789f, -0.569336f, 0.496338f, -0.588867f, 0.483887f, -0.608398f,
-0.459473f, -0.618652f, 0.439941f, -0.625977f, 0.390625f, -0.625977f, 0.20459f, -0.625977f,
-0.20459f, -0.365723f, 0.325195f, -0.365723f, 0.366699f, -0.365723f, 0.385986f, -0.384033f,
-0.405273f, -0.402344f, 0.411621f, -0.456543f, 0.429688f, -0.456543f, 0.429688f, -0.232422f,
-0.411621f, -0.232422f, 0.411133f, -0.270996f, 0.401611f, -0.289062f, 0.39209f, -0.307129f,
-0.375244f, -0.316162f, 0.358398f, -0.325195f, 0.325195f, -0.325195f, 0.20459f, -0.325195f,
-0.20459f, -0.117188f, 0.20459f, -0.0668945f, 0.210938f, -0.0507812f, 0.21582f, -0.0385742f,
-0.231445f, -0.0297852f, 0.25293f, -0.0180664f, 0.276367f, -0.0180664f, 0.300293f,
--0.0180664f, 0.300293f, 0, 0.0161133f, 0, 0.0161133f, -0.0180664f, 0.0395508f, -0.0180664f,
-0.0805664f, -0.0180664f, 0.0991211f, -0.0419922f, 0.11084f, -0.0576172f, 0.11084f,
--0.117188f, 0.11084f, -0.544922f, 0.11084f, -0.595215f, 0.104492f, -0.611328f, 0.0996094f,
--0.623535f, 0.0844727f, -0.632324f, 0.0634766f, -0.644043f, 0.0395508f, -0.644043f,
-0.0161133f, -0.644043f, 0.0161133f, -0.662109f, 0.508789f, -0.662109f, 0.515137f,
--0.516602f, 0.498047f, -0.516602f, 0.485352f, -0.562988f, 0.468506f, -0.584717f,
-0.45166f, -0.606445f, 0.427002f, -0.616211f, 0.402344f, -0.625977f, 0.350586f, -0.625977f,
-0.61377f, -0.677246f, 0.630859f, -0.468262f, 0.61377f, -0.468262f, 0.587891f, -0.546387f,
-0.546875f, -0.585938f, 0.487793f, -0.643066f, 0.39502f, -0.643066f, 0.268555f, -0.643066f,
-0.202637f, -0.542969f, 0.147461f, -0.458496f, 0.147461f, -0.341797f, 0.147461f, -0.24707f,
-0.184082f, -0.168945f, 0.220703f, -0.0908203f, 0.280029f, -0.0544434f, 0.339355f,
--0.0180664f, 0.401855f, -0.0180664f, 0.438477f, -0.0180664f, 0.472656f, -0.0273438f,
-0.506836f, -0.0366211f, 0.538574f, -0.0546875f, 0.538574f, -0.246094f, 0.538574f,
--0.295898f, 0.531006f, -0.311279f, 0.523438f, -0.32666f, 0.507568f, -0.334717f, 0.491699f,
--0.342773f, 0.45166f, -0.342773f, 0.45166f, -0.361328f, 0.708008f, -0.361328f, 0.708008f,
--0.342773f, 0.695801f, -0.342773f, 0.657715f, -0.342773f, 0.643555f, -0.317383f,
-0.633789f, -0.299316f, 0.633789f, -0.246094f, 0.633789f, -0.043457f, 0.577637f, -0.0131836f,
-0.522949f, 0.000976562f, 0.468262f, 0.0151367f, 0.401367f, 0.0151367f, 0.209473f,
-0.0151367f, 0.109863f, -0.10791f, 0.0351562f, -0.200195f, 0.0351562f, -0.320801f,
-0.0351562f, -0.408203f, 0.0771484f, -0.488281f, 0.126953f, -0.583496f, 0.213867f,
--0.634766f, 0.286621f, -0.677246f, 0.385742f, -0.677246f, 0.421875f, -0.677246f,
-0.451416f, -0.671387f, 0.480957f, -0.665527f, 0.535156f, -0.645508f, 0.5625f, -0.635254f,
-0.571777f, -0.635254f, 0.581055f, -0.635254f, 0.587646f, -0.643799f, 0.594238f, -0.652344f,
-0.595703f, -0.677246f, 0.205566f, -0.35498f, 0.513184f, -0.35498f, 0.513184f, -0.544434f,
-0.513184f, -0.595215f, 0.506836f, -0.611328f, 0.501953f, -0.623535f, 0.486328f, -0.632324f,
-0.465332f, -0.644043f, 0.441895f, -0.644043f, 0.418457f, -0.644043f, 0.418457f, -0.662109f,
-0.70166f, -0.662109f, 0.70166f, -0.644043f, 0.678223f, -0.644043f, 0.654785f, -0.644043f,
-0.633789f, -0.632812f, 0.618164f, -0.625f, 0.612549f, -0.609131f, 0.606934f, -0.593262f,
-0.606934f, -0.544434f, 0.606934f, -0.117188f, 0.606934f, -0.0668945f, 0.613281f,
--0.0507812f, 0.618164f, -0.0385742f, 0.633301f, -0.0297852f, 0.654785f, -0.0180664f,
-0.678223f, -0.0180664f, 0.70166f, -0.0180664f, 0.70166f, 0, 0.418457f, 0, 0.418457f,
--0.0180664f, 0.441895f, -0.0180664f, 0.482422f, -0.0180664f, 0.500977f, -0.0419922f,
-0.513184f, -0.0576172f, 0.513184f, -0.117188f, 0.513184f, -0.318848f, 0.205566f,
--0.318848f, 0.205566f, -0.117188f, 0.205566f, -0.0668945f, 0.211914f, -0.0507812f,
-0.216797f, -0.0385742f, 0.232422f, -0.0297852f, 0.253418f, -0.0180664f, 0.276855f,
--0.0180664f, 0.300781f, -0.0180664f, 0.300781f, 0, 0.0170898f, 0, 0.0170898f, -0.0180664f,
-0.0405273f, -0.0180664f, 0.081543f, -0.0180664f, 0.100098f, -0.0419922f, 0.111816f,
--0.0576172f, 0.111816f, -0.117188f, 0.111816f, -0.544434f, 0.111816f, -0.595215f,
-0.105469f, -0.611328f, 0.100586f, -0.623535f, 0.0854492f, -0.632324f, 0.0639648f,
--0.644043f, 0.0405273f, -0.644043f, 0.0170898f, -0.644043f, 0.0170898f, -0.662109f,
-0.300781f, -0.662109f, 0.300781f, -0.644043f, 0.276855f, -0.644043f, 0.253418f, -0.644043f,
-0.232422f, -0.632812f, 0.217285f, -0.625f, 0.211426f, -0.609131f, 0.205566f, -0.593262f,
-0.205566f, -0.544434f, 0.308594f, -0.0180664f, 0.308594f, 0, 0.0249023f, 0, 0.0249023f,
--0.0180664f, 0.0483398f, -0.0180664f, 0.0893555f, -0.0180664f, 0.10791f, -0.0419922f,
-0.119629f, -0.0576172f, 0.119629f, -0.117188f, 0.119629f, -0.544922f, 0.119629f,
--0.595215f, 0.113281f, -0.611328f, 0.108398f, -0.623535f, 0.0932617f, -0.632324f,
-0.0717773f, -0.644043f, 0.0483398f, -0.644043f, 0.0249023f, -0.644043f, 0.0249023f,
--0.662109f, 0.308594f, -0.662109f, 0.308594f, -0.644043f, 0.284668f, -0.644043f,
-0.244141f, -0.644043f, 0.225586f, -0.620117f, 0.213379f, -0.604492f, 0.213379f, -0.544922f,
-0.213379f, -0.117188f, 0.213379f, -0.0668945f, 0.219727f, -0.0507812f, 0.224609f,
--0.0385742f, 0.240234f, -0.0297852f, 0.26123f, -0.0180664f, 0.284668f, -0.0180664f,
-0.0996094f, -0.644043f, 0.0996094f, -0.662109f, 0.383301f, -0.662109f, 0.383301f,
--0.644043f, 0.359375f, -0.644043f, 0.318848f, -0.644043f, 0.300293f, -0.620117f,
-0.288574f, -0.604492f, 0.288574f, -0.544922f, 0.288574f, -0.221191f, 0.288574f, -0.146484f,
-0.272217f, -0.100098f, 0.255859f, -0.0537109f, 0.21582f, -0.0192871f, 0.175781f,
-0.0151367f, 0.119141f, 0.0151367f, 0.0732422f, 0.0151367f, 0.046875f, -0.00756836f,
-0.0205078f, -0.0302734f, 0.0205078f, -0.0595703f, 0.0205078f, -0.0834961f, 0.0327148f,
--0.0957031f, 0.0488281f, -0.11084f, 0.0703125f, -0.11084f, 0.0859375f, -0.11084f,
-0.0983887f, -0.100586f, 0.11084f, -0.090332f, 0.129883f, -0.0458984f, 0.141113f,
--0.0195312f, 0.158691f, -0.0195312f, 0.171875f, -0.0195312f, 0.18335f, -0.0356445f,
-0.194824f, -0.0517578f, 0.194824f, -0.0927734f, 0.194824f, -0.544922f, 0.194824f,
--0.595215f, 0.188477f, -0.611328f, 0.183594f, -0.623535f, 0.167969f, -0.632324f,
-0.146973f, -0.644043f, 0.123535f, -0.644043f, 0.298828f, -0.367188f, 0.542969f, -0.124512f,
-0.603027f, -0.0644531f, 0.645508f, -0.0427246f, 0.687988f, -0.0209961f, 0.730469f,
--0.0180664f, 0.730469f, 0, 0.415527f, 0, 0.415527f, -0.0180664f, 0.443848f, -0.0180664f,
-0.456299f, -0.0275879f, 0.46875f, -0.0371094f, 0.46875f, -0.0488281f, 0.46875f, -0.0605469f,
-0.464111f, -0.0698242f, 0.459473f, -0.0791016f, 0.433594f, -0.104492f, 0.205078f,
--0.330566f, 0.205078f, -0.117188f, 0.205078f, -0.0668945f, 0.211426f, -0.0507812f,
-0.216309f, -0.0385742f, 0.231934f, -0.0297852f, 0.25293f, -0.0180664f, 0.276367f,
--0.0180664f, 0.298828f, -0.0180664f, 0.298828f, 0, 0.0166016f, 0, 0.0166016f, -0.0180664f,
-0.0400391f, -0.0180664f, 0.0810547f, -0.0180664f, 0.0996094f, -0.0419922f, 0.111328f,
--0.0576172f, 0.111328f, -0.117188f, 0.111328f, -0.544922f, 0.111328f, -0.595215f,
-0.10498f, -0.611816f, 0.100098f, -0.623535f, 0.0849609f, -0.632324f, 0.0634766f,
--0.644043f, 0.0400391f, -0.644043f, 0.0166016f, -0.644043f, 0.0166016f, -0.662109f,
-0.298828f, -0.662109f, 0.298828f, -0.644043f, 0.276367f, -0.644043f, 0.253418f, -0.644043f,
-0.231934f, -0.632812f, 0.216797f, -0.625f, 0.210938f, -0.609375f, 0.205078f, -0.59375f,
-0.205078f, -0.544922f, 0.205078f, -0.342285f, 0.214844f, -0.351562f, 0.271973f, -0.404297f,
-0.416992f, -0.537109f, 0.447266f, -0.581543f, 0.460449f, -0.601074f, 0.460449f, -0.615723f,
-0.460449f, -0.626953f, 0.450195f, -0.635498f, 0.439941f, -0.644043f, 0.415527f, -0.644043f,
-0.400391f, -0.644043f, 0.400391f, -0.662109f, 0.643555f, -0.662109f, 0.643555f, -0.644043f,
-0.62207f, -0.643555f, 0.604492f, -0.638184f, 0.586914f, -0.632812f, 0.561523f, -0.617432f,
-0.536133f, -0.602051f, 0.499023f, -0.567871f, 0.488281f, -0.558105f, 0.399902f, -0.467773f,
-0.573242f, -0.183105f, 0.589355f, -0.179688f, 0.532715f, 0, 0.0200195f, 0, 0.0200195f,
--0.0180664f, 0.0449219f, -0.0180664f, 0.0869141f, -0.0180664f, 0.10498f, -0.0454102f,
-0.115234f, -0.0610352f, 0.115234f, -0.117676f, 0.115234f, -0.544922f, 0.115234f,
--0.606934f, 0.101562f, -0.622559f, 0.0825195f, -0.644043f, 0.0449219f, -0.644043f,
-0.0200195f, -0.644043f, 0.0200195f, -0.662109f, 0.319824f, -0.662109f, 0.319824f,
--0.644043f, 0.26709f, -0.644531f, 0.24585f, -0.634277f, 0.224609f, -0.624023f, 0.216797f,
--0.608398f, 0.208984f, -0.592773f, 0.208984f, -0.533691f, 0.208984f, -0.117676f,
-0.208984f, -0.0771484f, 0.216797f, -0.0620117f, 0.222656f, -0.0517578f, 0.234863f,
--0.046875f, 0.24707f, -0.0419922f, 0.311035f, -0.0419922f, 0.359375f, -0.0419922f,
-0.435547f, -0.0419922f, 0.466309f, -0.0532227f, 0.49707f, -0.0644531f, 0.522461f,
--0.0930176f, 0.547852f, -0.121582f, 0.573242f, -0.183105f, 0.40918f, 0, 0.15332f,
--0.557129f, 0.15332f, -0.114746f, 0.15332f, -0.0537109f, 0.166504f, -0.0385742f,
-0.18457f, -0.0180664f, 0.223633f, -0.0180664f, 0.24707f, -0.0180664f, 0.24707f, 0,
-0.0166016f, 0, 0.0166016f, -0.0180664f, 0.0400391f, -0.0180664f, 0.0820312f, -0.0180664f,
-0.0996094f, -0.043457f, 0.110352f, -0.059082f, 0.110352f, -0.114746f, 0.110352f,
--0.547363f, 0.110352f, -0.591309f, 0.100586f, -0.61084f, 0.09375f, -0.625f, 0.0754395f,
--0.634521f, 0.0571289f, -0.644043f, 0.0166016f, -0.644043f, 0.0166016f, -0.662109f,
-0.204102f, -0.662109f, 0.444336f, -0.144043f, 0.680664f, -0.662109f, 0.868164f, -0.662109f,
-0.868164f, -0.644043f, 0.845215f, -0.644043f, 0.802734f, -0.644043f, 0.785156f, -0.618652f,
-0.774414f, -0.603027f, 0.774414f, -0.547363f, 0.774414f, -0.114746f, 0.774414f, -0.0537109f,
-0.788086f, -0.0385742f, 0.806152f, -0.0180664f, 0.845215f, -0.0180664f, 0.868164f,
--0.0180664f, 0.868164f, 0, 0.586914f, 0, 0.586914f, -0.0180664f, 0.610352f, -0.0180664f,
-0.652832f, -0.0180664f, 0.669922f, -0.043457f, 0.680664f, -0.059082f, 0.680664f,
--0.114746f, 0.680664f, -0.557129f, 0.425293f, 0, -0.0131836f, -0.662109f, 0.166504f,
--0.662109f, 0.571289f, -0.165527f, 0.571289f, -0.547363f, 0.571289f, -0.608398f,
-0.557617f, -0.623535f, 0.539551f, -0.644043f, 0.500488f, -0.644043f, 0.477539f, -0.644043f,
-0.477539f, -0.662109f, 0.708008f, -0.662109f, 0.708008f, -0.644043f, 0.68457f, -0.644043f,
-0.642578f, -0.644043f, 0.625f, -0.618652f, 0.614258f, -0.603027f, 0.614258f, -0.547363f,
-0.614258f, 0.0107422f, 0.59668f, 0.0107422f, 0.160156f, -0.522461f, 0.160156f, -0.114746f,
-0.160156f, -0.0537109f, 0.17334f, -0.0385742f, 0.191895f, -0.0180664f, 0.230469f,
--0.0180664f, 0.253906f, -0.0180664f, 0.253906f, 0, 0.0234375f, 0, 0.0234375f, -0.0180664f,
-0.0463867f, -0.0180664f, 0.0888672f, -0.0180664f, 0.106445f, -0.043457f, 0.117188f,
--0.059082f, 0.117188f, -0.114746f, 0.117188f, -0.575195f, 0.0883789f, -0.608887f,
-0.0734863f, -0.619629f, 0.0585938f, -0.630371f, 0.0297852f, -0.639648f, 0.015625f,
--0.644043f, -0.0131836f, -0.644043f, 0.205078f, -0.310059f, 0.205078f, -0.117188f,
-0.205078f, -0.0546875f, 0.21875f, -0.0395508f, 0.237305f, -0.0180664f, 0.274902f,
--0.0180664f, 0.300293f, -0.0180664f, 0.300293f, 0, 0.0166016f, 0, 0.0166016f, -0.0180664f,
-0.0415039f, -0.0180664f, 0.0834961f, -0.0180664f, 0.101562f, -0.0454102f, 0.111328f,
--0.0605469f, 0.111328f, -0.117188f, 0.111328f, -0.544922f, 0.111328f, -0.607422f,
-0.0981445f, -0.622559f, 0.0791016f, -0.644043f, 0.0415039f, -0.644043f, 0.0166016f,
--0.644043f, 0.0166016f, -0.662109f, 0.259277f, -0.662109f, 0.348145f, -0.662109f,
-0.399414f, -0.643799f, 0.450684f, -0.625488f, 0.48584f, -0.582031f, 0.520996f, -0.538574f,
-0.520996f, -0.479004f, 0.520996f, -0.397949f, 0.467529f, -0.347168f, 0.414062f, -0.296387f,
-0.316406f, -0.296387f, 0.29248f, -0.296387f, 0.264648f, -0.299805f, 0.236816f, -0.303223f,
-0.205078f, -0.310059f, 0.205078f, -0.337891f, 0.230957f, -0.333008f, 0.250977f, -0.330566f,
-0.270996f, -0.328125f, 0.285156f, -0.328125f, 0.335938f, -0.328125f, 0.372803f, -0.367432f,
-0.409668f, -0.406738f, 0.409668f, -0.469238f, 0.409668f, -0.512207f, 0.39209f, -0.549072f,
-0.374512f, -0.585938f, 0.342285f, -0.604248f, 0.310059f, -0.622559f, 0.269043f, -0.622559f,
-0.244141f, -0.622559f, 0.205078f, -0.613281f, 0.44043f, 0.00732422f, 0.490234f, 0.0932617f,
-0.548096f, 0.133789f, 0.605957f, 0.174316f, 0.679688f, 0.180176f, 0.679688f, 0.195801f,
-0.612305f, 0.193359f, 0.535645f, 0.168701f, 0.458984f, 0.144043f, 0.390381f, 0.100342f,
-0.321777f, 0.0566406f, 0.271973f, 0.00732422f, 0.20166f, -0.0209961f, 0.160645f,
--0.0527344f, 0.101074f, -0.100098f, 0.0681152f, -0.169189f, 0.0351562f, -0.238281f,
-0.0351562f, -0.33252f, 0.0351562f, -0.480957f, 0.131348f, -0.579102f, 0.227539f,
--0.677246f, 0.364258f, -0.677246f, 0.494141f, -0.677246f, 0.589111f, -0.578857f,
-0.684082f, -0.480469f, 0.684082f, -0.330566f, 0.684082f, -0.208984f, 0.616455f, -0.117188f,
-0.548828f, -0.0253906f, 0.44043f, 0.00732422f, 0.358398f, -0.639648f, 0.269531f,
--0.639648f, 0.215332f, -0.576172f, 0.146973f, -0.496582f, 0.146973f, -0.33252f, 0.146973f,
--0.171875f, 0.216309f, -0.0849609f, 0.27002f, -0.0180664f, 0.358398f, -0.0180664f,
-0.450195f, -0.0180664f, 0.506348f, -0.0849609f, 0.572266f, -0.164062f, 0.572266f,
--0.318359f, 0.572266f, -0.437012f, 0.536133f, -0.518066f, 0.508301f, -0.580566f,
-0.462158f, -0.610107f, 0.416016f, -0.639648f, 0.358398f, -0.639648f, 0.675781f, 0,
-0.499023f, 0, 0.274902f, -0.30957f, 0.25f, -0.308594f, 0.234375f, -0.308594f, 0.228027f,
--0.308594f, 0.220703f, -0.308838f, 0.213379f, -0.309082f, 0.205566f, -0.30957f, 0.205566f,
--0.117188f, 0.205566f, -0.0546875f, 0.219238f, -0.0395508f, 0.237793f, -0.0180664f,
-0.274902f, -0.0180664f, 0.300781f, -0.0180664f, 0.300781f, 0, 0.0170898f, 0, 0.0170898f,
--0.0180664f, 0.0419922f, -0.0180664f, 0.0839844f, -0.0180664f, 0.102051f, -0.0454102f,
-0.112305f, -0.0605469f, 0.112305f, -0.117188f, 0.112305f, -0.544922f, 0.112305f,
--0.607422f, 0.0986328f, -0.622559f, 0.0795898f, -0.644043f, 0.0419922f, -0.644043f,
-0.0170898f, -0.644043f, 0.0170898f, -0.662109f, 0.258301f, -0.662109f, 0.36377f,
--0.662109f, 0.413818f, -0.646729f, 0.463867f, -0.631348f, 0.498779f, -0.590088f,
-0.533691f, -0.548828f, 0.533691f, -0.491699f, 0.533691f, -0.430664f, 0.493896f, -0.385742f,
-0.454102f, -0.34082f, 0.370605f, -0.322266f, 0.507324f, -0.132324f, 0.554199f, -0.0668945f,
-0.587891f, -0.0454102f, 0.621582f, -0.0239258f, 0.675781f, -0.0180664f, 0.205566f,
--0.340332f, 0.214844f, -0.340332f, 0.22168f, -0.340088f, 0.228516f, -0.339844f, 0.23291f,
--0.339844f, 0.327637f, -0.339844f, 0.375732f, -0.380859f, 0.423828f, -0.421875f,
-0.423828f, -0.485352f, 0.423828f, -0.547363f, 0.38501f, -0.586182f, 0.346191f, -0.625f,
-0.282227f, -0.625f, 0.253906f, -0.625f, 0.205566f, -0.615723f, 0.458496f, -0.677246f,
-0.458496f, -0.448242f, 0.44043f, -0.448242f, 0.431641f, -0.51416f, 0.408936f, -0.553223f,
-0.38623f, -0.592285f, 0.344238f, -0.615234f, 0.302246f, -0.638184f, 0.257324f, -0.638184f,
-0.206543f, -0.638184f, 0.17334f, -0.607178f, 0.140137f, -0.576172f, 0.140137f, -0.536621f,
-0.140137f, -0.506348f, 0.161133f, -0.481445f, 0.191406f, -0.444824f, 0.305176f, -0.383789f,
-0.397949f, -0.333984f, 0.431885f, -0.307373f, 0.46582f, -0.280762f, 0.484131f, -0.244629f,
-0.502441f, -0.208496f, 0.502441f, -0.168945f, 0.502441f, -0.09375f, 0.444092f, -0.0393066f,
-0.385742f, 0.0151367f, 0.293945f, 0.0151367f, 0.265137f, 0.0151367f, 0.239746f, 0.0107422f,
-0.224609f, 0.00830078f, 0.177002f, -0.00708008f, 0.129395f, -0.0224609f, 0.116699f,
--0.0224609f, 0.104492f, -0.0224609f, 0.0974121f, -0.0151367f, 0.090332f, -0.0078125f,
-0.0869141f, 0.0151367f, 0.0688477f, 0.0151367f, 0.0688477f, -0.211914f, 0.0869141f,
--0.211914f, 0.0996094f, -0.140625f, 0.121094f, -0.105225f, 0.142578f, -0.0698242f,
-0.186768f, -0.0463867f, 0.230957f, -0.0229492f, 0.283691f, -0.0229492f, 0.344727f,
--0.0229492f, 0.380127f, -0.0551758f, 0.415527f, -0.0874023f, 0.415527f, -0.131348f,
-0.415527f, -0.155762f, 0.4021f, -0.180664f, 0.388672f, -0.205566f, 0.360352f, -0.227051f,
-0.341309f, -0.241699f, 0.256348f, -0.289307f, 0.171387f, -0.336914f, 0.135498f, -0.365234f,
-0.0996094f, -0.393555f, 0.0810547f, -0.427734f, 0.0625f, -0.461914f, 0.0625f, -0.50293f,
-0.0625f, -0.574219f, 0.117188f, -0.625732f, 0.171875f, -0.677246f, 0.256348f, -0.677246f,
-0.309082f, -0.677246f, 0.368164f, -0.651367f, 0.395508f, -0.63916f, 0.406738f, -0.63916f,
-0.419434f, -0.63916f, 0.42749f, -0.646729f, 0.435547f, -0.654297f, 0.44043f, -0.677246f,
-0.578613f, -0.662109f, 0.585938f, -0.506836f, 0.567383f, -0.506836f, 0.562012f, -0.547852f,
-0.552734f, -0.56543f, 0.537598f, -0.59375f, 0.512451f, -0.607178f, 0.487305f, -0.620605f,
-0.446289f, -0.620605f, 0.353027f, -0.620605f, 0.353027f, -0.114746f, 0.353027f, -0.0537109f,
-0.366211f, -0.0385742f, 0.384766f, -0.0180664f, 0.42334f, -0.0180664f, 0.446289f,
--0.0180664f, 0.446289f, 0, 0.165527f, 0, 0.165527f, -0.0180664f, 0.188965f, -0.0180664f,
-0.230957f, -0.0180664f, 0.248535f, -0.043457f, 0.259277f, -0.059082f, 0.259277f,
--0.114746f, 0.259277f, -0.620605f, 0.179688f, -0.620605f, 0.133301f, -0.620605f,
-0.11377f, -0.61377f, 0.0883789f, -0.604492f, 0.0703125f, -0.578125f, 0.0522461f,
--0.551758f, 0.0488281f, -0.506836f, 0.0302734f, -0.506836f, 0.0380859f, -0.662109f,
-0.709961f, -0.662109f, 0.709961f, -0.644043f, 0.674805f, -0.637695f, 0.656738f, -0.621582f,
-0.630859f, -0.597656f, 0.61084f, -0.54834f, 0.379883f, 0.0151367f, 0.361816f, 0.0151367f,
-0.11377f, -0.555664f, 0.0947266f, -0.599609f, 0.0869141f, -0.609375f, 0.074707f,
--0.624512f, 0.0568848f, -0.633057f, 0.0390625f, -0.641602f, 0.00878906f, -0.644043f,
-0.00878906f, -0.662109f, 0.279297f, -0.662109f, 0.279297f, -0.644043f, 0.233398f,
--0.639648f, 0.219727f, -0.628418f, 0.206055f, -0.617188f, 0.206055f, -0.599609f,
-0.206055f, -0.575195f, 0.228516f, -0.523438f, 0.396973f, -0.135254f, 0.553223f, -0.518555f,
-0.576172f, -0.575195f, 0.576172f, -0.597168f, 0.576172f, -0.611328f, 0.562012f, -0.624268f,
-0.547852f, -0.637207f, 0.51416f, -0.642578f, 0.511719f, -0.643066f, 0.505859f, -0.644043f,
-0.505859f, -0.662109f, 0.936035f, -0.662109f, 0.936035f, -0.644043f, 0.910156f, -0.644043f,
-0.894043f, -0.634766f, 0.87793f, -0.625488f, 0.863281f, -0.600098f, 0.853516f, -0.583008f,
-0.83252f, -0.518555f, 0.647949f, 0.0151367f, 0.628418f, 0.0151367f, 0.477539f, -0.408203f,
-0.327637f, 0.0151367f, 0.310059f, 0.0151367f, 0.113281f, -0.534668f, 0.0913086f,
--0.596191f, 0.0854492f, -0.607422f, 0.0756836f, -0.625977f, 0.0588379f, -0.63501f,
-0.0419922f, -0.644043f, 0.0131836f, -0.644043f, 0.0131836f, -0.662109f, 0.258301f,
--0.662109f, 0.258301f, -0.644043f, 0.246582f, -0.644043f, 0.220703f, -0.644043f,
-0.207031f, -0.632324f, 0.193359f, -0.620605f, 0.193359f, -0.604004f, 0.193359f, -0.586914f,
-0.214844f, -0.525391f, 0.345215f, -0.153809f, 0.455078f, -0.469727f, 0.435547f, -0.525391f,
-0.419922f, -0.569824f, 0.409668f, -0.594238f, 0.396973f, -0.612793f, 0.390625f, -0.62207f,
-0.381348f, -0.628418f, 0.369141f, -0.637207f, 0.356934f, -0.641113f, 0.347656f, -0.644043f,
-0.327637f, -0.644043f, 0.327637f, -0.662109f, 0.585449f, -0.662109f, 0.585449f, -0.644043f,
-0.567871f, -0.644043f, 0.540527f, -0.644043f, 0.527832f, -0.632324f, 0.515137f, -0.620605f,
-0.515137f, -0.600586f, 0.515137f, -0.575684f, 0.537109f, -0.513672f, 0.664062f, -0.153809f,
-0.790039f, -0.518555f, 0.811523f, -0.579102f, 0.811523f, -0.602539f, 0.811523f, -0.61377f,
-0.804443f, -0.623535f, 0.797363f, -0.633301f, 0.786621f, -0.637207f, 0.768066f, -0.644043f,
-0.738281f, -0.644043f, 0.738281f, -0.662109f, 0.408203f, -0.366699f, 0.550293f, -0.154785f,
-0.609375f, -0.0668945f, 0.637939f, -0.0437012f, 0.666504f, -0.0205078f, 0.710449f,
--0.0180664f, 0.710449f, 0, 0.42627f, 0, 0.42627f, -0.0180664f, 0.45459f, -0.0185547f,
-0.468262f, -0.0239258f, 0.478516f, -0.0283203f, 0.485107f, -0.0373535f, 0.491699f,
--0.0463867f, 0.491699f, -0.0556641f, 0.491699f, -0.0668945f, 0.487305f, -0.078125f,
-0.483887f, -0.0864258f, 0.460449f, -0.121094f, 0.348145f, -0.291016f, 0.209473f,
--0.113281f, 0.1875f, -0.0849609f, 0.183105f, -0.0754395f, 0.178711f, -0.065918f,
-0.178711f, -0.0556641f, 0.178711f, -0.0400391f, 0.191895f, -0.0297852f, 0.205078f,
--0.0195312f, 0.242188f, -0.0180664f, 0.242188f, 0, 0.00732422f, 0, 0.00732422f, -0.0180664f,
-0.0322266f, -0.0205078f, 0.050293f, -0.0283203f, 0.0805664f, -0.0410156f, 0.10791f,
--0.0625f, 0.135254f, -0.0839844f, 0.17041f, -0.128418f, 0.32666f, -0.325684f, 0.196289f,
--0.516602f, 0.143066f, -0.594238f, 0.105957f, -0.618408f, 0.0688477f, -0.642578f,
-0.0205078f, -0.644043f, 0.0205078f, -0.662109f, 0.32666f, -0.662109f, 0.32666f, -0.644043f,
-0.287598f, -0.642578f, 0.273193f, -0.631348f, 0.258789f, -0.620117f, 0.258789f, -0.606445f,
-0.258789f, -0.588379f, 0.282227f, -0.553711f, 0.383789f, -0.401855f, 0.501465f, -0.550781f,
-0.521973f, -0.577148f, 0.526611f, -0.586914f, 0.53125f, -0.59668f, 0.53125f, -0.606934f,
-0.53125f, -0.617188f, 0.525391f, -0.625f, 0.518066f, -0.635254f, 0.506836f, -0.639404f,
-0.495605f, -0.643555f, 0.460449f, -0.644043f, 0.460449f, -0.662109f, 0.695312f, -0.662109f,
-0.695312f, -0.644043f, 0.66748f, -0.642578f, 0.649902f, -0.635254f, 0.623535f, -0.624023f,
-0.601562f, -0.60498f, 0.57959f, -0.585938f, 0.539551f, -0.534668f, 0.476562f, -0.662109f,
-0.70752f, -0.662109f, 0.70752f, -0.644043f, 0.694824f, -0.644043f, 0.682129f, -0.644043f,
-0.657715f, -0.632812f, 0.633301f, -0.621582f, 0.613281f, -0.600586f, 0.593262f, -0.57959f,
-0.563965f, -0.532227f, 0.404297f, -0.280762f, 0.404297f, -0.114746f, 0.404297f, -0.0537109f,
-0.417969f, -0.0385742f, 0.436523f, -0.0180664f, 0.476562f, -0.0180664f, 0.498047f,
--0.0180664f, 0.498047f, 0, 0.216797f, 0, 0.216797f, -0.0180664f, 0.240234f, -0.0180664f,
-0.282227f, -0.0180664f, 0.299805f, -0.043457f, 0.310547f, -0.059082f, 0.310547f,
--0.114746f, 0.310547f, -0.271484f, 0.128906f, -0.548828f, 0.0966797f, -0.597656f,
-0.0852051f, -0.609863f, 0.0737305f, -0.62207f, 0.0375977f, -0.63916f, 0.027832f,
--0.644043f, 0.00927734f, -0.644043f, 0.00927734f, -0.662109f, 0.29248f, -0.662109f,
-0.29248f, -0.644043f, 0.277832f, -0.644043f, 0.254883f, -0.644043f, 0.235596f, -0.633301f,
-0.216309f, -0.622559f, 0.216309f, -0.601074f, 0.216309f, -0.583496f, 0.246094f, -0.537598f,
-0.384277f, -0.324219f, 0.51416f, -0.52832f, 0.543457f, -0.574219f, 0.543457f, -0.59668f,
-0.543457f, -0.610352f, 0.536377f, -0.621094f, 0.529297f, -0.631836f, 0.516113f, -0.637939f,
-0.50293f, -0.644043f, 0.476562f, -0.644043f, 0.575195f, -0.662109f, 0.140137f, -0.0400391f,
-0.411621f, -0.0400391f, 0.474121f, -0.0400391f, 0.507568f, -0.0673828f, 0.541016f,
--0.0947266f, 0.566895f, -0.178223f, 0.583008f, -0.175293f, 0.551758f, 0, 0.0126953f,
-0, 0.0126953f, -0.0180664f, 0.4375f, -0.622559f, 0.225586f, -0.622559f, 0.172852f,
--0.622559f, 0.14917f, -0.611084f, 0.125488f, -0.599609f, 0.113037f, -0.577881f, 0.100586f,
--0.556152f, 0.090332f, -0.496582f, 0.0717773f, -0.496582f, 0.0854492f, -0.662109f,
-0.296875f, 0.198242f, 0.0820312f, 0.198242f, 0.0820312f, -0.677246f, 0.296875f, -0.677246f,
-0.296875f, -0.638672f, 0.155273f, -0.638672f, 0.155273f, 0.160156f, 0.296875f, 0.160156f,
-0.0405273f, -0.694336f, 0.279785f, 0.0136719f, 0.240723f, 0.0136719f, 0.00146484f,
--0.694336f, 0.0366211f, -0.677246f, 0.251465f, -0.677246f, 0.251465f, 0.19873f, 0.0366211f,
-0.19873f, 0.0366211f, 0.160156f, 0.178223f, 0.160156f, 0.178223f, -0.638672f, 0.0366211f,
--0.638672f, 0.243164f, -0.675781f, 0.450684f, -0.325684f, 0.405762f, -0.325684f,
-0.234863f, -0.611816f, 0.0639648f, -0.325684f, 0.0180664f, -0.325684f, 0.228516f,
--0.675781f, 0.508789f, 0.21582f, -0.00830078f, 0.21582f, -0.00830078f, 0.174805f,
-0.508789f, 0.174805f, 0.0576172f, -0.678711f, 0.166504f, -0.678711f, 0.218262f, -0.510254f,
-0.201172f, -0.510254f, 0.284668f, -0.0644531f, 0.21582f, -0.0112305f, 0.198242f,
--0.00292969f, 0.171875f, 0.00927734f, 0.14209f, 0.00927734f, 0.0957031f, 0.00927734f,
-0.0656738f, -0.0224609f, 0.0356445f, -0.0541992f, 0.0356445f, -0.105957f, 0.0356445f,
--0.138672f, 0.050293f, -0.162598f, 0.0703125f, -0.195801f, 0.119873f, -0.225098f,
-0.169434f, -0.254395f, 0.284668f, -0.296387f, 0.284668f, -0.313965f, 0.284668f, -0.380859f,
-0.263428f, -0.405762f, 0.242188f, -0.430664f, 0.20166f, -0.430664f, 0.170898f, -0.430664f,
-0.152832f, -0.414062f, 0.134277f, -0.397461f, 0.134277f, -0.375977f, 0.135254f, -0.347656f,
-0.135254f, -0.325195f, 0.123779f, -0.312988f, 0.112305f, -0.300781f, 0.09375f, -0.300781f,
-0.0756836f, -0.300781f, 0.064209f, -0.313477f, 0.0527344f, -0.326172f, 0.0527344f,
--0.348145f, 0.0527344f, -0.390137f, 0.0957031f, -0.425293f, 0.138672f, -0.460449f,
-0.216309f, -0.460449f, 0.275879f, -0.460449f, 0.313965f, -0.44043f, 0.342773f, -0.425293f,
-0.356445f, -0.393066f, 0.365234f, -0.37207f, 0.365234f, -0.307129f, 0.365234f, -0.155273f,
-0.365234f, -0.0913086f, 0.367676f, -0.0769043f, 0.370117f, -0.0625f, 0.375732f, -0.0576172f,
-0.381348f, -0.0527344f, 0.388672f, -0.0527344f, 0.396484f, -0.0527344f, 0.402344f,
--0.0561523f, 0.412598f, -0.0625f, 0.441895f, -0.0917969f, 0.441895f, -0.0644531f,
-0.387207f, 0.00878906f, 0.337402f, 0.00878906f, 0.313477f, 0.00878906f, 0.299316f,
--0.0078125f, 0.285156f, -0.0244141f, 0.284668f, -0.0644531f, 0.284668f, -0.0961914f,
-0.284668f, -0.266602f, 0.210938f, -0.237305f, 0.189453f, -0.225098f, 0.150879f, -0.203613f,
-0.134277f, -0.180176f, 0.117676f, -0.156738f, 0.117676f, -0.128906f, 0.117676f, -0.09375f,
-0.138672f, -0.0705566f, 0.159668f, -0.0473633f, 0.187012f, -0.0473633f, 0.224121f,
--0.0473633f, 0.284668f, -0.0961914f, 0.153809f, -0.370117f, 0.21875f, -0.460449f,
-0.293945f, -0.460449f, 0.362793f, -0.460449f, 0.414062f, -0.401611f, 0.465332f, -0.342773f,
-0.465332f, -0.240723f, 0.465332f, -0.121582f, 0.38623f, -0.0488281f, 0.318359f, 0.0136719f,
-0.234863f, 0.0136719f, 0.195801f, 0.0136719f, 0.155518f, -0.000488281f, 0.115234f,
--0.0146484f, 0.0732422f, -0.0429688f, 0.0732422f, -0.506348f, 0.0732422f, -0.58252f,
-0.0695801f, -0.600098f, 0.065918f, -0.617676f, 0.0581055f, -0.624023f, 0.050293f,
--0.630371f, 0.0385742f, -0.630371f, 0.0249023f, -0.630371f, 0.00439453f, -0.622559f,
--0.00244141f, -0.639648f, 0.131836f, -0.694336f, 0.153809f, -0.694336f, 0.153809f,
--0.338867f, 0.153809f, -0.0712891f, 0.178711f, -0.046875f, 0.205322f, -0.0344238f,
-0.231934f, -0.0219727f, 0.259766f, -0.0219727f, 0.304199f, -0.0219727f, 0.342529f,
--0.0708008f, 0.380859f, -0.119629f, 0.380859f, -0.212891f, 0.380859f, -0.298828f,
-0.342529f, -0.344971f, 0.304199f, -0.391113f, 0.255371f, -0.391113f, 0.229492f, -0.391113f,
-0.203613f, -0.37793f, 0.184082f, -0.368164f, 0.153809f, -0.338867f, 0.411133f, -0.169922f,
-0.393066f, -0.081543f, 0.340332f, -0.0339355f, 0.287598f, 0.0136719f, 0.223633f,
-0.0136719f, 0.147461f, 0.0136719f, 0.0908203f, -0.050293f, 0.0341797f, -0.114258f,
-0.0341797f, -0.223145f, 0.0341797f, -0.328613f, 0.0969238f, -0.394531f, 0.159668f,
--0.460449f, 0.247559f, -0.460449f, 0.313477f, -0.460449f, 0.355957f, -0.425537f,
-0.398438f, -0.390625f, 0.398438f, -0.353027f, 0.398438f, -0.334473f, 0.386475f, -0.322998f,
-0.374512f, -0.311523f, 0.353027f, -0.311523f, 0.324219f, -0.311523f, 0.30957f, -0.330078f,
-0.30127f, -0.340332f, 0.298584f, -0.369141f, 0.295898f, -0.397949f, 0.278809f, -0.413086f,
-0.261719f, -0.427734f, 0.231445f, -0.427734f, 0.182617f, -0.427734f, 0.152832f, -0.391602f,
-0.113281f, -0.34375f, 0.113281f, -0.265137f, 0.113281f, -0.185059f, 0.152588f, -0.123779f,
-0.191895f, -0.0625f, 0.258789f, -0.0625f, 0.306641f, -0.0625f, 0.344727f, -0.0952148f,
-0.371582f, -0.117676f, 0.396973f, -0.176758f, 0.347168f, -0.050293f, 0.314453f, -0.0161133f,
-0.283203f, -0.0012207f, 0.251953f, 0.0136719f, 0.21582f, 0.0136719f, 0.142578f, 0.0136719f,
-0.0878906f, -0.0476074f, 0.0332031f, -0.108887f, 0.0332031f, -0.205078f, 0.0332031f,
--0.30127f, 0.09375f, -0.381104f, 0.154297f, -0.460938f, 0.249512f, -0.460938f, 0.308594f,
--0.460938f, 0.347168f, -0.42334f, 0.347168f, -0.505859f, 0.347168f, -0.58252f, 0.343506f,
--0.600098f, 0.339844f, -0.617676f, 0.332031f, -0.624023f, 0.324219f, -0.630371f,
-0.3125f, -0.630371f, 0.299805f, -0.630371f, 0.278809f, -0.622559f, 0.272461f, -0.639648f,
-0.405762f, -0.694336f, 0.427734f, -0.694336f, 0.427734f, -0.177246f, 0.427734f, -0.0986328f,
-0.431396f, -0.0812988f, 0.435059f, -0.0639648f, 0.443115f, -0.0571289f, 0.451172f,
--0.050293f, 0.461914f, -0.050293f, 0.475098f, -0.050293f, 0.49707f, -0.0585938f,
-0.502441f, -0.0415039f, 0.369629f, 0.0136719f, 0.347168f, 0.0136719f, 0.347168f,
--0.0844727f, 0.347168f, -0.314941f, 0.344238f, -0.348145f, 0.32959f, -0.375488f,
-0.314941f, -0.402832f, 0.290771f, -0.416748f, 0.266602f, -0.430664f, 0.243652f, -0.430664f,
-0.200684f, -0.430664f, 0.166992f, -0.39209f, 0.122559f, -0.341309f, 0.122559f, -0.243652f,
-0.122559f, -0.14502f, 0.165527f, -0.0925293f, 0.208496f, -0.0400391f, 0.26123f, -0.0400391f,
-0.305664f, -0.0400391f, 0.347168f, -0.0844727f, 0.106445f, -0.278809f, 0.105957f,
--0.179199f, 0.154785f, -0.122559f, 0.203613f, -0.065918f, 0.269531f, -0.065918f,
-0.313477f, -0.065918f, 0.345947f, -0.0900879f, 0.378418f, -0.114258f, 0.400391f,
--0.172852f, 0.415527f, -0.163086f, 0.405273f, -0.0961914f, 0.355957f, -0.0412598f,
-0.306641f, 0.0136719f, 0.232422f, 0.0136719f, 0.151855f, 0.0136719f, 0.0944824f,
--0.0490723f, 0.0371094f, -0.111816f, 0.0371094f, -0.217773f, 0.0371094f, -0.33252f,
-0.0959473f, -0.396729f, 0.154785f, -0.460938f, 0.243652f, -0.460938f, 0.318848f,
--0.460938f, 0.367188f, -0.411377f, 0.415527f, -0.361816f, 0.415527f, -0.278809f,
-0.106445f, -0.307129f, 0.313477f, -0.307129f, 0.311035f, -0.350098f, 0.303223f, -0.367676f,
-0.291016f, -0.39502f, 0.266846f, -0.410645f, 0.242676f, -0.42627f, 0.216309f, -0.42627f,
-0.175781f, -0.42627f, 0.143799f, -0.394775f, 0.111816f, -0.363281f, 0.106445f, -0.307129f,
-0.206055f, -0.412109f, 0.206055f, -0.118164f, 0.206055f, -0.0556641f, 0.219727f,
--0.0390625f, 0.237793f, -0.0175781f, 0.268066f, -0.0175781f, 0.308594f, -0.0175781f,
-0.308594f, 0, 0.0415039f, 0, 0.0415039f, -0.0175781f, 0.0615234f, -0.0175781f, 0.0810547f,
--0.0175781f, 0.097168f, -0.0273438f, 0.113281f, -0.0371094f, 0.119385f, -0.0537109f,
-0.125488f, -0.0703125f, 0.125488f, -0.118164f, 0.125488f, -0.412109f, 0.0385742f,
--0.412109f, 0.0385742f, -0.447266f, 0.125488f, -0.447266f, 0.125488f, -0.476562f,
-0.125488f, -0.543457f, 0.146973f, -0.589844f, 0.168457f, -0.63623f, 0.212646f, -0.664795f,
-0.256836f, -0.693359f, 0.312012f, -0.693359f, 0.363281f, -0.693359f, 0.40625f, -0.660156f,
-0.43457f, -0.638184f, 0.43457f, -0.61084f, 0.43457f, -0.596191f, 0.421875f, -0.583252f,
-0.40918f, -0.570312f, 0.394531f, -0.570312f, 0.383301f, -0.570312f, 0.37085f, -0.578369f,
-0.358398f, -0.586426f, 0.340332f, -0.613037f, 0.322266f, -0.639648f, 0.307129f, -0.648926f,
-0.291992f, -0.658203f, 0.273438f, -0.658203f, 0.250977f, -0.658203f, 0.235352f, -0.64624f,
-0.219727f, -0.634277f, 0.212891f, -0.609131f, 0.206055f, -0.583984f, 0.206055f, -0.479492f,
-0.206055f, -0.447266f, 0.321289f, -0.447266f, 0.321289f, -0.412109f, 0.150879f, -0.163086f,
-0.109863f, -0.183105f, 0.0878906f, -0.218994f, 0.065918f, -0.254883f, 0.065918f,
--0.29834f, 0.065918f, -0.364746f, 0.115967f, -0.412598f, 0.166016f, -0.460449f, 0.244141f,
--0.460449f, 0.308105f, -0.460449f, 0.35498f, -0.429199f, 0.449707f, -0.429199f, 0.470703f,
--0.429199f, 0.474121f, -0.427979f, 0.477539f, -0.426758f, 0.479004f, -0.423828f,
-0.481934f, -0.419434f, 0.481934f, -0.408203f, 0.481934f, -0.395508f, 0.479492f, -0.390625f,
-0.478027f, -0.388184f, 0.474365f, -0.386719f, 0.470703f, -0.385254f, 0.449707f, -0.385254f,
-0.391602f, -0.385254f, 0.418945f, -0.350098f, 0.418945f, -0.29541f, 0.418945f, -0.23291f,
-0.371094f, -0.188477f, 0.323242f, -0.144043f, 0.242676f, -0.144043f, 0.209473f, -0.144043f,
-0.174805f, -0.153809f, 0.15332f, -0.135254f, 0.145752f, -0.121338f, 0.138184f, -0.107422f,
-0.138184f, -0.0976562f, 0.138184f, -0.0893555f, 0.14624f, -0.081543f, 0.154297f,
--0.0737305f, 0.177734f, -0.0703125f, 0.191406f, -0.0683594f, 0.246094f, -0.0668945f,
-0.34668f, -0.0644531f, 0.376465f, -0.0600586f, 0.421875f, -0.0537109f, 0.448975f,
--0.0263672f, 0.476074f, 0.000976562f, 0.476074f, 0.0410156f, 0.476074f, 0.0961914f,
-0.424316f, 0.144531f, 0.348145f, 0.21582f, 0.225586f, 0.21582f, 0.131348f, 0.21582f,
-0.0664062f, 0.17334f, 0.0297852f, 0.148926f, 0.0297852f, 0.122559f, 0.0297852f, 0.11084f,
-0.0351562f, 0.0991211f, 0.043457f, 0.0810547f, 0.0693359f, 0.0488281f, 0.0727539f,
-0.0444336f, 0.119141f, -0.00390625f, 0.09375f, -0.019043f, 0.083252f, -0.0310059f,
-0.0727539f, -0.0429688f, 0.0727539f, -0.0581055f, 0.0727539f, -0.0751953f, 0.0866699f,
--0.0981445f, 0.100586f, -0.121094f, 0.150879f, -0.163086f, 0.23584f, -0.437012f,
-0.199707f, -0.437012f, 0.175293f, -0.408203f, 0.150879f, -0.379395f, 0.150879f, -0.319824f,
-0.150879f, -0.242676f, 0.184082f, -0.200195f, 0.209473f, -0.167969f, 0.248535f, -0.167969f,
-0.285645f, -0.167969f, 0.30957f, -0.195801f, 0.333496f, -0.223633f, 0.333496f, -0.283203f,
-0.333496f, -0.36084f, 0.299805f, -0.404785f, 0.274902f, -0.437012f, 0.23584f, -0.437012f,
-0.145996f, 0, 0.123047f, 0.0249023f, 0.111328f, 0.0463867f, 0.0996094f, 0.0678711f,
-0.0996094f, 0.0859375f, 0.0996094f, 0.109375f, 0.12793f, 0.126953f, 0.176758f, 0.157227f,
-0.269043f, 0.157227f, 0.356934f, 0.157227f, 0.398682f, 0.126221f, 0.44043f, 0.0952148f,
-0.44043f, 0.0600586f, 0.44043f, 0.034668f, 0.415527f, 0.0239258f, 0.390137f, 0.0131836f,
-0.314941f, 0.0112305f, 0.205078f, 0.00830078f, 0.145996f, 0, 0.14502f, -0.694336f,
-0.165527f, -0.694336f, 0.179932f, -0.679932f, 0.194336f, -0.665527f, 0.194336f, -0.64502f,
-0.194336f, -0.624512f, 0.179932f, -0.609863f, 0.165527f, -0.595215f, 0.14502f, -0.595215f,
-0.124512f, -0.595215f, 0.109863f, -0.609863f, 0.0952148f, -0.624512f, 0.0952148f,
--0.64502f, 0.0952148f, -0.665527f, 0.109619f, -0.679932f, 0.124023f, -0.694336f,
-0.14502f, -0.694336f, 0.185547f, -0.460449f, 0.185547f, -0.101074f, 0.185547f, -0.059082f,
-0.19165f, -0.045166f, 0.197754f, -0.03125f, 0.209717f, -0.0244141f, 0.22168f, -0.0175781f,
-0.253418f, -0.0175781f, 0.253418f, 0, 0.0361328f, 0, 0.0361328f, -0.0175781f, 0.0688477f,
--0.0175781f, 0.0800781f, -0.0239258f, 0.0913086f, -0.0302734f, 0.0979004f, -0.0449219f,
-0.104492f, -0.0595703f, 0.104492f, -0.101074f, 0.104492f, -0.273438f, 0.104492f,
--0.346191f, 0.100098f, -0.367676f, 0.0966797f, -0.383301f, 0.0893555f, -0.389404f,
-0.0820312f, -0.395508f, 0.0693359f, -0.395508f, 0.0556641f, -0.395508f, 0.0361328f,
--0.388184f, 0.0292969f, -0.405762f, 0.164062f, -0.460449f, 0.144531f, -0.694824f,
-0.165527f, -0.694824f, 0.180176f, -0.680176f, 0.194824f, -0.665527f, 0.194824f, -0.644531f,
-0.194824f, -0.624023f, 0.180176f, -0.609375f, 0.165527f, -0.594727f, 0.144531f, -0.594727f,
-0.124023f, -0.594727f, 0.109375f, -0.609375f, 0.0947266f, -0.624023f, 0.0947266f,
--0.644531f, 0.0947266f, -0.665527f, 0.109375f, -0.680176f, 0.124023f, -0.694824f,
-0.144531f, -0.694824f, 0.186523f, -0.460449f, 0.186523f, -0.0102539f, 0.186523f,
-0.104492f, 0.137695f, 0.160156f, 0.0888672f, 0.21582f, 0.0107422f, 0.21582f, -0.0336914f,
-0.21582f, -0.0551758f, 0.199707f, -0.0766602f, 0.183594f, -0.0766602f, 0.166504f,
--0.0766602f, 0.149414f, -0.0646973f, 0.137207f, -0.0527344f, 0.125f, -0.0366211f,
-0.125f, -0.0239258f, 0.125f, -0.0107422f, 0.131348f, -0.00244141f, 0.134766f, 0.0212402f,
-0.156006f, 0.0449219f, 0.177246f, 0.0610352f, 0.177246f, 0.0727539f, 0.177246f, 0.0839844f,
-0.168213f, 0.0952148f, 0.15918f, 0.100586f, 0.137939f, 0.105957f, 0.116699f, 0.105957f,
-0.0458984f, 0.105957f, -0.272461f, 0.105957f, -0.346191f, 0.101562f, -0.367188f,
-0.0981445f, -0.383301f, 0.0908203f, -0.389404f, 0.0834961f, -0.395508f, 0.0708008f,
--0.395508f, 0.0571289f, -0.395508f, 0.0375977f, -0.388184f, 0.0307617f, -0.405762f,
-0.165527f, -0.460449f, 0.163574f, -0.694336f, 0.163574f, -0.249023f, 0.277344f, -0.353027f,
-0.313477f, -0.38623f, 0.319336f, -0.39502f, 0.323242f, -0.400879f, 0.323242f, -0.406738f,
-0.323242f, -0.416504f, 0.315186f, -0.423584f, 0.307129f, -0.430664f, 0.288574f, -0.431641f,
-0.288574f, -0.447266f, 0.48291f, -0.447266f, 0.48291f, -0.431641f, 0.442871f, -0.430664f,
-0.41626f, -0.419434f, 0.389648f, -0.408203f, 0.35791f, -0.379395f, 0.243164f, -0.273438f,
-0.35791f, -0.128418f, 0.405762f, -0.0683594f, 0.422363f, -0.0522461f, 0.445801f,
--0.0292969f, 0.463379f, -0.0224609f, 0.475586f, -0.0175781f, 0.505859f, -0.0175781f,
-0.505859f, 0, 0.288574f, 0, 0.288574f, -0.0175781f, 0.307129f, -0.0180664f, 0.313721f,
--0.0231934f, 0.320312f, -0.0283203f, 0.320312f, -0.0375977f, 0.320312f, -0.0488281f,
-0.300781f, -0.0737305f, 0.163574f, -0.249023f, 0.163574f, -0.100586f, 0.163574f,
--0.0571289f, 0.169678f, -0.043457f, 0.175781f, -0.0297852f, 0.187012f, -0.0239258f,
-0.198242f, -0.0180664f, 0.23584f, -0.0175781f, 0.23584f, 0, 0.00830078f, 0, 0.00830078f,
--0.0175781f, 0.0424805f, -0.0175781f, 0.0595703f, -0.0258789f, 0.0698242f, -0.03125f,
-0.0751953f, -0.0424805f, 0.0825195f, -0.0585938f, 0.0825195f, -0.0981445f, 0.0825195f,
--0.505371f, 0.0825195f, -0.583008f, 0.0791016f, -0.600342f, 0.0756836f, -0.617676f,
-0.0678711f, -0.624268f, 0.0600586f, -0.630859f, 0.0473633f, -0.630859f, 0.0371094f,
--0.630859f, 0.0166016f, -0.622559f, 0.00830078f, -0.639648f, 0.141113f, -0.694336f,
-0.185059f, -0.694336f, 0.185059f, -0.101074f, 0.185059f, -0.059082f, 0.191162f, -0.0454102f,
-0.197266f, -0.0317383f, 0.209961f, -0.0246582f, 0.222656f, -0.0175781f, 0.257324f,
--0.0175781f, 0.257324f, 0, 0.0380859f, 0, 0.0380859f, -0.0175781f, 0.0688477f, -0.0175781f,
-0.0800781f, -0.0239258f, 0.0913086f, -0.0302734f, 0.0976562f, -0.0449219f, 0.104004f,
--0.0595703f, 0.104004f, -0.101074f, 0.104004f, -0.507324f, 0.104004f, -0.583008f,
-0.100586f, -0.600342f, 0.097168f, -0.617676f, 0.0895996f, -0.624023f, 0.0820312f,
--0.630371f, 0.0703125f, -0.630371f, 0.0576172f, -0.630371f, 0.0380859f, -0.622559f,
-0.0297852f, -0.639648f, 0.163086f, -0.694336f, 0.164062f, -0.365234f, 0.212891f,
--0.414062f, 0.22168f, -0.421387f, 0.243652f, -0.439941f, 0.269043f, -0.450195f, 0.294434f,
--0.460449f, 0.319336f, -0.460449f, 0.361328f, -0.460449f, 0.391602f, -0.436035f,
-0.421875f, -0.411621f, 0.432129f, -0.365234f, 0.482422f, -0.423828f, 0.51709f, -0.442139f,
-0.551758f, -0.460449f, 0.588379f, -0.460449f, 0.624023f, -0.460449f, 0.651611f, -0.442139f,
-0.679199f, -0.423828f, 0.695312f, -0.382324f, 0.706055f, -0.354004f, 0.706055f, -0.293457f,
-0.706055f, -0.101074f, 0.706055f, -0.059082f, 0.712402f, -0.043457f, 0.717285f, -0.0327148f,
-0.730469f, -0.0251465f, 0.743652f, -0.0175781f, 0.773438f, -0.0175781f, 0.773438f,
-0, 0.552734f, 0, 0.552734f, -0.0175781f, 0.562012f, -0.0175781f, 0.59082f, -0.0175781f,
-0.606934f, -0.0288086f, 0.618164f, -0.0366211f, 0.623047f, -0.0537109f, 0.625f, -0.0620117f,
-0.625f, -0.101074f, 0.625f, -0.293457f, 0.625f, -0.348145f, 0.611816f, -0.370605f,
-0.592773f, -0.401855f, 0.550781f, -0.401855f, 0.524902f, -0.401855f, 0.498779f, -0.388916f,
-0.472656f, -0.375977f, 0.435547f, -0.34082f, 0.43457f, -0.335449f, 0.435547f, -0.314453f,
-0.435547f, -0.101074f, 0.435547f, -0.0551758f, 0.440674f, -0.0439453f, 0.445801f,
--0.0327148f, 0.459961f, -0.0251465f, 0.474121f, -0.0175781f, 0.508301f, -0.0175781f,
-0.508301f, 0, 0.282227f, 0, 0.282227f, -0.0175781f, 0.319336f, -0.0175781f, 0.333252f,
--0.0263672f, 0.347168f, -0.0351562f, 0.352539f, -0.0527344f, 0.35498f, -0.0610352f,
-0.35498f, -0.101074f, 0.35498f, -0.293457f, 0.35498f, -0.348145f, 0.338867f, -0.37207f,
-0.317383f, -0.40332f, 0.278809f, -0.40332f, 0.252441f, -0.40332f, 0.226562f, -0.38916f,
-0.186035f, -0.367676f, 0.164062f, -0.34082f, 0.164062f, -0.101074f, 0.164062f, -0.0571289f,
-0.170166f, -0.0439453f, 0.17627f, -0.0307617f, 0.188232f, -0.0241699f, 0.200195f,
--0.0175781f, 0.236816f, -0.0175781f, 0.236816f, 0, 0.015625f, 0, 0.015625f, -0.0175781f,
-0.0463867f, -0.0175781f, 0.0585938f, -0.0241699f, 0.0708008f, -0.0307617f, 0.0771484f,
--0.045166f, 0.0834961f, -0.0595703f, 0.0834961f, -0.101074f, 0.0834961f, -0.271973f,
-0.0834961f, -0.345703f, 0.0791016f, -0.367188f, 0.0756836f, -0.383301f, 0.0683594f,
--0.389404f, 0.0610352f, -0.395508f, 0.0483398f, -0.395508f, 0.034668f, -0.395508f,
-0.015625f, -0.388184f, 0.00830078f, -0.405762f, 0.143066f, -0.460449f, 0.164062f,
--0.460449f, 0.161621f, -0.365723f, 0.240234f, -0.460449f, 0.311523f, -0.460449f,
-0.348145f, -0.460449f, 0.374512f, -0.442139f, 0.400879f, -0.423828f, 0.416504f, -0.381836f,
-0.427246f, -0.352539f, 0.427246f, -0.291992f, 0.427246f, -0.101074f, 0.427246f, -0.0585938f,
-0.434082f, -0.043457f, 0.439453f, -0.03125f, 0.451416f, -0.0244141f, 0.463379f, -0.0175781f,
-0.495605f, -0.0175781f, 0.495605f, 0, 0.274414f, 0, 0.274414f, -0.0175781f, 0.283691f,
--0.0175781f, 0.314941f, -0.0175781f, 0.327393f, -0.0270996f, 0.339844f, -0.0366211f,
-0.344727f, -0.0551758f, 0.34668f, -0.0625f, 0.34668f, -0.101074f, 0.34668f, -0.28418f,
-0.34668f, -0.345215f, 0.330811f, -0.372803f, 0.314941f, -0.400391f, 0.277344f, -0.400391f,
-0.219238f, -0.400391f, 0.161621f, -0.336914f, 0.161621f, -0.101074f, 0.161621f, -0.0556641f,
-0.166992f, -0.0449219f, 0.173828f, -0.0307617f, 0.185791f, -0.0241699f, 0.197754f,
--0.0175781f, 0.234375f, -0.0175781f, 0.234375f, 0, 0.0131836f, 0, 0.0131836f, -0.0175781f,
-0.0229492f, -0.0175781f, 0.0571289f, -0.0175781f, 0.0690918f, -0.0349121f, 0.0810547f,
--0.0522461f, 0.0810547f, -0.101074f, 0.0810547f, -0.26709f, 0.0810547f, -0.347656f,
-0.0773926f, -0.365234f, 0.0737305f, -0.382812f, 0.0661621f, -0.38916f, 0.0585938f,
--0.395508f, 0.0458984f, -0.395508f, 0.0322266f, -0.395508f, 0.0131836f, -0.388184f,
-0.00585938f, -0.405762f, 0.140625f, -0.460449f, 0.161621f, -0.460449f, 0.25f, -0.460449f,
-0.351562f, -0.460449f, 0.413086f, -0.383301f, 0.465332f, -0.317383f, 0.465332f, -0.231934f,
-0.465332f, -0.171875f, 0.436523f, -0.110352f, 0.407715f, -0.0488281f, 0.357178f,
--0.0175781f, 0.306641f, 0.0136719f, 0.244629f, 0.0136719f, 0.143555f, 0.0136719f,
-0.0839844f, -0.0668945f, 0.0336914f, -0.134766f, 0.0336914f, -0.219238f, 0.0336914f,
--0.280762f, 0.064209f, -0.341553f, 0.0947266f, -0.402344f, 0.144531f, -0.431396f,
-0.194336f, -0.460449f, 0.25f, -0.460449f, 0.234863f, -0.428711f, 0.208984f, -0.428711f,
-0.182861f, -0.41333f, 0.156738f, -0.397949f, 0.140625f, -0.359375f, 0.124512f, -0.320801f,
-0.124512f, -0.260254f, 0.124512f, -0.162598f, 0.16333f, -0.0917969f, 0.202148f, -0.0209961f,
-0.265625f, -0.0209961f, 0.312988f, -0.0209961f, 0.34375f, -0.0600586f, 0.374512f,
--0.0991211f, 0.374512f, -0.194336f, 0.374512f, -0.313477f, 0.323242f, -0.381836f,
-0.288574f, -0.428711f, 0.234863f, -0.428711f, -0.000976562f, -0.402832f, 0.136719f,
--0.458496f, 0.155273f, -0.458496f, 0.155273f, -0.354004f, 0.189941f, -0.413086f,
-0.224854f, -0.436768f, 0.259766f, -0.460449f, 0.29834f, -0.460449f, 0.365723f, -0.460449f,
-0.410645f, -0.407715f, 0.46582f, -0.343262f, 0.46582f, -0.239746f, 0.46582f, -0.124023f,
-0.399414f, -0.0483398f, 0.344727f, 0.0136719f, 0.261719f, 0.0136719f, 0.225586f,
-0.0136719f, 0.199219f, 0.00341797f, 0.179688f, -0.00390625f, 0.155273f, -0.0258789f,
-0.155273f, 0.110352f, 0.155273f, 0.15625f, 0.160889f, 0.168701f, 0.166504f, 0.181152f,
-0.18042f, 0.188477f, 0.194336f, 0.195801f, 0.230957f, 0.195801f, 0.230957f, 0.213867f,
--0.00341797f, 0.213867f, -0.00341797f, 0.195801f, 0.00878906f, 0.195801f, 0.0356445f,
-0.196289f, 0.0546875f, 0.185547f, 0.0639648f, 0.180176f, 0.0690918f, 0.168213f, 0.0742188f,
-0.15625f, 0.0742188f, 0.107422f, 0.0742188f, -0.31543f, 0.0742188f, -0.358887f, 0.0703125f,
--0.370605f, 0.0664062f, -0.382324f, 0.0578613f, -0.388184f, 0.0493164f, -0.394043f,
-0.034668f, -0.394043f, 0.0229492f, -0.394043f, 0.00488281f, -0.387207f, 0.155273f,
--0.325195f, 0.155273f, -0.158203f, 0.155273f, -0.104004f, 0.159668f, -0.0869141f,
-0.166504f, -0.0585938f, 0.193115f, -0.0371094f, 0.219727f, -0.015625f, 0.260254f,
--0.015625f, 0.309082f, -0.015625f, 0.339355f, -0.0537109f, 0.378906f, -0.103516f,
-0.378906f, -0.193848f, 0.378906f, -0.296387f, 0.333984f, -0.351562f, 0.302734f, -0.389648f,
-0.259766f, -0.389648f, 0.236328f, -0.389648f, 0.213379f, -0.37793f, 0.195801f, -0.369141f,
-0.155273f, -0.325195f, 0.427246f, -0.460449f, 0.427246f, 0.114746f, 0.427246f, 0.157715f,
-0.433105f, 0.169922f, 0.438965f, 0.182129f, 0.451416f, 0.188965f, 0.463867f, 0.195801f,
-0.5f, 0.195801f, 0.5f, 0.213867f, 0.274414f, 0.213867f, 0.274414f, 0.195801f, 0.283691f,
-0.195801f, 0.311035f, 0.195801f, 0.325195f, 0.187988f, 0.334961f, 0.182617f, 0.34082f,
-0.168701f, 0.34668f, 0.154785f, 0.34668f, 0.114746f, 0.34668f, -0.0776367f, 0.302246f,
--0.0249023f, 0.269043f, -0.00561523f, 0.23584f, 0.0136719f, 0.200195f, 0.0136719f,
-0.135254f, 0.0136719f, 0.0842285f, -0.0454102f, 0.0332031f, -0.104492f, 0.0332031f,
--0.203613f, 0.0332031f, -0.317383f, 0.100586f, -0.388916f, 0.167969f, -0.460449f,
-0.263184f, -0.460449f, 0.291016f, -0.460449f, 0.314453f, -0.452637f, 0.337891f, -0.444824f,
-0.356445f, -0.429199f, 0.384766f, -0.442871f, 0.410645f, -0.460449f, 0.34668f, -0.108398f,
-0.34668f, -0.318359f, 0.34668f, -0.35498f, 0.337158f, -0.375977f, 0.327637f, -0.396973f,
-0.303223f, -0.411621f, 0.278809f, -0.42627f, 0.248047f, -0.42627f, 0.193359f, -0.42627f,
-0.154297f, -0.379883f, 0.115234f, -0.333496f, 0.115234f, -0.239258f, 0.115234f, -0.148926f,
-0.155029f, -0.102051f, 0.194824f, -0.0551758f, 0.250977f, -0.0551758f, 0.279785f,
--0.0551758f, 0.302246f, -0.067627f, 0.324707f, -0.0800781f, 0.34668f, -0.108398f,
-0.162109f, -0.460449f, 0.162109f, -0.359863f, 0.218262f, -0.460449f, 0.277344f, -0.460449f,
-0.304199f, -0.460449f, 0.321777f, -0.444092f, 0.339355f, -0.427734f, 0.339355f, -0.40625f,
-0.339355f, -0.387207f, 0.32666f, -0.374023f, 0.313965f, -0.36084f, 0.296387f, -0.36084f,
-0.279297f, -0.36084f, 0.258057f, -0.377686f, 0.236816f, -0.394531f, 0.226562f, -0.394531f,
-0.217773f, -0.394531f, 0.20752f, -0.384766f, 0.185547f, -0.364746f, 0.162109f, -0.318848f,
-0.162109f, -0.104492f, 0.162109f, -0.0673828f, 0.171387f, -0.0483398f, 0.177734f,
--0.0351562f, 0.193848f, -0.0263672f, 0.209961f, -0.0175781f, 0.240234f, -0.0175781f,
-0.240234f, 0, 0.0112305f, 0, 0.0112305f, -0.0175781f, 0.0454102f, -0.0175781f, 0.0620117f,
--0.0283203f, 0.0742188f, -0.0361328f, 0.0791016f, -0.0532227f, 0.081543f, -0.0615234f,
-0.081543f, -0.100586f, 0.081543f, -0.273926f, 0.081543f, -0.352051f, 0.0783691f,
--0.366943f, 0.0751953f, -0.381836f, 0.0666504f, -0.388672f, 0.0581055f, -0.395508f,
-0.0454102f, -0.395508f, 0.0302734f, -0.395508f, 0.0112305f, -0.388184f, 0.00634766f,
--0.405762f, 0.141602f, -0.460449f, 0.320312f, -0.460449f, 0.320312f, -0.308105f,
-0.304199f, -0.308105f, 0.285645f, -0.379883f, 0.256592f, -0.405762f, 0.227539f, -0.431641f,
-0.182617f, -0.431641f, 0.148438f, -0.431641f, 0.127441f, -0.413574f, 0.106445f, -0.395508f,
-0.106445f, -0.373535f, 0.106445f, -0.346191f, 0.12207f, -0.32666f, 0.137207f, -0.306641f,
-0.183594f, -0.28418f, 0.254883f, -0.249512f, 0.354004f, -0.201172f, 0.354004f, -0.12207f,
-0.354004f, -0.0610352f, 0.307861f, -0.0236816f, 0.261719f, 0.0136719f, 0.20459f,
-0.0136719f, 0.163574f, 0.0136719f, 0.11084f, -0.000976562f, 0.0947266f, -0.00585938f,
-0.0844727f, -0.00585938f, 0.0732422f, -0.00585938f, 0.0668945f, 0.00683594f, 0.0507812f,
-0.00683594f, 0.0507812f, -0.152832f, 0.0668945f, -0.152832f, 0.0805664f, -0.0844727f,
-0.119141f, -0.0498047f, 0.157715f, -0.0151367f, 0.205566f, -0.0151367f, 0.239258f,
--0.0151367f, 0.260498f, -0.0349121f, 0.281738f, -0.0546875f, 0.281738f, -0.0825195f,
-0.281738f, -0.116211f, 0.258057f, -0.13916f, 0.234375f, -0.162109f, 0.163574f, -0.197266f,
-0.0927734f, -0.232422f, 0.0708008f, -0.260742f, 0.0488281f, -0.288574f, 0.0488281f,
--0.331055f, 0.0488281f, -0.38623f, 0.0866699f, -0.42334f, 0.124512f, -0.460449f,
-0.18457f, -0.460449f, 0.210938f, -0.460449f, 0.248535f, -0.449219f, 0.273438f, -0.441895f,
-0.281738f, -0.441895f, 0.289551f, -0.441895f, 0.293945f, -0.445312f, 0.29834f, -0.44873f,
-0.304199f, -0.460449f, 0.161133f, -0.594238f, 0.161133f, -0.447266f, 0.265625f, -0.447266f,
-0.265625f, -0.413086f, 0.161133f, -0.413086f, 0.161133f, -0.123047f, 0.161133f, -0.0795898f,
-0.173584f, -0.0644531f, 0.186035f, -0.0493164f, 0.205566f, -0.0493164f, 0.22168f,
--0.0493164f, 0.236816f, -0.0593262f, 0.251953f, -0.0693359f, 0.260254f, -0.0888672f,
-0.279297f, -0.0888672f, 0.262207f, -0.0410156f, 0.230957f, -0.0168457f, 0.199707f,
-0.00732422f, 0.166504f, 0.00732422f, 0.144043f, 0.00732422f, 0.122559f, -0.00512695f,
-0.101074f, -0.0175781f, 0.0908203f, -0.0407715f, 0.0805664f, -0.0639648f, 0.0805664f,
--0.112305f, 0.0805664f, -0.413086f, 0.00976562f, -0.413086f, 0.00976562f, -0.429199f,
-0.0366211f, -0.439941f, 0.0646973f, -0.465576f, 0.0927734f, -0.491211f, 0.114746f,
--0.526367f, 0.125977f, -0.544922f, 0.145996f, -0.594238f, 0.42334f, -0.447266f, 0.42334f,
--0.17627f, 0.42334f, -0.0986328f, 0.427002f, -0.0812988f, 0.430664f, -0.0639648f,
-0.438721f, -0.0571289f, 0.446777f, -0.050293f, 0.45752f, -0.050293f, 0.472656f, -0.050293f,
-0.491699f, -0.0585938f, 0.498535f, -0.0415039f, 0.364746f, 0.0136719f, 0.342773f,
-0.0136719f, 0.342773f, -0.0810547f, 0.285156f, -0.0185547f, 0.254883f, -0.00244141f,
-0.224609f, 0.0136719f, 0.190918f, 0.0136719f, 0.15332f, 0.0136719f, 0.125732f, -0.00805664f,
-0.0981445f, -0.0297852f, 0.0874023f, -0.0639648f, 0.0766602f, -0.0981445f, 0.0766602f,
--0.160645f, 0.0766602f, -0.360352f, 0.0766602f, -0.39209f, 0.0698242f, -0.404297f,
-0.0629883f, -0.416504f, 0.0495605f, -0.423096f, 0.0361328f, -0.429688f, 0.000976562f,
--0.429199f, 0.000976562f, -0.447266f, 0.157715f, -0.447266f, 0.157715f, -0.147949f,
-0.157715f, -0.0854492f, 0.179443f, -0.065918f, 0.201172f, -0.0463867f, 0.231934f,
--0.0463867f, 0.25293f, -0.0463867f, 0.279541f, -0.0595703f, 0.306152f, -0.0727539f,
-0.342773f, -0.109863f, 0.342773f, -0.363281f, 0.342773f, -0.401367f, 0.328857f, -0.414795f,
-0.314941f, -0.428223f, 0.270996f, -0.429199f, 0.270996f, -0.447266f, 0.00830078f,
--0.447266f, 0.21875f, -0.447266f, 0.21875f, -0.429199f, 0.205078f, -0.429199f, 0.186035f,
--0.429199f, 0.176025f, -0.419922f, 0.166016f, -0.410645f, 0.166016f, -0.39502f, 0.166016f,
--0.37793f, 0.17627f, -0.354492f, 0.280273f, -0.107422f, 0.384766f, -0.36377f, 0.395996f,
--0.391113f, 0.395996f, -0.405273f, 0.395996f, -0.412109f, 0.39209f, -0.416504f, 0.386719f,
--0.423828f, 0.378418f, -0.426514f, 0.370117f, -0.429199f, 0.344727f, -0.429199f,
-0.344727f, -0.447266f, 0.490723f, -0.447266f, 0.490723f, -0.429199f, 0.465332f, -0.427246f,
-0.455566f, -0.418945f, 0.438477f, -0.404297f, 0.424805f, -0.370117f, 0.266113f, 0.0136719f,
-0.246094f, 0.0136719f, 0.0864258f, -0.36377f, 0.0756836f, -0.390137f, 0.065918f,
--0.401611f, 0.0561523f, -0.413086f, 0.0410156f, -0.420898f, 0.0327148f, -0.425293f,
-0.00830078f, -0.429199f, 0.00634766f, -0.447266f, 0.193848f, -0.447266f, 0.193848f,
--0.429199f, 0.167969f, -0.427246f, 0.159912f, -0.419922f, 0.151855f, -0.412598f,
-0.151855f, -0.398926f, 0.151855f, -0.383789f, 0.160156f, -0.362305f, 0.255859f, -0.10498f,
-0.352051f, -0.314453f, 0.32666f, -0.380371f, 0.314941f, -0.409668f, 0.295898f, -0.420898f,
-0.285156f, -0.427734f, 0.255859f, -0.429199f, 0.255859f, -0.447266f, 0.46875f, -0.447266f,
-0.46875f, -0.429199f, 0.433594f, -0.427734f, 0.418945f, -0.416504f, 0.40918f, -0.408691f,
-0.40918f, -0.391602f, 0.40918f, -0.381836f, 0.413086f, -0.371582f, 0.514648f, -0.114746f,
-0.608887f, -0.362305f, 0.618652f, -0.388672f, 0.618652f, -0.404297f, 0.618652f, -0.413574f,
-0.609131f, -0.420898f, 0.599609f, -0.428223f, 0.571777f, -0.429199f, 0.571777f, -0.447266f,
-0.712891f, -0.447266f, 0.712891f, -0.429199f, 0.67041f, -0.422852f, 0.650391f, -0.371582f,
-0.500977f, 0.0136719f, 0.480957f, 0.0136719f, 0.369141f, -0.271973f, 0.23877f, 0.0136719f,
-0.220703f, 0.0136719f, 0.0771484f, -0.362305f, 0.0629883f, -0.397949f, 0.0493164f,
--0.4104f, 0.0356445f, -0.422852f, 0.00634766f, -0.429199f, 0.0131836f, -0.447266f,
-0.223633f, -0.447266f, 0.223633f, -0.429199f, 0.203613f, -0.429199f, 0.195557f, -0.422363f,
-0.1875f, -0.415527f, 0.1875f, -0.404297f, 0.1875f, -0.392578f, 0.20459f, -0.368164f,
-0.209961f, -0.360352f, 0.220703f, -0.34375f, 0.252441f, -0.292969f, 0.289062f, -0.34375f,
-0.324219f, -0.39209f, 0.324219f, -0.404785f, 0.324219f, -0.415039f, 0.315918f, -0.422119f,
-0.307617f, -0.429199f, 0.289062f, -0.429199f, 0.289062f, -0.447266f, 0.44043f, -0.447266f,
-0.44043f, -0.429199f, 0.416504f, -0.427734f, 0.398926f, -0.416016f, 0.375f, -0.399414f,
-0.333496f, -0.34375f, 0.272461f, -0.262207f, 0.383789f, -0.102051f, 0.424805f, -0.0429688f,
-0.442383f, -0.0310059f, 0.459961f, -0.019043f, 0.487793f, -0.0175781f, 0.487793f,
-0, 0.276855f, 0, 0.276855f, -0.0175781f, 0.298828f, -0.0175781f, 0.311035f, -0.0273438f,
-0.320312f, -0.0341797f, 0.320312f, -0.0454102f, 0.320312f, -0.0566406f, 0.289062f,
--0.102051f, 0.223633f, -0.197754f, 0.151855f, -0.102051f, 0.118652f, -0.0576172f,
-0.118652f, -0.0493164f, 0.118652f, -0.0375977f, 0.129639f, -0.0280762f, 0.140625f,
--0.0185547f, 0.162598f, -0.0175781f, 0.162598f, 0, 0.0166016f, 0, 0.0166016f, -0.0175781f,
-0.0341797f, -0.0200195f, 0.0473633f, -0.0297852f, 0.065918f, -0.0439453f, 0.109863f,
--0.102051f, 0.203613f, -0.226562f, 0.118652f, -0.349609f, 0.0825195f, -0.402344f,
-0.0627441f, -0.415771f, 0.0429688f, -0.429199f, 0.0131836f, -0.429199f, 0.00585938f,
--0.447266f, 0.214355f, -0.447266f, 0.214355f, -0.429199f, 0.204102f, -0.429199f,
-0.182129f, -0.429199f, 0.171143f, -0.419678f, 0.160156f, -0.410156f, 0.160156f, -0.395996f,
-0.160156f, -0.376953f, 0.17627f, -0.343262f, 0.285156f, -0.117676f, 0.385254f, -0.364746f,
-0.393555f, -0.384766f, 0.393555f, -0.404297f, 0.393555f, -0.413086f, 0.390137f, -0.41748f,
-0.38623f, -0.422852f, 0.37793f, -0.426025f, 0.369629f, -0.429199f, 0.348633f, -0.429199f,
-0.348633f, -0.447266f, 0.494141f, -0.447266f, 0.494141f, -0.429199f, 0.476074f, -0.427246f,
-0.466309f, -0.421387f, 0.456543f, -0.415527f, 0.444824f, -0.399414f, 0.44043f, -0.392578f,
-0.428223f, -0.361816f, 0.246094f, 0.0844727f, 0.219727f, 0.149414f, 0.177002f, 0.182617f,
-0.134277f, 0.21582f, 0.0947266f, 0.21582f, 0.065918f, 0.21582f, 0.0473633f, 0.199219f,
-0.0288086f, 0.182617f, 0.0288086f, 0.161133f, 0.0288086f, 0.140625f, 0.0422363f,
-0.128174f, 0.0556641f, 0.115723f, 0.0791016f, 0.115723f, 0.0952148f, 0.115723f, 0.123047f,
-0.126465f, 0.142578f, 0.133789f, 0.147461f, 0.133789f, 0.162109f, 0.133789f, 0.179443f,
-0.118652f, 0.196777f, 0.103516f, 0.214355f, 0.0600586f, 0.246094f, -0.0175781f, 0.0854492f,
--0.35498f, 0.078125f, -0.370117f, 0.0620117f, -0.392578f, 0.0498047f, -0.409668f,
-0.0419922f, -0.415527f, 0.0307617f, -0.42334f, 0.00585938f, -0.429199f, 0.419922f,
--0.137207f, 0.414551f, 0, 0.0200195f, 0, 0.0200195f, -0.0175781f, 0.316895f, -0.413086f,
-0.17041f, -0.413086f, 0.123047f, -0.413086f, 0.108398f, -0.406982f, 0.09375f, -0.400879f,
-0.0844727f, -0.383789f, 0.0712891f, -0.359375f, 0.0693359f, -0.323242f, 0.0498047f,
--0.323242f, 0.0527344f, -0.447266f, 0.427734f, -0.447266f, 0.427734f, -0.429199f,
-0.12793f, -0.0327148f, 0.291016f, -0.0327148f, 0.342285f, -0.0327148f, 0.360596f,
--0.0412598f, 0.378906f, -0.0498047f, 0.390137f, -0.0712891f, 0.397949f, -0.0869141f,
-0.40332f, -0.137207f
-};
-
-const unsigned char TimesNewRomankNormalVerbs[] = {
-6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2,
-2, 2, 2, 2, 1, 5, 0, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1,
-2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 5,
-0, 1, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1,
-2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1,
-1, 5, 6, 0, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1,
-1, 2, 2, 1, 1, 1, 2, 2, 2, 5, 0, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1,
-1, 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 1, 1, 1, 2,
-2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2,
-2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1,
-1, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2,
-1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-2, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2,
-2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2,
-2, 5, 6, 0, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2,
-2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2,
-2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 1,
-1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2,
-2, 2, 2, 2, 1, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2,
-2, 1, 1, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2,
-1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
-1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1,
-1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2,
-2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2,
-1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 5, 6,
-0, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5,
-6, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0,
-1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 5, 0, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2,
-2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,
-1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1,
-1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1,
-2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2,
-1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2,
-2, 2, 2, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2,
-2, 1, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1,
-1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2,
-2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1,
-1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 5, 6, 0, 1, 1, 2,
-2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2,
-2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1,
-1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1,
-1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 5, 6
-};
-
-const unsigned TimesNewRomankNormalCharCodes[] = {
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84,
-86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105,
-106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
-122
-};
-
-const SkFixed TimesNewRomankNormalWidths[] = {
-0x00004000, 0x00005540, 0x00006880, 0x00008000, 0x00008000, 0x0000d540, 0x0000c720,
-0x00002e20, 0x00005540, 0x00005540, 0x00008000, 0x00009060, 0x00004000, 0x00005540,
-0x00004000, 0x00004720, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000,
-0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00004720, 0x00009060, 0x00009060,
-0x00009060, 0x000071a0, 0x0000ebc0, 0x0000b8e0, 0x0000aac0, 0x0000aac0, 0x0000b8e0,
-0x00009c60, 0x00008e60, 0x0000b8e0, 0x0000b8e0, 0x00005540, 0x000063a0, 0x0000b8e0,
-0x00009c60, 0x0000e3a0, 0x0000b8e0, 0x00008e60, 0x0000b8e0, 0x0000aac0, 0x00008e60,
-0x00009c60, 0x0000b8e0, 0x0000f1a0, 0x0000b8e0, 0x0000b8e0, 0x00009c60, 0x00005540,
-0x00004720, 0x00005540, 0x00007820, 0x00008000, 0x00005540, 0x000071a0, 0x00008000,
-0x000071a0, 0x00008000, 0x000071a0, 0x00005540, 0x00008000, 0x00004720, 0x00004720,
-0x00008000, 0x00004720, 0x0000c720, 0x00008000, 0x00008000, 0x00008000, 0x00008000,
-0x00005540, 0x000063a0, 0x00004720, 0x00008000, 0x00008000, 0x0000b8e0, 0x00008000,
-0x00008000, 0x000071a0
-};
-
-const int TimesNewRomankNormalCharCodesCount = (int) SK_ARRAY_COUNT(TimesNewRomankNormalCharCodes);
-
-const SkPaint::FontMetrics TimesNewRomankNormalMetrics = {
-0x2d202c67, -1.00684f, -0.891113f, 0.216309f, 0.306641f, 0.0424805f, 2.56836f, 4.1423e-11f,
--0.568359f, 2, 0.460449f, 1.01859e-11f, 0.0488281f, 0.108887f
-};
-
-const SkScalar TimesNewRomankBoldPoints[] = {
-0.177734f, -0.215332f, 0.15625f, -0.215332f, 0.152832f, -0.270996f, 0.133789f, -0.350098f,
-0.108398f, -0.456543f, 0.0854492f, -0.552246f, 0.0854492f, -0.59375f, 0.0854492f,
--0.631348f, 0.10791f, -0.654297f, 0.130371f, -0.677246f, 0.166504f, -0.677246f, 0.20166f,
--0.677246f, 0.224854f, -0.654053f, 0.248047f, -0.630859f, 0.248047f, -0.595215f,
-0.248047f, -0.558105f, 0.223633f, -0.456543f, 0.197754f, -0.350098f, 0.184082f, -0.293457f,
-0.177734f, -0.215332f, 0.16748f, -0.145508f, 0.200195f, -0.145508f, 0.223389f, -0.122314f,
-0.246582f, -0.0991211f, 0.246582f, -0.065918f, 0.246582f, -0.0332031f, 0.223389f,
--0.0100098f, 0.200195f, 0.0131836f, 0.16748f, 0.0131836f, 0.134766f, 0.0131836f,
-0.111572f, -0.0100098f, 0.0883789f, -0.0332031f, 0.0883789f, -0.065918f, 0.0883789f,
--0.0986328f, 0.111328f, -0.12207f, 0.134277f, -0.145508f, 0.16748f, -0.145508f, 0.17041f,
--0.352051f, 0.146484f, -0.352051f, 0.0957031f, -0.540039f, 0.0859375f, -0.57666f,
-0.0859375f, -0.604492f, 0.0859375f, -0.634766f, 0.107178f, -0.656006f, 0.128418f,
--0.677246f, 0.158203f, -0.677246f, 0.192383f, -0.677246f, 0.211426f, -0.655029f,
-0.230469f, -0.632812f, 0.230469f, -0.606934f, 0.230469f, -0.584961f, 0.21875f, -0.539062f,
-0.40625f, -0.352051f, 0.381836f, -0.352051f, 0.33252f, -0.539551f, 0.320801f, -0.58252f,
-0.320801f, -0.605957f, 0.320801f, -0.634277f, 0.342529f, -0.655762f, 0.364258f, -0.677246f,
-0.394531f, -0.677246f, 0.429199f, -0.677246f, 0.44751f, -0.654297f, 0.46582f, -0.631348f,
-0.46582f, -0.607422f, 0.46582f, -0.590332f, 0.453125f, -0.539551f, 0.0439453f, 0.0136719f,
-0.0859375f, -0.193359f, 0.0195312f, -0.193359f, 0.0195312f, -0.258301f, 0.0986328f,
--0.258301f, 0.127441f, -0.400879f, 0.0195312f, -0.400879f, 0.0195312f, -0.464355f,
-0.140137f, -0.464355f, 0.182617f, -0.675781f, 0.24707f, -0.675781f, 0.204102f, -0.464355f,
-0.348145f, -0.464355f, 0.390137f, -0.675781f, 0.45459f, -0.675781f, 0.411621f, -0.464355f,
-0.47998f, -0.464355f, 0.47998f, -0.400879f, 0.399414f, -0.400879f, 0.370117f, -0.258301f,
-0.47998f, -0.258301f, 0.47998f, -0.193359f, 0.35791f, -0.193359f, 0.315918f, 0.0136719f,
-0.250977f, 0.0136719f, 0.292969f, -0.193359f, 0.150879f, -0.193359f, 0.106934f, 0.0136719f,
-0.163574f, -0.258301f, 0.307129f, -0.258301f, 0.335449f, -0.400879f, 0.191895f, -0.400879f,
-0.276367f, -0.407715f, 0.393066f, -0.333984f, 0.425293f, -0.296387f, 0.468262f, -0.245605f,
-0.468262f, -0.176758f, 0.468262f, -0.101562f, 0.41748f, -0.0495605f, 0.366699f, 0.00244141f,
-0.276367f, 0.0102539f, 0.276367f, 0.0673828f, 0.233887f, 0.0673828f, 0.233887f, 0.0136719f,
-0.182129f, 0.0126953f, 0.14209f, 0.00512695f, 0.102051f, -0.00244141f, 0.050293f,
--0.0224609f, 0.050293f, -0.180176f, 0.0708008f, -0.180176f, 0.0805664f, -0.126465f,
-0.101562f, -0.0932617f, 0.122559f, -0.0600586f, 0.154541f, -0.0432129f, 0.186523f,
--0.0263672f, 0.233887f, -0.0224609f, 0.233887f, -0.263672f, 0.116211f, -0.337402f,
-0.0773926f, -0.381592f, 0.0385742f, -0.425781f, 0.0385742f, -0.484375f, 0.0385742f,
--0.547852f, 0.0874023f, -0.596436f, 0.13623f, -0.64502f, 0.233887f, -0.657227f, 0.233887f,
--0.680176f, 0.276367f, -0.680176f, 0.276367f, -0.657227f, 0.359375f, -0.651367f,
-0.443359f, -0.605957f, 0.443359f, -0.464844f, 0.424316f, -0.464844f, 0.410156f, -0.512695f,
-0.390381f, -0.543457f, 0.370605f, -0.574219f, 0.339355f, -0.596191f, 0.31543f, -0.612305f,
-0.276367f, -0.623047f, 0.233887f, -0.624512f, 0.198242f, -0.621582f, 0.176758f, -0.60498f,
-0.142578f, -0.579102f, 0.142578f, -0.54248f, 0.142578f, -0.52002f, 0.158447f, -0.49707f,
-0.174316f, -0.474121f, 0.233887f, -0.43457f, 0.276367f, -0.0224609f, 0.318359f, -0.0322266f,
-0.337891f, -0.0559082f, 0.357422f, -0.0795898f, 0.357422f, -0.115234f, 0.357422f,
--0.145996f, 0.340088f, -0.172852f, 0.322754f, -0.199707f, 0.276367f, -0.233887f,
-0.768066f, -0.677246f, 0.297852f, 0.027832f, 0.232422f, 0.027832f, 0.702148f, -0.677246f,
-0.233398f, -0.677246f, 0.302734f, -0.677246f, 0.350342f, -0.628174f, 0.397949f, -0.579102f,
-0.397949f, -0.501465f, 0.397949f, -0.421875f, 0.350098f, -0.372314f, 0.302246f, -0.322754f,
-0.231445f, -0.322754f, 0.161621f, -0.322754f, 0.115479f, -0.370605f, 0.0693359f,
--0.418457f, 0.0693359f, -0.496582f, 0.0693359f, -0.577148f, 0.116699f, -0.627197f,
-0.164062f, -0.677246f, 0.233398f, -0.677246f, 0.233398f, -0.651367f, 0.222656f, -0.651367f,
-0.21582f, -0.64502f, 0.203613f, -0.633789f, 0.19751f, -0.606201f, 0.191406f, -0.578613f,
-0.191406f, -0.492188f, 0.191406f, -0.42334f, 0.199707f, -0.385742f, 0.20459f, -0.364258f,
-0.216309f, -0.353516f, 0.223633f, -0.347168f, 0.233398f, -0.347168f, 0.244141f, -0.347168f,
-0.250488f, -0.353027f, 0.261719f, -0.363281f, 0.26709f, -0.38623f, 0.275391f, -0.42334f,
-0.275391f, -0.490234f, 0.275391f, -0.572266f, 0.267578f, -0.608887f, 0.262207f, -0.634277f,
-0.25f, -0.645996f, 0.244141f, -0.651367f, 0.233398f, -0.651367f, 0.764648f, -0.327637f,
-0.835449f, -0.327637f, 0.883057f, -0.279053f, 0.930664f, -0.230469f, 0.930664f, -0.151855f,
-0.930664f, -0.0722656f, 0.882324f, -0.0224609f, 0.833984f, 0.0273438f, 0.765625f,
-0.0273438f, 0.697754f, 0.0273438f, 0.650146f, -0.0224609f, 0.602539f, -0.0722656f,
-0.602539f, -0.150391f, 0.602539f, -0.229004f, 0.648926f, -0.27832f, 0.695312f, -0.327637f,
-0.764648f, -0.327637f, 0.766113f, -0.302246f, 0.756348f, -0.302246f, 0.749512f, -0.296387f,
-0.737793f, -0.285645f, 0.731445f, -0.259033f, 0.725098f, -0.232422f, 0.725098f, -0.157227f,
-0.725098f, -0.0771484f, 0.732422f, -0.0419922f, 0.737793f, -0.0170898f, 0.750488f,
--0.00585938f, 0.756836f, 0, 0.76709f, 0, 0.776367f, 0, 0.782227f, -0.00537109f, 0.794434f,
--0.0166016f, 0.800293f, -0.0419922f, 0.808594f, -0.0776367f, 0.808594f, -0.149902f,
-0.808594f, -0.226074f, 0.800781f, -0.26123f, 0.794922f, -0.286621f, 0.783203f, -0.296875f,
-0.777344f, -0.302246f, 0.766113f, -0.302246f, 0.569336f, -0.395996f, 0.772461f, -0.395996f,
-0.772461f, -0.376953f, 0.738281f, -0.37207f, 0.71875f, -0.356689f, 0.699219f, -0.341309f,
-0.667969f, -0.285156f, 0.636719f, -0.229004f, 0.580078f, -0.159668f, 0.629883f, -0.114746f,
-0.661133f, -0.097168f, 0.683105f, -0.0849609f, 0.704102f, -0.0849609f, 0.740234f,
--0.0849609f, 0.769531f, -0.132324f, 0.789551f, -0.121582f, 0.749512f, -0.0429688f,
-0.704102f, -0.00976562f, 0.669434f, 0.0151367f, 0.625f, 0.0151367f, 0.586914f, 0.0151367f,
-0.55249f, -0.0012207f, 0.518066f, -0.0175781f, 0.46875f, -0.0625f, 0.407715f, -0.0214844f,
-0.354004f, -0.00317383f, 0.300293f, 0.0151367f, 0.242188f, 0.0151367f, 0.149414f,
-0.0151367f, 0.0947266f, -0.0351562f, 0.0400391f, -0.0854492f, 0.0400391f, -0.15332f,
-0.0400391f, -0.226562f, 0.0922852f, -0.280762f, 0.144531f, -0.334961f, 0.244141f,
--0.374512f, 0.231445f, -0.40625f, 0.225098f, -0.436523f, 0.21875f, -0.466797f, 0.21875f,
--0.495117f, 0.21875f, -0.573242f, 0.273682f, -0.625244f, 0.328613f, -0.677246f, 0.414062f,
--0.677246f, 0.48291f, -0.677246f, 0.523193f, -0.642822f, 0.563477f, -0.608398f, 0.563477f,
--0.5625f, 0.563477f, -0.507324f, 0.522217f, -0.468018f, 0.480957f, -0.428711f, 0.391602f,
--0.395996f, 0.446777f, -0.298828f, 0.553223f, -0.186523f, 0.625f, -0.26709f, 0.625f,
--0.324707f, 0.625f, -0.345215f, 0.61084f, -0.359619f, 0.59668f, -0.374023f, 0.569336f,
--0.376953f, 0.375f, -0.425293f, 0.42627f, -0.444336f, 0.443848f, -0.466064f, 0.461426f,
--0.487793f, 0.461426f, -0.518555f, 0.461426f, -0.573242f, 0.432617f, -0.61084f, 0.413574f,
--0.635742f, 0.385742f, -0.635742f, 0.362793f, -0.635742f, 0.346436f, -0.617676f,
-0.330078f, -0.599609f, 0.330078f, -0.568848f, 0.330078f, -0.544922f, 0.337891f, -0.517578f,
-0.345703f, -0.490234f, 0.375f, -0.425293f, 0.257812f, -0.343262f, 0.21875f, -0.32666f,
-0.202637f, -0.308105f, 0.179688f, -0.280762f, 0.179688f, -0.24707f, 0.179688f, -0.201172f,
-0.206299f, -0.155762f, 0.23291f, -0.110352f, 0.270508f, -0.0854492f, 0.308105f, -0.0605469f,
-0.345703f, -0.0605469f, 0.364258f, -0.0605469f, 0.387451f, -0.0686035f, 0.410645f,
--0.0766602f, 0.437988f, -0.0927734f, 0.320312f, -0.213379f, 0.257812f, -0.343262f,
-0.152832f, -0.352539f, 0.129395f, -0.352539f, 0.078125f, -0.539062f, 0.0683594f,
--0.57373f, 0.0683594f, -0.603027f, 0.0683594f, -0.634766f, 0.0891113f, -0.656006f,
-0.109863f, -0.677246f, 0.140137f, -0.677246f, 0.174805f, -0.677246f, 0.193604f, -0.654785f,
-0.212402f, -0.632324f, 0.212402f, -0.605957f, 0.212402f, -0.583984f, 0.201172f, -0.539551f,
-0.321289f, -0.677246f, 0.321289f, -0.654785f, 0.270508f, -0.621582f, 0.246582f, -0.589844f,
-0.213379f, -0.545898f, 0.194824f, -0.477051f, 0.171387f, -0.391602f, 0.171387f, -0.238281f,
-0.171387f, -0.09375f, 0.192627f, -0.0136719f, 0.213867f, 0.0664062f, 0.250488f, 0.115723f,
-0.275879f, 0.149902f, 0.321289f, 0.175781f, 0.321289f, 0.200195f, 0.203613f, 0.160645f,
-0.121826f, 0.0388184f, 0.0400391f, -0.0830078f, 0.0400391f, -0.241211f, 0.0400391f,
--0.397461f, 0.121582f, -0.517822f, 0.203125f, -0.638184f, 0.321289f, -0.677246f,
-0.012207f, 0.200195f, 0.012207f, 0.177734f, 0.0629883f, 0.144043f, 0.0869141f, 0.112305f,
-0.119629f, 0.0683594f, 0.138672f, 0, 0.162109f, -0.0859375f, 0.162109f, -0.239258f,
-0.162109f, -0.383789f, 0.140869f, -0.463623f, 0.119629f, -0.543457f, 0.0830078f,
--0.592773f, 0.0576172f, -0.626953f, 0.012207f, -0.652832f, 0.012207f, -0.677246f,
-0.129883f, -0.637695f, 0.21167f, -0.515869f, 0.293457f, -0.394043f, 0.293457f, -0.23584f,
-0.293457f, -0.0800781f, 0.21167f, 0.0402832f, 0.129883f, 0.160645f, 0.012207f, 0.200195f,
-0.240723f, -0.484375f, 0.239258f, -0.512695f, 0.235107f, -0.527344f, 0.230957f, -0.541992f,
-0.215088f, -0.572754f, 0.199219f, -0.603516f, 0.199219f, -0.620605f, 0.199219f, -0.643066f,
-0.215088f, -0.660156f, 0.230957f, -0.677246f, 0.25f, -0.677246f, 0.270996f, -0.677246f,
-0.286377f, -0.661377f, 0.301758f, -0.645508f, 0.301758f, -0.620117f, 0.301758f, -0.600098f,
-0.286621f, -0.571777f, 0.271484f, -0.543457f, 0.267334f, -0.528564f, 0.263184f, -0.513672f,
-0.260742f, -0.484375f, 0.288086f, -0.495605f, 0.299805f, -0.503906f, 0.311523f, -0.512207f,
-0.334473f, -0.536621f, 0.365234f, -0.569336f, 0.393555f, -0.569336f, 0.415039f, -0.569336f,
-0.429688f, -0.555176f, 0.444336f, -0.541016f, 0.444336f, -0.521484f, 0.444336f, -0.500488f,
-0.42627f, -0.484375f, 0.408203f, -0.468262f, 0.379395f, -0.468262f, 0.369629f, -0.468262f,
-0.344727f, -0.469727f, 0.333008f, -0.470215f, 0.319336f, -0.470215f, 0.30127f, -0.470215f,
-0.264648f, -0.468262f, 0.285645f, -0.444336f, 0.297363f, -0.435303f, 0.309082f, -0.42627f,
-0.337891f, -0.411621f, 0.366699f, -0.396973f, 0.379395f, -0.380371f, 0.388672f, -0.368164f,
-0.388672f, -0.349121f, 0.388672f, -0.328125f, 0.374512f, -0.313721f, 0.360352f, -0.299316f,
-0.340332f, -0.299316f, 0.319336f, -0.299316f, 0.30249f, -0.31665f, 0.285645f, -0.333984f,
-0.279297f, -0.378418f, 0.275391f, -0.407227f, 0.270752f, -0.42041f, 0.266113f, -0.433594f,
-0.250977f, -0.458984f, 0.234863f, -0.433105f, 0.229492f, -0.418945f, 0.224121f, -0.404785f,
-0.220215f, -0.378418f, 0.213867f, -0.333984f, 0.197754f, -0.317383f, 0.181641f, -0.300781f,
-0.160156f, -0.300781f, 0.140137f, -0.300781f, 0.125732f, -0.314453f, 0.111328f, -0.328125f,
-0.111328f, -0.347168f, 0.111328f, -0.366699f, 0.122314f, -0.38208f, 0.133301f, -0.397461f,
-0.162842f, -0.413818f, 0.192383f, -0.430176f, 0.203613f, -0.438477f, 0.214844f, -0.446777f,
-0.236328f, -0.468262f, 0.184082f, -0.470215f, 0.17041f, -0.470215f, 0.158203f, -0.469727f,
-0.129395f, -0.467773f, 0.118652f, -0.467773f, 0.0908203f, -0.467773f, 0.0732422f,
--0.483398f, 0.0556641f, -0.499023f, 0.0556641f, -0.520508f, 0.0556641f, -0.540527f,
-0.0700684f, -0.554932f, 0.0844727f, -0.569336f, 0.106445f, -0.569336f, 0.137207f,
--0.569336f, 0.165527f, -0.540039f, 0.193848f, -0.510742f, 0.202148f, -0.504395f,
-0.213867f, -0.496094f, 0.240723f, -0.484375f, 0.0195312f, -0.363281f, 0.254395f,
--0.363281f, 0.254395f, -0.597656f, 0.318359f, -0.597656f, 0.318359f, -0.363281f,
-0.553223f, -0.363281f, 0.553223f, -0.298828f, 0.318359f, -0.298828f, 0.318359f, -0.0664062f,
-0.254395f, -0.0664062f, 0.254395f, -0.298828f, 0.0195312f, -0.298828f, 0.0498047f,
-0.175293f, 0.0498047f, 0.153809f, 0.106445f, 0.129395f, 0.13208f, 0.0905762f, 0.157715f,
-0.0517578f, 0.157715f, 0.0112305f, 0.157715f, 0.00292969f, 0.154297f, -0.00146484f,
-0.150879f, -0.00537109f, 0.147461f, -0.00537109f, 0.144531f, -0.00537109f, 0.138672f,
--0.00195312f, 0.124512f, 0.00634766f, 0.103516f, 0.00634766f, 0.074707f, 0.00634766f,
-0.0534668f, -0.0161133f, 0.0322266f, -0.0385742f, 0.0322266f, -0.0688477f, 0.0322266f,
--0.101074f, 0.0566406f, -0.125488f, 0.0810547f, -0.149902f, 0.115723f, -0.149902f,
-0.157715f, -0.149902f, 0.1875f, -0.117432f, 0.217285f, -0.0849609f, 0.217285f, -0.0283203f,
-0.217285f, 0.0415039f, 0.175049f, 0.0957031f, 0.132812f, 0.149902f, 0.0498047f, 0.175293f,
-0.309082f, -0.179199f, 0.0244141f, -0.179199f, 0.0244141f, -0.280273f, 0.309082f,
--0.280273f, 0.125f, -0.150391f, 0.15918f, -0.150391f, 0.182861f, -0.126465f, 0.206543f,
--0.102539f, 0.206543f, -0.0688477f, 0.206543f, -0.0351562f, 0.182617f, -0.0114746f,
-0.158691f, 0.012207f, 0.125f, 0.012207f, 0.0913086f, 0.012207f, 0.067627f, -0.0114746f,
-0.0439453f, -0.0351562f, 0.0439453f, -0.0688477f, 0.0439453f, -0.102539f, 0.067627f,
--0.126465f, 0.0913086f, -0.150391f, 0.125f, -0.150391f, 0.280762f, -0.677246f, 0.0634766f,
-0.0151367f, 0.000976562f, 0.0151367f, 0.219238f, -0.677246f, 0.463379f, -0.331055f,
-0.463379f, -0.231934f, 0.435547f, -0.145996f, 0.418945f, -0.0932617f, 0.390869f,
--0.0595703f, 0.362793f, -0.0258789f, 0.327148f, -0.00610352f, 0.291504f, 0.0136719f,
-0.249512f, 0.0136719f, 0.20166f, 0.0136719f, 0.163086f, -0.0107422f, 0.124512f, -0.0351562f,
-0.0947266f, -0.0805664f, 0.0732422f, -0.11377f, 0.0571289f, -0.168945f, 0.0361328f,
--0.243652f, 0.0361328f, -0.323242f, 0.0361328f, -0.431152f, 0.0664062f, -0.521484f,
-0.0913086f, -0.596191f, 0.14209f, -0.635986f, 0.192871f, -0.675781f, 0.249512f, -0.675781f,
-0.307129f, -0.675781f, 0.357178f, -0.636475f, 0.407227f, -0.597168f, 0.430664f, -0.530762f,
-0.463379f, -0.439453f, 0.463379f, -0.331055f, 0.312988f, -0.332031f, 0.312988f, -0.505859f,
-0.311035f, -0.534668f, 0.306152f, -0.602539f, 0.287598f, -0.626465f, 0.275391f, -0.64209f,
-0.248047f, -0.64209f, 0.227051f, -0.64209f, 0.214844f, -0.630371f, 0.196777f, -0.613281f,
-0.19043f, -0.570068f, 0.184082f, -0.526855f, 0.184082f, -0.268555f, 0.184082f, -0.12793f,
-0.193848f, -0.0800781f, 0.201172f, -0.0454102f, 0.214844f, -0.0336914f, 0.228516f,
--0.0219727f, 0.250977f, -0.0219727f, 0.275391f, -0.0219727f, 0.287598f, -0.0375977f,
-0.308105f, -0.0649414f, 0.311035f, -0.12207f, 0.325684f, -0.675781f, 0.325684f, -0.134277f,
-0.325684f, -0.0732422f, 0.331055f, -0.0563965f, 0.336426f, -0.0395508f, 0.353516f,
--0.0288086f, 0.370605f, -0.0180664f, 0.408203f, -0.0180664f, 0.42334f, -0.0180664f,
-0.42334f, 0, 0.074707f, 0, 0.074707f, -0.0180664f, 0.0922852f, -0.0180664f, 0.134766f,
--0.0180664f, 0.152832f, -0.027832f, 0.170898f, -0.0375977f, 0.177246f, -0.0546875f,
-0.183594f, -0.0717773f, 0.183594f, -0.134277f, 0.183594f, -0.477539f, 0.183594f,
--0.523438f, 0.179199f, -0.534912f, 0.174805f, -0.546387f, 0.162842f, -0.554443f,
-0.150879f, -0.5625f, 0.135254f, -0.5625f, 0.110352f, -0.5625f, 0.074707f, -0.546875f,
-0.065918f, -0.564453f, 0.30957f, -0.675781f, 0.414062f, 0, 0.0244141f, 0, 0.0244141f,
--0.0107422f, 0.203613f, -0.224121f, 0.241943f, -0.297852f, 0.280273f, -0.371582f,
-0.280273f, -0.441895f, 0.280273f, -0.493164f, 0.248535f, -0.5271f, 0.216797f, -0.561035f,
-0.170898f, -0.561035f, 0.0957031f, -0.561035f, 0.0541992f, -0.48584f, 0.0361328f,
--0.492188f, 0.0625f, -0.585938f, 0.116211f, -0.630859f, 0.169922f, -0.675781f, 0.240234f,
--0.675781f, 0.290527f, -0.675781f, 0.332031f, -0.652344f, 0.373535f, -0.628906f,
-0.396973f, -0.588135f, 0.42041f, -0.547363f, 0.42041f, -0.511719f, 0.42041f, -0.446777f,
-0.384277f, -0.379883f, 0.334961f, -0.289551f, 0.168945f, -0.12793f, 0.312012f, -0.12793f,
-0.364746f, -0.12793f, 0.380615f, -0.132324f, 0.396484f, -0.136719f, 0.406738f, -0.147217f,
-0.416992f, -0.157715f, 0.433594f, -0.191406f, 0.451172f, -0.191406f, 0.147949f, -0.332031f,
-0.147949f, -0.349121f, 0.203613f, -0.365234f, 0.225098f, -0.37915f, 0.246582f, -0.393066f,
-0.262207f, -0.421631f, 0.277832f, -0.450195f, 0.277832f, -0.479492f, 0.277832f, -0.52002f,
-0.248291f, -0.549072f, 0.21875f, -0.578125f, 0.174805f, -0.578125f, 0.106445f, -0.578125f,
-0.0585938f, -0.505859f, 0.0405273f, -0.512207f, 0.0756836f, -0.59375f, 0.130615f,
--0.634766f, 0.185547f, -0.675781f, 0.25293f, -0.675781f, 0.321777f, -0.675781f, 0.366455f,
--0.633789f, 0.411133f, -0.591797f, 0.411133f, -0.535645f, 0.411133f, -0.499023f,
-0.390381f, -0.465088f, 0.369629f, -0.431152f, 0.325195f, -0.405273f, 0.382324f, -0.377441f,
-0.412354f, -0.33667f, 0.442383f, -0.295898f, 0.442383f, -0.234375f, 0.442383f, -0.130859f,
-0.367432f, -0.0583496f, 0.29248f, 0.0141602f, 0.166504f, 0.0141602f, 0.0825195f,
-0.0141602f, 0.0439453f, -0.0136719f, 0.0161133f, -0.0332031f, 0.0161133f, -0.0639648f,
-0.0161133f, -0.0864258f, 0.0322266f, -0.102295f, 0.0483398f, -0.118164f, 0.0693359f,
--0.118164f, 0.0854492f, -0.118164f, 0.0996094f, -0.111328f, 0.107422f, -0.107422f,
-0.155029f, -0.0686035f, 0.202637f, -0.0297852f, 0.244141f, -0.0297852f, 0.280273f,
--0.0297852f, 0.306152f, -0.0583496f, 0.332031f, -0.0869141f, 0.332031f, -0.130859f,
-0.332031f, -0.197754f, 0.285156f, -0.25415f, 0.238281f, -0.310547f, 0.147949f, -0.332031f,
-0.0249023f, -0.249512f, 0.339355f, -0.675781f, 0.398926f, -0.675781f, 0.398926f,
--0.249512f, 0.459473f, -0.249512f, 0.459473f, -0.148438f, 0.398926f, -0.148438f,
-0.398926f, 0, 0.264648f, 0, 0.264648f, -0.148438f, 0.0249023f, -0.148438f, 0.0722656f,
--0.249512f, 0.264648f, -0.249512f, 0.264648f, -0.510742f, 0.152344f, -0.662109f,
-0.462402f, -0.662109f, 0.413086f, -0.536133f, 0.152344f, -0.536133f, 0.127441f, -0.470215f,
-0.295898f, -0.463867f, 0.386719f, -0.38623f, 0.461426f, -0.322266f, 0.461426f, -0.227051f,
-0.461426f, -0.166016f, 0.426758f, -0.107666f, 0.39209f, -0.0493164f, 0.329102f, -0.0178223f,
-0.266113f, 0.0136719f, 0.190918f, 0.0136719f, 0.109863f, 0.0136719f, 0.0664062f,
--0.0166016f, 0.0361328f, -0.0380859f, 0.0361328f, -0.0654297f, 0.0361328f, -0.0864258f,
-0.052002f, -0.102539f, 0.0678711f, -0.118652f, 0.0888672f, -0.118652f, 0.10791f,
--0.118652f, 0.127441f, -0.11084f, 0.146973f, -0.103027f, 0.194336f, -0.0698242f,
-0.224121f, -0.0493164f, 0.245605f, -0.0415039f, 0.260742f, -0.0356445f, 0.279785f,
--0.0356445f, 0.319824f, -0.0356445f, 0.3479f, -0.0649414f, 0.375977f, -0.0942383f,
-0.375977f, -0.135254f, 0.375977f, -0.221191f, 0.290039f, -0.274902f, 0.204102f, -0.328613f,
-0.0732422f, -0.328613f, 0.0600586f, -0.328613f, 0.0336914f, -0.328125f, 0.469727f,
--0.675781f, 0.469727f, -0.662109f, 0.381348f, -0.639648f, 0.327881f, -0.604248f,
-0.274414f, -0.568848f, 0.243408f, -0.518311f, 0.212402f, -0.467773f, 0.195312f, -0.393066f,
-0.216797f, -0.407715f, 0.230957f, -0.412109f, 0.262695f, -0.421875f, 0.294922f, -0.421875f,
-0.369141f, -0.421875f, 0.418701f, -0.36792f, 0.468262f, -0.313965f, 0.468262f, -0.220703f,
-0.468262f, -0.155273f, 0.441406f, -0.100586f, 0.414551f, -0.0458984f, 0.365234f,
--0.0161133f, 0.315918f, 0.0136719f, 0.259766f, 0.0136719f, 0.19873f, 0.0136719f,
-0.146973f, -0.0197754f, 0.0952148f, -0.0532227f, 0.0661621f, -0.117676f, 0.0371094f,
--0.182129f, 0.0371094f, -0.257812f, 0.0371094f, -0.369141f, 0.0905762f, -0.465088f,
-0.144043f, -0.561035f, 0.242432f, -0.61792f, 0.34082f, -0.674805f, 0.469727f, -0.675781f,
-0.188965f, -0.353516f, 0.185059f, -0.286133f, 0.185059f, -0.254883f, 0.185059f, -0.1875f,
-0.197998f, -0.124512f, 0.210938f, -0.0615234f, 0.233398f, -0.0361328f, 0.249512f,
--0.0180664f, 0.271484f, -0.0180664f, 0.293945f, -0.0180664f, 0.311523f, -0.0441895f,
-0.329102f, -0.0703125f, 0.329102f, -0.150391f, 0.329102f, -0.285156f, 0.296387f,
--0.336426f, 0.275391f, -0.369629f, 0.239746f, -0.369629f, 0.220215f, -0.369629f,
-0.188965f, -0.353516f, 0.177246f, 0.0136719f, 0.357422f, -0.532715f, 0.220215f, -0.532715f,
-0.139648f, -0.532715f, 0.0991211f, -0.511719f, 0.0708008f, -0.49707f, 0.0522461f,
--0.456543f, 0.0336914f, -0.456543f, 0.081543f, -0.662109f, 0.476074f, -0.662109f,
-0.253906f, 0.0136719f, 0.34082f, -0.374023f, 0.410645f, -0.322754f, 0.437744f, -0.278564f,
-0.464844f, -0.234375f, 0.464844f, -0.177246f, 0.464844f, -0.097168f, 0.404541f, -0.041748f,
-0.344238f, 0.0136719f, 0.240723f, 0.0136719f, 0.142578f, 0.0136719f, 0.0888672f,
--0.034668f, 0.0351562f, -0.0830078f, 0.0351562f, -0.152832f, 0.0351562f, -0.206055f,
-0.0661621f, -0.246094f, 0.097168f, -0.286133f, 0.169434f, -0.319336f, 0.0908203f,
--0.379395f, 0.0686035f, -0.41748f, 0.0463867f, -0.455566f, 0.0463867f, -0.505859f,
-0.0463867f, -0.572266f, 0.102783f, -0.622803f, 0.15918f, -0.67334f, 0.257324f, -0.67334f,
-0.352051f, -0.67334f, 0.403076f, -0.628662f, 0.454102f, -0.583984f, 0.454102f, -0.521484f,
-0.454102f, -0.474609f, 0.426514f, -0.438721f, 0.398926f, -0.402832f, 0.34082f, -0.374023f,
-0.303711f, -0.398926f, 0.321777f, -0.42334f, 0.330566f, -0.453613f, 0.339355f, -0.483887f,
-0.339355f, -0.52002f, 0.339355f, -0.583496f, 0.312012f, -0.617188f, 0.291504f, -0.643066f,
-0.255371f, -0.643066f, 0.222656f, -0.643066f, 0.199707f, -0.619385f, 0.176758f, -0.595703f,
-0.176758f, -0.560547f, 0.176758f, -0.524902f, 0.202393f, -0.486572f, 0.228027f, -0.448242f,
-0.303711f, -0.398926f, 0.206055f, -0.295898f, 0.190918f, -0.282227f, 0.18457f, -0.270996f,
-0.174805f, -0.253906f, 0.166992f, -0.221191f, 0.15918f, -0.188477f, 0.15918f, -0.152832f,
-0.15918f, -0.106934f, 0.170898f, -0.0759277f, 0.182617f, -0.0449219f, 0.204346f,
--0.03125f, 0.226074f, -0.0175781f, 0.249023f, -0.0175781f, 0.284668f, -0.0175781f,
-0.309082f, -0.0437012f, 0.333496f, -0.0698242f, 0.333496f, -0.115234f, 0.333496f,
--0.209961f, 0.206055f, -0.295898f, 0.0307617f, 0.0136719f, 0.0307617f, 0, 0.111816f,
--0.0185547f, 0.168213f, -0.0546875f, 0.224609f, -0.0908203f, 0.257568f, -0.144043f,
-0.290527f, -0.197266f, 0.303711f, -0.266602f, 0.273438f, -0.250977f, 0.252197f, -0.244873f,
-0.230957f, -0.23877f, 0.20752f, -0.23877f, 0.132324f, -0.23877f, 0.0822754f, -0.292969f,
-0.0322266f, -0.347168f, 0.0322266f, -0.441406f, 0.0322266f, -0.506836f, 0.0593262f,
--0.561279f, 0.0864258f, -0.615723f, 0.136719f, -0.645752f, 0.187012f, -0.675781f,
-0.241211f, -0.675781f, 0.299316f, -0.675781f, 0.351074f, -0.642578f, 0.402832f, -0.609375f,
-0.433594f, -0.546387f, 0.464355f, -0.483398f, 0.464355f, -0.402832f, 0.464355f, -0.29834f,
-0.414307f, -0.202637f, 0.364258f, -0.106934f, 0.265137f, -0.0490723f, 0.166016f,
-0.00878906f, 0.0307617f, 0.0136719f, 0.311035f, -0.307617f, 0.315918f, -0.362305f,
-0.315918f, -0.403809f, 0.315918f, -0.492676f, 0.29541f, -0.569336f, 0.283691f, -0.611816f,
-0.260742f, -0.631836f, 0.248535f, -0.642578f, 0.229004f, -0.642578f, 0.20459f, -0.642578f,
-0.190918f, -0.621582f, 0.171875f, -0.592773f, 0.171875f, -0.511719f, 0.171875f, -0.376465f,
-0.204102f, -0.325195f, 0.225098f, -0.291992f, 0.260742f, -0.291992f, 0.279785f, -0.291992f,
-0.311035f, -0.307617f, 0.166992f, -0.469727f, 0.200684f, -0.469727f, 0.224365f, -0.446045f,
-0.248047f, -0.422363f, 0.248047f, -0.388672f, 0.248047f, -0.35498f, 0.224365f, -0.331299f,
-0.200684f, -0.307617f, 0.166992f, -0.307617f, 0.133301f, -0.307617f, 0.109619f, -0.331299f,
-0.0859375f, -0.35498f, 0.0859375f, -0.388672f, 0.0859375f, -0.422363f, 0.109619f,
--0.446045f, 0.133301f, -0.469727f, 0.166992f, -0.469727f, 0.166504f, -0.150391f,
-0.200684f, -0.150391f, 0.224365f, -0.126465f, 0.248047f, -0.102539f, 0.248047f, -0.0688477f,
-0.248047f, -0.0351562f, 0.224121f, -0.0114746f, 0.200195f, 0.012207f, 0.166504f,
-0.012207f, 0.132812f, 0.012207f, 0.109131f, -0.0114746f, 0.0854492f, -0.0351562f,
-0.0854492f, -0.0688477f, 0.0854492f, -0.102539f, 0.109131f, -0.126465f, 0.132812f,
--0.150391f, 0.166504f, -0.150391f, 0.166504f, -0.469727f, 0.200195f, -0.469727f,
-0.223633f, -0.446289f, 0.24707f, -0.422852f, 0.24707f, -0.38916f, 0.24707f, -0.355469f,
-0.223389f, -0.331787f, 0.199707f, -0.308105f, 0.166504f, -0.308105f, 0.132812f, -0.308105f,
-0.109131f, -0.331787f, 0.0854492f, -0.355469f, 0.0854492f, -0.38916f, 0.0854492f,
--0.422852f, 0.108887f, -0.446289f, 0.132324f, -0.469727f, 0.166504f, -0.469727f,
-0.0917969f, 0.175293f, 0.0917969f, 0.153809f, 0.148438f, 0.129395f, 0.174072f, 0.0905762f,
-0.199707f, 0.0517578f, 0.199707f, 0.0112305f, 0.199707f, 0.00292969f, 0.196289f,
--0.00146484f, 0.192871f, -0.00537109f, 0.189453f, -0.00537109f, 0.186523f, -0.00537109f,
-0.180664f, -0.00195312f, 0.166504f, 0.00634766f, 0.145508f, 0.00634766f, 0.116699f,
-0.00634766f, 0.095459f, -0.0161133f, 0.0742188f, -0.0385742f, 0.0742188f, -0.0688477f,
-0.0742188f, -0.101074f, 0.0986328f, -0.125488f, 0.123047f, -0.149902f, 0.157715f,
--0.149902f, 0.199707f, -0.149902f, 0.229492f, -0.117432f, 0.259277f, -0.0849609f,
-0.259277f, -0.0283203f, 0.259277f, 0.0415039f, 0.217041f, 0.0957031f, 0.174805f,
-0.149902f, 0.0917969f, 0.175293f, 0.553223f, -0.090332f, 0.0200195f, -0.308105f,
-0.0200195f, -0.347656f, 0.553223f, -0.567871f, 0.553223f, -0.500488f, 0.140625f,
--0.328125f, 0.553223f, -0.158691f, 0.0195312f, -0.441406f, 0.553711f, -0.441406f,
-0.553711f, -0.37793f, 0.0195312f, -0.37793f, 0.0195312f, -0.281738f, 0.553711f, -0.281738f,
-0.553711f, -0.218262f, 0.0195312f, -0.218262f, 0.0200195f, -0.567871f, 0.553223f,
--0.350586f, 0.553223f, -0.310547f, 0.0200195f, -0.090332f, 0.0200195f, -0.158203f,
-0.432617f, -0.330078f, 0.0200195f, -0.499512f, 0.237305f, -0.21582f, 0.217285f, -0.21582f,
-0.216309f, -0.27002f, 0.222412f, -0.296875f, 0.228516f, -0.32373f, 0.25415f, -0.37085f,
-0.279785f, -0.417969f, 0.287842f, -0.446533f, 0.295898f, -0.475098f, 0.295898f, -0.51709f,
-0.295898f, -0.582031f, 0.270508f, -0.612793f, 0.245117f, -0.643555f, 0.210449f, -0.643555f,
-0.184082f, -0.643555f, 0.166016f, -0.629395f, 0.152344f, -0.618652f, 0.152344f, -0.606934f,
-0.152344f, -0.599121f, 0.161621f, -0.58252f, 0.182617f, -0.544922f, 0.182617f, -0.518555f,
-0.182617f, -0.494629f, 0.16626f, -0.478516f, 0.149902f, -0.462402f, 0.125488f, -0.462402f,
-0.0981445f, -0.462402f, 0.0795898f, -0.481689f, 0.0610352f, -0.500977f, 0.0610352f,
--0.532715f, 0.0610352f, -0.590332f, 0.11084f, -0.633789f, 0.160645f, -0.677246f,
-0.25f, -0.677246f, 0.344727f, -0.677246f, 0.394287f, -0.63208f, 0.443848f, -0.586914f,
-0.443848f, -0.522949f, 0.443848f, -0.476562f, 0.418457f, -0.437256f, 0.393066f, -0.397949f,
-0.320312f, -0.350098f, 0.271484f, -0.317871f, 0.256104f, -0.292725f, 0.240723f, -0.267578f,
-0.237305f, -0.21582f, 0.231934f, -0.144531f, 0.264648f, -0.144531f, 0.287598f, -0.121582f,
-0.310547f, -0.0986328f, 0.310547f, -0.065918f, 0.310547f, -0.0332031f, 0.287598f,
--0.0100098f, 0.264648f, 0.0131836f, 0.231934f, 0.0131836f, 0.199219f, 0.0131836f,
-0.17627f, -0.0100098f, 0.15332f, -0.0332031f, 0.15332f, -0.065918f, 0.15332f, -0.0986328f,
-0.17627f, -0.121582f, 0.199219f, -0.144531f, 0.231934f, -0.144531f, 0.575684f, -0.45166f,
-0.694824f, -0.456543f, 0.605469f, -0.149902f, 0.590332f, -0.0991211f, 0.590332f,
--0.0737305f, 0.590332f, -0.0581055f, 0.601807f, -0.0466309f, 0.613281f, -0.0351562f,
-0.629883f, -0.0351562f, 0.663574f, -0.0351562f, 0.717041f, -0.0739746f, 0.770508f,
--0.112793f, 0.80542f, -0.184814f, 0.840332f, -0.256836f, 0.840332f, -0.338379f, 0.840332f,
--0.473145f, 0.753662f, -0.559814f, 0.666992f, -0.646484f, 0.527832f, -0.646484f,
-0.407715f, -0.646484f, 0.30957f, -0.590088f, 0.211426f, -0.533691f, 0.153809f, -0.42627f,
-0.0961914f, -0.318848f, 0.0961914f, -0.195801f, 0.0961914f, -0.0268555f, 0.203857f,
-0.0808105f, 0.311523f, 0.188477f, 0.478027f, 0.188477f, 0.615234f, 0.188477f, 0.724121f,
-0.114746f, 0.833008f, 0.0410156f, 0.878418f, -0.0805664f, 0.908203f, -0.0805664f,
-0.849609f, 0.0629883f, 0.737549f, 0.139404f, 0.625488f, 0.21582f, 0.477051f, 0.21582f,
-0.289062f, 0.21582f, 0.166992f, 0.0944824f, 0.0449219f, -0.0268555f, 0.0449219f,
--0.212891f, 0.0449219f, -0.34082f, 0.105469f, -0.449951f, 0.166016f, -0.559082f,
-0.275391f, -0.618164f, 0.384766f, -0.677246f, 0.517578f, -0.677246f, 0.625488f, -0.677246f,
-0.706299f, -0.634033f, 0.787109f, -0.59082f, 0.827637f, -0.512695f, 0.868164f, -0.43457f,
-0.868164f, -0.347656f, 0.868164f, -0.246582f, 0.824463f, -0.163086f, 0.780762f, -0.0795898f,
-0.715576f, -0.0397949f, 0.650391f, 0, 0.575195f, 0, 0.526855f, 0, 0.501465f, -0.0239258f,
-0.476074f, -0.0478516f, 0.476074f, -0.0854492f, 0.476074f, -0.111816f, 0.487793f,
--0.154297f, 0.447266f, -0.0869141f, 0.424805f, -0.0610352f, 0.394043f, -0.0263672f,
-0.36377f, -0.0102539f, 0.344238f, 0, 0.319336f, 0, 0.284668f, 0, 0.260986f, -0.0275879f,
-0.237305f, -0.0551758f, 0.237305f, -0.108398f, 0.237305f, -0.163086f, 0.253174f,
--0.215576f, 0.269043f, -0.268066f, 0.296387f, -0.314209f, 0.32373f, -0.360352f, 0.359619f,
--0.396973f, 0.395508f, -0.433594f, 0.44043f, -0.45752f, 0.463379f, -0.470215f, 0.489746f,
--0.470215f, 0.51709f, -0.470215f, 0.534912f, -0.453125f, 0.552734f, -0.436035f, 0.559082f,
--0.393555f, 0.501953f, -0.435059f, 0.483398f, -0.435059f, 0.465332f, -0.414551f,
-0.440918f, -0.386719f, 0.413086f, -0.321777f, 0.363281f, -0.205078f, 0.363281f, -0.134277f,
-0.363281f, -0.112793f, 0.372314f, -0.101074f, 0.381348f, -0.0893555f, 0.39209f, -0.0893555f,
-0.401367f, -0.0893555f, 0.418945f, -0.103027f, 0.443848f, -0.12207f, 0.472168f, -0.16748f,
-0.500488f, -0.212891f, 0.518555f, -0.268311f, 0.536621f, -0.32373f, 0.536621f, -0.370605f,
-0.536621f, -0.404297f, 0.523926f, -0.421875f, 0.514648f, -0.435059f, 0.501953f, -0.435059f,
-0.416016f, -0.188477f, 0.182129f, -0.188477f, 0.154297f, -0.124023f, 0.140625f, -0.0917969f,
-0.140625f, -0.0708008f, 0.140625f, -0.0429688f, 0.163086f, -0.0297852f, 0.17627f,
--0.0219727f, 0.228027f, -0.0180664f, 0.228027f, 0, 0.0078125f, 0, 0.0078125f, -0.0180664f,
-0.043457f, -0.0234375f, 0.0664062f, -0.0476074f, 0.0893555f, -0.0717773f, 0.123047f,
--0.147461f, 0.359863f, -0.675781f, 0.369141f, -0.675781f, 0.60791f, -0.132812f, 0.64209f,
--0.0556641f, 0.664062f, -0.0356445f, 0.680664f, -0.0205078f, 0.710938f, -0.0180664f,
-0.710938f, 0, 0.390625f, 0, 0.390625f, -0.0180664f, 0.403809f, -0.0180664f, 0.442383f,
--0.0180664f, 0.458008f, -0.0288086f, 0.46875f, -0.0366211f, 0.46875f, -0.0512695f,
-0.46875f, -0.0600586f, 0.46582f, -0.0693359f, 0.464844f, -0.0737305f, 0.451172f,
--0.105957f, 0.399414f, -0.224609f, 0.300781f, -0.452637f, 0.199219f, -0.224609f,
-0.444824f, -0.351074f, 0.539062f, -0.329102f, 0.577148f, -0.297852f, 0.631836f, -0.253418f,
-0.631836f, -0.182617f, 0.631836f, -0.10791f, 0.571777f, -0.059082f, 0.498047f, 0,
-0.357422f, 0, 0.0209961f, 0, 0.0209961f, -0.0180664f, 0.0668945f, -0.0180664f, 0.083252f,
--0.0266113f, 0.0996094f, -0.0351562f, 0.106201f, -0.0488281f, 0.112793f, -0.0625f,
-0.112793f, -0.116211f, 0.112793f, -0.545898f, 0.112793f, -0.599609f, 0.106201f, -0.613525f,
-0.0996094f, -0.627441f, 0.0830078f, -0.635742f, 0.0664062f, -0.644043f, 0.0209961f,
--0.644043f, 0.0209961f, -0.662109f, 0.338379f, -0.662109f, 0.452148f, -0.662109f,
-0.499512f, -0.641846f, 0.546875f, -0.621582f, 0.574219f, -0.581299f, 0.601562f, -0.541016f,
-0.601562f, -0.495605f, 0.601562f, -0.447754f, 0.566895f, -0.4104f, 0.532227f, -0.373047f,
-0.444824f, -0.351074f, 0.26709f, -0.364258f, 0.336426f, -0.364258f, 0.369385f, -0.379883f,
-0.402344f, -0.395508f, 0.419922f, -0.423828f, 0.4375f, -0.452148f, 0.4375f, -0.496094f,
-0.4375f, -0.540039f, 0.420166f, -0.568115f, 0.402832f, -0.596191f, 0.370605f, -0.61084f,
-0.338379f, -0.625488f, 0.26709f, -0.625f, 0.26709f, -0.326172f, 0.26709f, -0.11377f,
-0.266602f, -0.0893555f, 0.266602f, -0.0629883f, 0.280029f, -0.0495605f, 0.293457f,
--0.0361328f, 0.319824f, -0.0361328f, 0.358887f, -0.0361328f, 0.391846f, -0.0534668f,
-0.424805f, -0.0708008f, 0.442383f, -0.10376f, 0.459961f, -0.136719f, 0.459961f, -0.177246f,
-0.459961f, -0.223633f, 0.438477f, -0.260498f, 0.416992f, -0.297363f, 0.379395f, -0.312012f,
-0.341797f, -0.32666f, 0.26709f, -0.326172f, 0.66748f, -0.677246f, 0.66748f, -0.447754f,
-0.648438f, -0.447754f, 0.626953f, -0.537598f, 0.568359f, -0.585449f, 0.509766f, -0.633301f,
-0.435547f, -0.633301f, 0.373535f, -0.633301f, 0.321777f, -0.597656f, 0.27002f, -0.562012f,
-0.246094f, -0.504395f, 0.215332f, -0.430664f, 0.215332f, -0.340332f, 0.215332f, -0.251465f,
-0.237793f, -0.178467f, 0.260254f, -0.105469f, 0.308105f, -0.0681152f, 0.355957f,
--0.0307617f, 0.432129f, -0.0307617f, 0.494629f, -0.0307617f, 0.546631f, -0.0581055f,
-0.598633f, -0.0854492f, 0.65625f, -0.152344f, 0.65625f, -0.0952148f, 0.600586f, -0.0371094f,
-0.540283f, -0.0109863f, 0.47998f, 0.0151367f, 0.399414f, 0.0151367f, 0.293457f, 0.0151367f,
-0.211182f, -0.0273438f, 0.128906f, -0.0698242f, 0.0842285f, -0.149414f, 0.0395508f,
--0.229004f, 0.0395508f, -0.318848f, 0.0395508f, -0.413574f, 0.0891113f, -0.498535f,
-0.138672f, -0.583496f, 0.2229f, -0.630371f, 0.307129f, -0.677246f, 0.401855f, -0.677246f,
-0.47168f, -0.677246f, 0.549316f, -0.646973f, 0.594238f, -0.629395f, 0.606445f, -0.629395f,
-0.62207f, -0.629395f, 0.633545f, -0.640869f, 0.64502f, -0.652344f, 0.648438f, -0.677246f,
-0.0131836f, 0, 0.0131836f, -0.0180664f, 0.0351562f, -0.0180664f, 0.0639648f, -0.0180664f,
-0.0793457f, -0.0270996f, 0.0947266f, -0.0361328f, 0.102051f, -0.0517578f, 0.106445f,
--0.0620117f, 0.106445f, -0.113281f, 0.106445f, -0.548828f, 0.106445f, -0.599609f,
-0.101074f, -0.612305f, 0.0957031f, -0.625f, 0.0793457f, -0.634521f, 0.0629883f, -0.644043f,
-0.0351562f, -0.644043f, 0.0131836f, -0.644043f, 0.0131836f, -0.662109f, 0.30957f,
--0.662109f, 0.428223f, -0.662109f, 0.500488f, -0.629883f, 0.588867f, -0.590332f,
-0.634521f, -0.510254f, 0.680176f, -0.430176f, 0.680176f, -0.329102f, 0.680176f, -0.259277f,
-0.657715f, -0.200439f, 0.635254f, -0.141602f, 0.599609f, -0.103271f, 0.563965f, -0.0649414f,
-0.517334f, -0.041748f, 0.470703f, -0.0185547f, 0.40332f, -0.00585938f, 0.373535f,
-0, 0.30957f, 0, 0.265625f, -0.624512f, 0.265625f, -0.10791f, 0.265625f, -0.0668945f,
-0.269531f, -0.0576172f, 0.273438f, -0.0483398f, 0.282715f, -0.043457f, 0.295898f,
--0.0361328f, 0.320801f, -0.0361328f, 0.402344f, -0.0361328f, 0.445312f, -0.0917969f,
-0.503906f, -0.166992f, 0.503906f, -0.325195f, 0.503906f, -0.452637f, 0.463867f, -0.528809f,
-0.432129f, -0.588379f, 0.382324f, -0.609863f, 0.347168f, -0.625f, 0.265625f, -0.624512f,
-0.272461f, -0.624023f, 0.272461f, -0.354492f, 0.285645f, -0.354492f, 0.348633f, -0.354492f,
-0.376953f, -0.394043f, 0.405273f, -0.433594f, 0.413086f, -0.510742f, 0.431641f, -0.510742f,
-0.431641f, -0.164062f, 0.413086f, -0.164062f, 0.407227f, -0.220703f, 0.388428f, -0.256836f,
-0.369629f, -0.292969f, 0.344727f, -0.30542f, 0.319824f, -0.317871f, 0.272461f, -0.317871f,
-0.272461f, -0.131348f, 0.272461f, -0.0766602f, 0.2771f, -0.0644531f, 0.281738f, -0.0522461f,
-0.294434f, -0.0444336f, 0.307129f, -0.0366211f, 0.335449f, -0.0366211f, 0.375f, -0.0366211f,
-0.467773f, -0.0366211f, 0.523682f, -0.0795898f, 0.57959f, -0.122559f, 0.604004f,
--0.210449f, 0.62207f, -0.210449f, 0.592285f, 0, 0.0200195f, 0, 0.0200195f, -0.0180664f,
-0.0419922f, -0.0180664f, 0.0708008f, -0.0180664f, 0.0883789f, -0.0283203f, 0.101074f,
--0.0351562f, 0.10791f, -0.0517578f, 0.113281f, -0.0634766f, 0.113281f, -0.113281f,
-0.113281f, -0.548828f, 0.113281f, -0.59375f, 0.11084f, -0.604004f, 0.105957f, -0.621094f,
-0.0927734f, -0.630371f, 0.0742188f, -0.644043f, 0.0419922f, -0.644043f, 0.0200195f,
--0.644043f, 0.0200195f, -0.662109f, 0.574219f, -0.662109f, 0.574219f, -0.466309f,
-0.555664f, -0.466309f, 0.541504f, -0.538086f, 0.515869f, -0.569336f, 0.490234f, -0.600586f,
-0.443359f, -0.615234f, 0.416016f, -0.624023f, 0.34082f, -0.624023f, 0.274902f, -0.624023f,
-0.274902f, -0.352051f, 0.293945f, -0.352051f, 0.337891f, -0.352051f, 0.365723f, -0.365234f,
-0.393555f, -0.378418f, 0.412842f, -0.409668f, 0.432129f, -0.440918f, 0.437988f, -0.494141f,
-0.455078f, -0.494141f, 0.455078f, -0.161621f, 0.437988f, -0.161621f, 0.428711f, -0.255859f,
-0.387451f, -0.285889f, 0.346191f, -0.315918f, 0.293945f, -0.315918f, 0.274902f, -0.315918f,
-0.274902f, -0.113281f, 0.274902f, -0.0625f, 0.280518f, -0.0498047f, 0.286133f, -0.0371094f,
-0.30249f, -0.0275879f, 0.318848f, -0.0180664f, 0.34668f, -0.0180664f, 0.368652f,
--0.0180664f, 0.368652f, 0, 0.0224609f, 0, 0.0224609f, -0.0180664f, 0.0444336f, -0.0180664f,
-0.0732422f, -0.0180664f, 0.0908203f, -0.0283203f, 0.103516f, -0.0351562f, 0.110352f,
--0.0517578f, 0.115723f, -0.0634766f, 0.115723f, -0.113281f, 0.115723f, -0.548828f,
-0.115723f, -0.599609f, 0.110352f, -0.612305f, 0.10498f, -0.625f, 0.088623f, -0.634521f,
-0.0722656f, -0.644043f, 0.0444336f, -0.644043f, 0.0224609f, -0.644043f, 0.0224609f,
--0.662109f, 0.581055f, -0.662109f, 0.581055f, -0.472168f, 0.561035f, -0.472168f,
-0.554199f, -0.539062f, 0.526123f, -0.571289f, 0.498047f, -0.603516f, 0.444824f, -0.616699f,
-0.415527f, -0.624023f, 0.336426f, -0.624023f, 0.689941f, -0.677246f, 0.689941f, -0.443848f,
-0.671875f, -0.443848f, 0.63916f, -0.539551f, 0.57373f, -0.589355f, 0.508301f, -0.63916f,
-0.430664f, -0.63916f, 0.356445f, -0.63916f, 0.307129f, -0.597412f, 0.257812f, -0.555664f,
-0.237305f, -0.480957f, 0.216797f, -0.40625f, 0.216797f, -0.327637f, 0.216797f, -0.232422f,
-0.239258f, -0.160645f, 0.261719f, -0.0888672f, 0.311768f, -0.0551758f, 0.361816f,
--0.0214844f, 0.430664f, -0.0214844f, 0.45459f, -0.0214844f, 0.479736f, -0.0266113f,
-0.504883f, -0.0317383f, 0.53125f, -0.0415039f, 0.53125f, -0.179199f, 0.53125f, -0.218262f,
-0.525879f, -0.229736f, 0.520508f, -0.241211f, 0.503662f, -0.250488f, 0.486816f, -0.259766f,
-0.462891f, -0.259766f, 0.445801f, -0.259766f, 0.445801f, -0.277832f, 0.767578f, -0.277832f,
-0.767578f, -0.259766f, 0.730957f, -0.257324f, 0.716553f, -0.249756f, 0.702148f, -0.242188f,
-0.694336f, -0.224609f, 0.689941f, -0.215332f, 0.689941f, -0.179199f, 0.689941f, -0.0415039f,
-0.626465f, -0.0131836f, 0.557861f, 0.0012207f, 0.489258f, 0.015625f, 0.415527f, 0.015625f,
-0.321289f, 0.015625f, 0.259033f, -0.0100098f, 0.196777f, -0.0356445f, 0.14917f, -0.0773926f,
-0.101562f, -0.119141f, 0.074707f, -0.171387f, 0.0405273f, -0.23877f, 0.0405273f,
--0.322266f, 0.0405273f, -0.47168f, 0.145508f, -0.574707f, 0.250488f, -0.677734f,
-0.409668f, -0.677734f, 0.458984f, -0.677734f, 0.498535f, -0.669922f, 0.52002f, -0.666016f,
-0.568115f, -0.647705f, 0.616211f, -0.629395f, 0.625f, -0.629395f, 0.638672f, -0.629395f,
-0.650391f, -0.639404f, 0.662109f, -0.649414f, 0.671875f, -0.677246f, 0.273438f, -0.318359f,
-0.273438f, -0.113281f, 0.273438f, -0.0625f, 0.279053f, -0.0498047f, 0.284668f, -0.0371094f,
-0.301025f, -0.0275879f, 0.317383f, -0.0180664f, 0.345215f, -0.0180664f, 0.367188f,
--0.0180664f, 0.367188f, 0, 0.0209961f, 0, 0.0209961f, -0.0180664f, 0.0429688f, -0.0180664f,
-0.0717773f, -0.0180664f, 0.0893555f, -0.0283203f, 0.102051f, -0.0351562f, 0.108887f,
--0.0517578f, 0.114258f, -0.0634766f, 0.114258f, -0.113281f, 0.114258f, -0.548828f,
-0.114258f, -0.599609f, 0.108887f, -0.612305f, 0.103516f, -0.625f, 0.0871582f, -0.634521f,
-0.0708008f, -0.644043f, 0.0429688f, -0.644043f, 0.0209961f, -0.644043f, 0.0209961f,
--0.662109f, 0.367188f, -0.662109f, 0.367188f, -0.644043f, 0.345215f, -0.644043f,
-0.316406f, -0.644043f, 0.298828f, -0.633789f, 0.286133f, -0.626953f, 0.278809f, -0.610352f,
-0.273438f, -0.598633f, 0.273438f, -0.548828f, 0.273438f, -0.361328f, 0.507324f, -0.361328f,
-0.507324f, -0.548828f, 0.507324f, -0.599609f, 0.501953f, -0.612305f, 0.496582f, -0.625f,
-0.47998f, -0.634521f, 0.463379f, -0.644043f, 0.435547f, -0.644043f, 0.414062f, -0.644043f,
-0.414062f, -0.662109f, 0.759766f, -0.662109f, 0.759766f, -0.644043f, 0.738281f, -0.644043f,
-0.708984f, -0.644043f, 0.691895f, -0.633789f, 0.679199f, -0.626953f, 0.671875f, -0.610352f,
-0.666504f, -0.598633f, 0.666504f, -0.548828f, 0.666504f, -0.113281f, 0.666504f, -0.0625f,
-0.671875f, -0.0498047f, 0.677246f, -0.0371094f, 0.693848f, -0.0275879f, 0.710449f,
--0.0180664f, 0.738281f, -0.0180664f, 0.759766f, -0.0180664f, 0.759766f, 0, 0.414062f,
-0, 0.414062f, -0.0180664f, 0.435547f, -0.0180664f, 0.464844f, -0.0180664f, 0.481934f,
--0.0283203f, 0.494629f, -0.0351562f, 0.501953f, -0.0517578f, 0.507324f, -0.0634766f,
-0.507324f, -0.113281f, 0.507324f, -0.318359f, 0.366211f, -0.0180664f, 0.366211f,
-0, 0.0200195f, 0, 0.0200195f, -0.0180664f, 0.0419922f, -0.0180664f, 0.0708008f, -0.0180664f,
-0.0883789f, -0.0283203f, 0.101074f, -0.0351562f, 0.10791f, -0.0517578f, 0.113281f,
--0.0634766f, 0.113281f, -0.113281f, 0.113281f, -0.548828f, 0.113281f, -0.599609f,
-0.10791f, -0.612305f, 0.102539f, -0.625f, 0.0861816f, -0.634521f, 0.0698242f, -0.644043f,
-0.0419922f, -0.644043f, 0.0200195f, -0.644043f, 0.0200195f, -0.662109f, 0.366211f,
--0.662109f, 0.366211f, -0.644043f, 0.344238f, -0.644043f, 0.31543f, -0.644043f, 0.297852f,
--0.633789f, 0.285156f, -0.626953f, 0.277832f, -0.610352f, 0.272461f, -0.598633f,
-0.272461f, -0.548828f, 0.272461f, -0.113281f, 0.272461f, -0.0625f, 0.278076f, -0.0498047f,
-0.283691f, -0.0371094f, 0.300049f, -0.0275879f, 0.316406f, -0.0180664f, 0.344238f,
--0.0180664f, 0.14209f, -0.644043f, 0.14209f, -0.662109f, 0.494141f, -0.662109f, 0.494141f,
--0.644043f, 0.472656f, -0.644043f, 0.443359f, -0.644043f, 0.425781f, -0.633789f,
-0.413574f, -0.626953f, 0.40625f, -0.610352f, 0.400879f, -0.598633f, 0.400879f, -0.548828f,
-0.400879f, -0.224609f, 0.400879f, -0.129395f, 0.381836f, -0.0861816f, 0.362793f,
--0.0429688f, 0.314209f, -0.013916f, 0.265625f, 0.0151367f, 0.197266f, 0.0151367f,
-0.11377f, 0.0151367f, 0.0622559f, -0.0288086f, 0.0107422f, -0.0727539f, 0.0107422f,
--0.125977f, 0.0107422f, -0.160156f, 0.0317383f, -0.181396f, 0.0527344f, -0.202637f,
-0.0830078f, -0.202637f, 0.112793f, -0.202637f, 0.133057f, -0.183594f, 0.15332f, -0.164551f,
-0.15332f, -0.136719f, 0.15332f, -0.123047f, 0.149902f, -0.112793f, 0.147949f, -0.10791f,
-0.134521f, -0.0881348f, 0.121094f, -0.0683594f, 0.121094f, -0.0600586f, 0.121094f,
--0.0473633f, 0.133789f, -0.0380859f, 0.152344f, -0.0244141f, 0.182129f, -0.0244141f,
-0.203125f, -0.0244141f, 0.216797f, -0.0351562f, 0.230469f, -0.0458984f, 0.236084f,
--0.0686035f, 0.241699f, -0.0913086f, 0.241699f, -0.194824f, 0.241699f, -0.548828f,
-0.241699f, -0.599609f, 0.236084f, -0.612305f, 0.230469f, -0.625f, 0.214111f, -0.634521f,
-0.197754f, -0.644043f, 0.169922f, -0.644043f, 0.416504f, -0.408691f, 0.649414f, -0.117188f,
-0.69873f, -0.0556641f, 0.734375f, -0.0336914f, 0.760254f, -0.0180664f, 0.789062f,
--0.0180664f, 0.789062f, 0, 0.444336f, 0, 0.444336f, -0.0180664f, 0.477051f, -0.0209961f,
-0.486572f, -0.0283203f, 0.496094f, -0.0356445f, 0.496094f, -0.0463867f, 0.496094f,
--0.0668945f, 0.451172f, -0.123535f, 0.299316f, -0.314453f, 0.274902f, -0.293945f,
-0.274902f, -0.113281f, 0.274902f, -0.0615234f, 0.280762f, -0.0488281f, 0.286621f,
--0.0361328f, 0.303223f, -0.0270996f, 0.319824f, -0.0180664f, 0.356445f, -0.0180664f,
-0.356445f, 0, 0.0224609f, 0, 0.0224609f, -0.0180664f, 0.0444336f, -0.0180664f, 0.0732422f,
--0.0180664f, 0.0908203f, -0.0283203f, 0.103516f, -0.0351562f, 0.110352f, -0.0517578f,
-0.115723f, -0.0634766f, 0.115723f, -0.113281f, 0.115723f, -0.548828f, 0.115723f,
--0.599609f, 0.110352f, -0.612305f, 0.10498f, -0.625f, 0.088623f, -0.634521f, 0.0722656f,
--0.644043f, 0.0444336f, -0.644043f, 0.0224609f, -0.644043f, 0.0224609f, -0.662109f,
-0.352051f, -0.662109f, 0.352051f, -0.644043f, 0.318359f, -0.644043f, 0.300781f, -0.634277f,
-0.288086f, -0.627441f, 0.280762f, -0.611328f, 0.274902f, -0.599121f, 0.274902f, -0.548828f,
-0.274902f, -0.342773f, 0.520508f, -0.541504f, 0.571777f, -0.583008f, 0.571777f, -0.60791f,
-0.571777f, -0.626465f, 0.550781f, -0.637207f, 0.540039f, -0.642578f, 0.497559f, -0.644043f,
-0.497559f, -0.662109f, 0.755859f, -0.662109f, 0.755859f, -0.644043f, 0.721191f, -0.641602f,
-0.701416f, -0.631592f, 0.681641f, -0.621582f, 0.610352f, -0.563965f, 0.631348f, -0.232422f,
-0.606445f, 0, 0.0185547f, 0, 0.0185547f, -0.0180664f, 0.0405273f, -0.0180664f, 0.0693359f,
--0.0180664f, 0.0869141f, -0.0283203f, 0.0996094f, -0.0351562f, 0.106445f, -0.0517578f,
-0.111816f, -0.0634766f, 0.111816f, -0.113281f, 0.111816f, -0.548828f, 0.111816f,
--0.599609f, 0.106445f, -0.612305f, 0.101074f, -0.625f, 0.0847168f, -0.634521f, 0.0683594f,
--0.644043f, 0.0405273f, -0.644043f, 0.0185547f, -0.644043f, 0.0185547f, -0.662109f,
-0.371582f, -0.662109f, 0.371582f, -0.644043f, 0.342773f, -0.644043f, 0.313965f, -0.644043f,
-0.296387f, -0.633789f, 0.283691f, -0.626953f, 0.276367f, -0.610352f, 0.270996f, -0.598633f,
-0.270996f, -0.548828f, 0.270996f, -0.126953f, 0.270996f, -0.0761719f, 0.276855f,
--0.0622559f, 0.282715f, -0.0483398f, 0.299805f, -0.0415039f, 0.312012f, -0.0371094f,
-0.358887f, -0.0371094f, 0.414062f, -0.0371094f, 0.466797f, -0.0371094f, 0.501953f,
--0.0556641f, 0.537109f, -0.0742188f, 0.562744f, -0.114258f, 0.588379f, -0.154297f,
-0.611328f, -0.232422f, 0.476562f, -0.225586f, 0.65625f, -0.662109f, 0.925781f, -0.662109f,
-0.925781f, -0.644043f, 0.904297f, -0.644043f, 0.875f, -0.644043f, 0.857422f, -0.633789f,
-0.845215f, -0.626953f, 0.837891f, -0.61084f, 0.83252f, -0.599121f, 0.83252f, -0.549805f,
-0.83252f, -0.113281f, 0.83252f, -0.0625f, 0.837891f, -0.0498047f, 0.843262f, -0.0371094f,
-0.859863f, -0.0275879f, 0.876465f, -0.0180664f, 0.904297f, -0.0180664f, 0.925781f,
--0.0180664f, 0.925781f, 0, 0.580078f, 0, 0.580078f, -0.0180664f, 0.601562f, -0.0180664f,
-0.630859f, -0.0180664f, 0.648438f, -0.0283203f, 0.660645f, -0.0351562f, 0.667969f,
--0.0517578f, 0.67334f, -0.0634766f, 0.67334f, -0.113281f, 0.67334f, -0.604004f, 0.419434f,
-0, 0.407715f, 0, 0.149902f, -0.599609f, 0.149902f, -0.133301f, 0.149902f, -0.0844727f,
-0.152344f, -0.0732422f, 0.158691f, -0.0488281f, 0.179932f, -0.0334473f, 0.201172f,
--0.0180664f, 0.246582f, -0.0180664f, 0.246582f, 0, 0.0200195f, 0, 0.0200195f, -0.0180664f,
-0.0268555f, -0.0180664f, 0.0488281f, -0.0175781f, 0.0678711f, -0.0251465f, 0.0869141f,
--0.0327148f, 0.0966797f, -0.0454102f, 0.106445f, -0.0581055f, 0.111816f, -0.0810547f,
-0.112793f, -0.0864258f, 0.112793f, -0.130859f, 0.112793f, -0.549805f, 0.112793f,
--0.600098f, 0.107422f, -0.612549f, 0.102051f, -0.625f, 0.0854492f, -0.634521f, 0.0688477f,
--0.644043f, 0.0410156f, -0.644043f, 0.0200195f, -0.644043f, 0.0200195f, -0.662109f,
-0.290527f, -0.662109f, 0.249023f, -0.662109f, 0.575684f, -0.251465f, 0.575684f, -0.536133f,
-0.575684f, -0.595703f, 0.558594f, -0.616699f, 0.535156f, -0.64502f, 0.47998f, -0.644043f,
-0.47998f, -0.662109f, 0.69873f, -0.662109f, 0.69873f, -0.644043f, 0.656738f, -0.638672f,
-0.642334f, -0.630127f, 0.62793f, -0.621582f, 0.619873f, -0.602295f, 0.611816f, -0.583008f,
-0.611816f, -0.536133f, 0.611816f, 0.0151367f, 0.595215f, 0.0151367f, 0.147461f, -0.536133f,
-0.147461f, -0.115234f, 0.147461f, -0.0581055f, 0.173584f, -0.0380859f, 0.199707f,
--0.0180664f, 0.233398f, -0.0180664f, 0.249023f, -0.0180664f, 0.249023f, 0, 0.0141602f,
-0, 0.0141602f, -0.0180664f, 0.0688477f, -0.0185547f, 0.090332f, -0.0405273f, 0.111816f,
--0.0625f, 0.111816f, -0.115234f, 0.111816f, -0.58252f, 0.0976562f, -0.600098f, 0.0766602f,
--0.626465f, 0.0605469f, -0.634766f, 0.0444336f, -0.643066f, 0.0141602f, -0.644043f,
-0.0141602f, -0.662109f, 0.38623f, -0.671387f, 0.544434f, -0.677246f, 0.643311f, -0.579102f,
-0.742188f, -0.480957f, 0.742188f, -0.333496f, 0.742188f, -0.20752f, 0.668457f, -0.111816f,
-0.570801f, 0.0151367f, 0.392578f, 0.0151367f, 0.213867f, 0.0151367f, 0.116211f, -0.105957f,
-0.0390625f, -0.20166f, 0.0390625f, -0.333008f, 0.0390625f, -0.480469f, 0.139404f,
--0.578857f, 0.239746f, -0.677246f, 0.38623f, -0.671387f, 0.39209f, -0.640137f, 0.30127f,
--0.640137f, 0.253906f, -0.547363f, 0.215332f, -0.471191f, 0.215332f, -0.328613f,
-0.215332f, -0.15918f, 0.274902f, -0.078125f, 0.316406f, -0.0214844f, 0.391113f, -0.0214844f,
-0.441406f, -0.0214844f, 0.475098f, -0.0458984f, 0.518066f, -0.0771484f, 0.541992f,
--0.145752f, 0.565918f, -0.214355f, 0.565918f, -0.324707f, 0.565918f, -0.456055f,
-0.541504f, -0.52124f, 0.51709f, -0.586426f, 0.479248f, -0.613281f, 0.441406f, -0.640137f,
-0.39209f, -0.640137f, 0.27002f, -0.299805f, 0.27002f, -0.116211f, 0.27002f, -0.0625f,
-0.276611f, -0.048584f, 0.283203f, -0.034668f, 0.300049f, -0.0263672f, 0.316895f,
--0.0180664f, 0.361816f, -0.0180664f, 0.361816f, 0, 0.0253906f, 0, 0.0253906f, -0.0180664f,
-0.0712891f, -0.0180664f, 0.0876465f, -0.0266113f, 0.104004f, -0.0351562f, 0.110596f,
--0.0488281f, 0.117188f, -0.0625f, 0.117188f, -0.116211f, 0.117188f, -0.545898f, 0.117188f,
--0.599609f, 0.110596f, -0.613525f, 0.104004f, -0.627441f, 0.0874023f, -0.635742f,
-0.0708008f, -0.644043f, 0.0253906f, -0.644043f, 0.0253906f, -0.662109f, 0.313965f,
--0.662109f, 0.456543f, -0.662109f, 0.518555f, -0.611328f, 0.580566f, -0.560547f,
-0.580566f, -0.484375f, 0.580566f, -0.419922f, 0.540527f, -0.374023f, 0.500488f, -0.328125f,
-0.430176f, -0.311523f, 0.382812f, -0.299805f, 0.27002f, -0.299805f, 0.27002f, -0.624023f,
-0.27002f, -0.337891f, 0.286133f, -0.336914f, 0.294434f, -0.336914f, 0.354004f, -0.336914f,
-0.38623f, -0.372314f, 0.418457f, -0.407715f, 0.418457f, -0.481934f, 0.418457f, -0.555664f,
-0.38623f, -0.589844f, 0.354004f, -0.624023f, 0.290039f, -0.624023f, 0.478027f, 0.00585938f,
-0.500488f, 0.0708008f, 0.547852f, 0.103516f, 0.595215f, 0.13623f, 0.666504f, 0.13623f,
-0.686035f, 0.13623f, 0.708008f, 0.132324f, 0.708008f, 0.162109f, 0.634277f, 0.180664f,
-0.576172f, 0.180664f, 0.485352f, 0.180664f, 0.413818f, 0.13623f, 0.342285f, 0.0917969f,
-0.306152f, 0.00585938f, 0.186035f, -0.0195312f, 0.112549f, -0.111816f, 0.0390625f,
--0.204102f, 0.0390625f, -0.332031f, 0.0390625f, -0.480469f, 0.138672f, -0.578857f,
-0.238281f, -0.677246f, 0.391602f, -0.677246f, 0.544434f, -0.677246f, 0.643555f, -0.578613f,
-0.742676f, -0.47998f, 0.742676f, -0.332031f, 0.742676f, -0.203125f, 0.665039f, -0.10791f,
-0.587402f, -0.0126953f, 0.478027f, 0.00585938f, 0.391113f, -0.640137f, 0.303223f,
--0.640137f, 0.255371f, -0.548828f, 0.215332f, -0.472168f, 0.215332f, -0.330566f,
-0.215332f, -0.160645f, 0.275391f, -0.0786133f, 0.317383f, -0.0214844f, 0.391113f,
--0.0214844f, 0.465332f, -0.0214844f, 0.506836f, -0.0776367f, 0.566895f, -0.158203f,
-0.566895f, -0.319824f, 0.566895f, -0.479004f, 0.529297f, -0.550293f, 0.482422f, -0.640137f,
-0.391113f, -0.640137f, 0.265625f, -0.301758f, 0.265625f, -0.116211f, 0.265625f, -0.0625f,
-0.272217f, -0.048584f, 0.278809f, -0.034668f, 0.29541f, -0.0263672f, 0.312012f, -0.0180664f,
-0.357422f, -0.0180664f, 0.357422f, 0, 0.0185547f, 0, 0.0185547f, -0.0180664f, 0.0644531f,
--0.0180664f, 0.0808105f, -0.0266113f, 0.097168f, -0.0351562f, 0.10376f, -0.0488281f,
-0.110352f, -0.0625f, 0.110352f, -0.116211f, 0.110352f, -0.545898f, 0.110352f, -0.599609f,
-0.10376f, -0.613525f, 0.097168f, -0.627441f, 0.0805664f, -0.635742f, 0.0639648f,
--0.644043f, 0.0185547f, -0.644043f, 0.0185547f, -0.662109f, 0.326172f, -0.662109f,
-0.446289f, -0.662109f, 0.501953f, -0.645508f, 0.557617f, -0.628906f, 0.592773f, -0.584229f,
-0.62793f, -0.539551f, 0.62793f, -0.479492f, 0.62793f, -0.40625f, 0.575195f, -0.358398f,
-0.541504f, -0.328125f, 0.480957f, -0.312988f, 0.640137f, -0.0888672f, 0.671387f,
--0.0454102f, 0.68457f, -0.034668f, 0.70459f, -0.0195312f, 0.730957f, -0.0180664f,
-0.730957f, 0, 0.522461f, 0, 0.309082f, -0.301758f, 0.265625f, -0.626465f, 0.265625f,
--0.336426f, 0.293457f, -0.336426f, 0.361328f, -0.336426f, 0.39502f, -0.348877f, 0.428711f,
--0.361328f, 0.447998f, -0.393799f, 0.467285f, -0.42627f, 0.467285f, -0.478516f, 0.467285f,
--0.554199f, 0.431885f, -0.590332f, 0.396484f, -0.626465f, 0.317871f, -0.626465f,
-0.469727f, -0.677246f, 0.475098f, -0.456543f, 0.455078f, -0.456543f, 0.440918f, -0.539551f,
-0.385498f, -0.590088f, 0.330078f, -0.640625f, 0.265625f, -0.640625f, 0.21582f, -0.640625f,
-0.186768f, -0.614014f, 0.157715f, -0.587402f, 0.157715f, -0.552734f, 0.157715f, -0.530762f,
-0.167969f, -0.513672f, 0.182129f, -0.490723f, 0.213379f, -0.468262f, 0.236328f, -0.452148f,
-0.319336f, -0.411133f, 0.435547f, -0.354004f, 0.476074f, -0.303223f, 0.516113f, -0.252441f,
-0.516113f, -0.187012f, 0.516113f, -0.104004f, 0.451416f, -0.0441895f, 0.386719f,
-0.015625f, 0.287109f, 0.015625f, 0.255859f, 0.015625f, 0.228027f, 0.00927734f, 0.200195f,
-0.00292969f, 0.158203f, -0.0146484f, 0.134766f, -0.0244141f, 0.119629f, -0.0244141f,
-0.106934f, -0.0244141f, 0.0927734f, -0.0146484f, 0.0786133f, -0.00488281f, 0.0698242f,
-0.0151367f, 0.0517578f, 0.0151367f, 0.0517578f, -0.234863f, 0.0698242f, -0.234863f,
-0.0913086f, -0.129395f, 0.152588f, -0.0739746f, 0.213867f, -0.0185547f, 0.284668f,
--0.0185547f, 0.339355f, -0.0185547f, 0.371826f, -0.0483398f, 0.404297f, -0.078125f,
-0.404297f, -0.117676f, 0.404297f, -0.141113f, 0.391846f, -0.163086f, 0.379395f, -0.185059f,
-0.354004f, -0.204834f, 0.328613f, -0.224609f, 0.26416f, -0.256348f, 0.173828f, -0.300781f,
-0.134277f, -0.332031f, 0.0947266f, -0.363281f, 0.0734863f, -0.401855f, 0.0522461f,
--0.44043f, 0.0522461f, -0.486816f, 0.0522461f, -0.565918f, 0.110352f, -0.621582f,
-0.168457f, -0.677246f, 0.256836f, -0.677246f, 0.289062f, -0.677246f, 0.319336f, -0.669434f,
-0.342285f, -0.663574f, 0.375244f, -0.647705f, 0.408203f, -0.631836f, 0.421387f, -0.631836f,
-0.434082f, -0.631836f, 0.441406f, -0.639648f, 0.44873f, -0.647461f, 0.455078f, -0.677246f,
-0.630859f, -0.662109f, 0.630859f, -0.48291f, 0.613281f, -0.48291f, 0.597656f, -0.544922f,
-0.578613f, -0.572021f, 0.55957f, -0.599121f, 0.526367f, -0.615234f, 0.507812f, -0.624023f,
-0.461426f, -0.624023f, 0.412109f, -0.624023f, 0.412109f, -0.113281f, 0.412109f, -0.0625f,
-0.417725f, -0.0498047f, 0.42334f, -0.0371094f, 0.439697f, -0.0275879f, 0.456055f,
--0.0180664f, 0.484375f, -0.0180664f, 0.506348f, -0.0180664f, 0.506348f, 0, 0.159668f,
-0, 0.159668f, -0.0180664f, 0.181641f, -0.0180664f, 0.210449f, -0.0180664f, 0.228027f,
--0.0283203f, 0.240723f, -0.0351562f, 0.248047f, -0.0517578f, 0.253418f, -0.0634766f,
-0.253418f, -0.113281f, 0.253418f, -0.624023f, 0.205566f, -0.624023f, 0.138672f, -0.624023f,
-0.108398f, -0.595703f, 0.065918f, -0.556152f, 0.0546875f, -0.48291f, 0.0361328f,
--0.48291f, 0.0361328f, -0.662109f, 0.0234375f, -0.662109f, 0.365234f, -0.662109f,
-0.365234f, -0.644043f, 0.348145f, -0.644043f, 0.30957f, -0.644043f, 0.295166f, -0.635986f,
-0.280762f, -0.62793f, 0.274658f, -0.61377f, 0.268555f, -0.599609f, 0.268555f, -0.542969f,
-0.268555f, -0.21875f, 0.268555f, -0.129883f, 0.281982f, -0.101074f, 0.29541f, -0.0722656f,
-0.326172f, -0.0532227f, 0.356934f, -0.0341797f, 0.403809f, -0.0341797f, 0.45752f,
--0.0341797f, 0.495361f, -0.0583496f, 0.533203f, -0.0825195f, 0.552002f, -0.125f,
-0.570801f, -0.16748f, 0.570801f, -0.272949f, 0.570801f, -0.542969f, 0.570801f, -0.587402f,
-0.561523f, -0.606445f, 0.552246f, -0.625488f, 0.538086f, -0.632812f, 0.516113f, -0.644043f,
-0.476074f, -0.644043f, 0.476074f, -0.662109f, 0.705078f, -0.662109f, 0.705078f, -0.644043f,
-0.691406f, -0.644043f, 0.663574f, -0.644043f, 0.64502f, -0.632812f, 0.626465f, -0.621582f,
-0.618164f, -0.599121f, 0.611816f, -0.583496f, 0.611816f, -0.542969f, 0.611816f, -0.291504f,
-0.611816f, -0.174805f, 0.596436f, -0.123047f, 0.581055f, -0.0712891f, 0.521484f,
--0.027832f, 0.461914f, 0.015625f, 0.358887f, 0.015625f, 0.272949f, 0.015625f, 0.226074f,
--0.00732422f, 0.162109f, -0.0385742f, 0.135742f, -0.0874023f, 0.109375f, -0.13623f,
-0.109375f, -0.21875f, 0.109375f, -0.542969f, 0.109375f, -0.600098f, 0.103027f, -0.614014f,
-0.0966797f, -0.62793f, 0.0810547f, -0.63623f, 0.0654297f, -0.644531f, 0.0234375f,
--0.644043f, 0.711914f, -0.662109f, 0.711914f, -0.644043f, 0.675781f, -0.638184f,
-0.647461f, -0.605469f, 0.626953f, -0.581055f, 0.586426f, -0.490723f, 0.358398f, 0.0151367f,
-0.342285f, 0.0151367f, 0.115234f, -0.51123f, 0.0742188f, -0.606445f, 0.0603027f,
--0.623047f, 0.0463867f, -0.639648f, 0.0078125f, -0.644043f, 0.0078125f, -0.662109f,
-0.325195f, -0.662109f, 0.325195f, -0.644043f, 0.314453f, -0.644043f, 0.271484f, -0.644043f,
-0.255859f, -0.633301f, 0.244629f, -0.625977f, 0.244629f, -0.611816f, 0.244629f, -0.603027f,
-0.248535f, -0.591064f, 0.252441f, -0.579102f, 0.274902f, -0.526855f, 0.416016f, -0.197266f,
-0.546875f, -0.490723f, 0.570312f, -0.543945f, 0.575684f, -0.562012f, 0.581055f, -0.580078f,
-0.581055f, -0.592773f, 0.581055f, -0.607422f, 0.573242f, -0.618652f, 0.56543f, -0.629883f,
-0.550293f, -0.635742f, 0.529297f, -0.644043f, 0.494629f, -0.644043f, 0.494629f, -0.662109f,
-0.991211f, -0.662109f, 0.991211f, -0.644043f, 0.972656f, -0.642578f, 0.959961f, -0.633789f,
-0.947266f, -0.625f, 0.9375f, -0.606934f, 0.93457f, -0.601074f, 0.906738f, -0.53125f,
-0.699219f, 0.0151367f, 0.680176f, 0.0151367f, 0.516113f, -0.411621f, 0.335449f, 0.0151367f,
-0.317383f, 0.0151367f, 0.0996094f, -0.525391f, 0.0664062f, -0.606934f, 0.0532227f,
--0.624023f, 0.0400391f, -0.641113f, 0.00878906f, -0.644043f, 0.00878906f, -0.662109f,
-0.295898f, -0.662109f, 0.295898f, -0.644043f, 0.26123f, -0.643066f, 0.249756f, -0.633545f,
-0.238281f, -0.624023f, 0.238281f, -0.609863f, 0.238281f, -0.591309f, 0.262207f, -0.53125f,
-0.39209f, -0.209961f, 0.496094f, -0.460938f, 0.46875f, -0.53125f, 0.446289f, -0.588867f,
-0.434082f, -0.608154f, 0.421875f, -0.627441f, 0.406006f, -0.635742f, 0.390137f, -0.644043f,
-0.359375f, -0.644043f, 0.359375f, -0.662109f, 0.680176f, -0.662109f, 0.680176f, -0.644043f,
-0.646484f, -0.643555f, 0.631836f, -0.638672f, 0.621582f, -0.635254f, 0.615723f, -0.627197f,
-0.609863f, -0.619141f, 0.609863f, -0.608887f, 0.609863f, -0.597656f, 0.631836f, -0.540039f,
-0.752441f, -0.226562f, 0.860352f, -0.510254f, 0.877441f, -0.554199f, 0.881348f, -0.570312f,
-0.885254f, -0.586426f, 0.885254f, -0.600098f, 0.885254f, -0.620117f, 0.871582f, -0.631592f,
-0.85791f, -0.643066f, 0.819336f, -0.644043f, 0.819336f, -0.662109f, 0.422363f, -0.388184f,
-0.60498f, -0.117188f, 0.650391f, -0.0498047f, 0.669678f, -0.0354004f, 0.688965f,
--0.0209961f, 0.715332f, -0.0180664f, 0.715332f, 0, 0.392578f, 0, 0.392578f, -0.0180664f,
-0.431152f, -0.0209961f, 0.442383f, -0.0297852f, 0.453613f, -0.0385742f, 0.453613f,
--0.0512695f, 0.453613f, -0.0600586f, 0.450195f, -0.0668945f, 0.443359f, -0.081543f,
-0.416016f, -0.121582f, 0.319336f, -0.264648f, 0.218262f, -0.141113f, 0.172852f, -0.0849609f,
-0.172852f, -0.0649414f, 0.172852f, -0.0507812f, 0.18457f, -0.0385742f, 0.196289f,
--0.0263672f, 0.219238f, -0.0209961f, 0.229492f, -0.0180664f, 0.26123f, -0.0180664f,
-0.26123f, 0, 0.00683594f, 0, 0.00683594f, -0.0180664f, 0.050293f, -0.0244141f, 0.0751953f,
--0.0415039f, 0.10791f, -0.0639648f, 0.166504f, -0.135254f, 0.297852f, -0.29541f,
-0.129395f, -0.542969f, 0.0878906f, -0.604004f, 0.0820312f, -0.61084f, 0.0688477f,
--0.626953f, 0.0561523f, -0.633789f, 0.043457f, -0.640625f, 0.0209961f, -0.644043f,
-0.0209961f, -0.662109f, 0.349609f, -0.662109f, 0.349609f, -0.644043f, 0.333008f,
--0.644043f, 0.304688f, -0.644043f, 0.293457f, -0.63501f, 0.282227f, -0.625977f, 0.282227f,
--0.612305f, 0.282227f, -0.601562f, 0.285645f, -0.59375f, 0.319336f, -0.542969f, 0.401367f,
--0.417969f, 0.471191f, -0.503418f, 0.524902f, -0.569336f, 0.524902f, -0.595703f,
-0.524902f, -0.608887f, 0.517334f, -0.620117f, 0.509766f, -0.631348f, 0.495605f, -0.637695f,
-0.481445f, -0.644043f, 0.45166f, -0.644043f, 0.45166f, -0.662109f, 0.695312f, -0.662109f,
-0.695312f, -0.644043f, 0.666504f, -0.643555f, 0.648926f, -0.636963f, 0.631348f, -0.630371f,
-0.611328f, -0.612305f, 0.598633f, -0.600586f, 0.547852f, -0.539551f, 0.710938f, -0.662109f,
-0.710938f, -0.644043f, 0.678223f, -0.639648f, 0.660645f, -0.625f, 0.63623f, -0.604492f,
-0.583496f, -0.513184f, 0.439941f, -0.273438f, 0.439941f, -0.113281f, 0.439941f, -0.0620117f,
-0.445312f, -0.0495605f, 0.450684f, -0.0371094f, 0.466553f, -0.0275879f, 0.482422f,
--0.0180664f, 0.508789f, -0.0180664f, 0.545898f, -0.0180664f, 0.545898f, 0, 0.174316f,
-0, 0.174316f, -0.0180664f, 0.208984f, -0.0180664f, 0.238281f, -0.0180664f, 0.255371f,
--0.0283203f, 0.268066f, -0.0351562f, 0.275391f, -0.0517578f, 0.280762f, -0.0634766f,
-0.280762f, -0.113281f, 0.280762f, -0.246094f, 0.125f, -0.529785f, 0.0786133f, -0.61377f,
-0.0595703f, -0.628662f, 0.0405273f, -0.643555f, 0.00878906f, -0.644043f, 0.00878906f,
--0.662109f, 0.326172f, -0.662109f, 0.326172f, -0.644043f, 0.312012f, -0.644043f,
-0.283203f, -0.644043f, 0.271729f, -0.635742f, 0.260254f, -0.627441f, 0.260254f, -0.618164f,
-0.260254f, -0.600586f, 0.299316f, -0.529785f, 0.418945f, -0.310547f, 0.538086f, -0.510254f,
-0.58252f, -0.583496f, 0.58252f, -0.607422f, 0.58252f, -0.620605f, 0.569824f, -0.629395f,
-0.553223f, -0.641602f, 0.508789f, -0.644043f, 0.508789f, -0.662109f, 0.610352f, -0.662109f,
-0.221191f, -0.0371094f, 0.347168f, -0.0371094f, 0.436523f, -0.0371094f, 0.472168f,
--0.0483398f, 0.530273f, -0.065918f, 0.572266f, -0.113037f, 0.614258f, -0.160156f,
-0.630371f, -0.239258f, 0.649414f, -0.239258f, 0.622559f, 0, 0.0161133f, 0, 0.405762f,
--0.625977f, 0.307617f, -0.625977f, 0.250488f, -0.625977f, 0.232422f, -0.622559f,
-0.198242f, -0.616211f, 0.168213f, -0.597412f, 0.138184f, -0.578613f, 0.118408f, -0.547363f,
-0.0986328f, -0.516113f, 0.0874023f, -0.468262f, 0.0693359f, -0.468262f, 0.0874023f,
--0.662109f, 0.104492f, 0.182617f, 0.104492f, -0.662109f, 0.300781f, -0.662109f, 0.300781f,
--0.641602f, 0.278809f, -0.641602f, 0.246582f, -0.641602f, 0.235596f, -0.63501f, 0.224609f,
--0.628418f, 0.218994f, -0.615479f, 0.213379f, -0.602539f, 0.213379f, -0.553223f,
-0.213379f, 0.0771484f, 0.213379f, 0.124023f, 0.215332f, 0.130859f, 0.219727f, 0.148438f,
-0.231689f, 0.156738f, 0.243652f, 0.165039f, 0.278809f, 0.165039f, 0.300781f, 0.165039f,
-0.300781f, 0.182617f, 0.000976562f, -0.677246f, 0.0625f, -0.677246f, 0.280762f, 0.0151367f,
-0.217773f, 0.0151367f, 0.229004f, -0.662109f, 0.229004f, 0.182617f, 0.0327148f, 0.182617f,
-0.0327148f, 0.164062f, 0.0546875f, 0.164062f, 0.0869141f, 0.164062f, 0.0979004f,
-0.157715f, 0.108887f, 0.151367f, 0.114502f, 0.138184f, 0.120117f, 0.125f, 0.120117f,
-0.0761719f, 0.120117f, -0.554688f, 0.120117f, -0.601562f, 0.118164f, -0.608398f,
-0.11377f, -0.625488f, 0.101807f, -0.634033f, 0.0898438f, -0.642578f, 0.0546875f,
--0.642578f, 0.0327148f, -0.642578f, 0.0327148f, -0.662109f, 0.0717773f, -0.325195f,
-0.272461f, -0.675781f, 0.3125f, -0.675781f, 0.509766f, -0.325195f, 0.432129f, -0.325195f,
-0.288086f, -0.575195f, 0.146484f, -0.325195f, -0.00927734f, 0.151855f, 0.509277f,
-0.151855f, 0.509277f, 0.21582f, -0.00927734f, 0.21582f, 0.0185547f, -0.68457f, 0.165527f,
--0.68457f, 0.222168f, -0.515137f, 0.180664f, -0.515137f, 0.285645f, -0.0673828f,
-0.202148f, 0.00634766f, 0.135742f, 0.00634766f, 0.0966797f, 0.00634766f, 0.0708008f,
--0.0192871f, 0.0449219f, -0.0449219f, 0.0449219f, -0.0834961f, 0.0449219f, -0.135742f,
-0.0898438f, -0.17749f, 0.134766f, -0.219238f, 0.285645f, -0.288574f, 0.285645f, -0.334473f,
-0.285645f, -0.38623f, 0.280029f, -0.399658f, 0.274414f, -0.413086f, 0.258789f, -0.423096f,
-0.243164f, -0.433105f, 0.223633f, -0.433105f, 0.191895f, -0.433105f, 0.171387f, -0.418945f,
-0.158691f, -0.410156f, 0.158691f, -0.398438f, 0.158691f, -0.388184f, 0.172363f, -0.373047f,
-0.190918f, -0.352051f, 0.190918f, -0.33252f, 0.190918f, -0.308594f, 0.173096f, -0.291748f,
-0.155273f, -0.274902f, 0.126465f, -0.274902f, 0.0957031f, -0.274902f, 0.0749512f,
--0.293457f, 0.0541992f, -0.312012f, 0.0541992f, -0.336914f, 0.0541992f, -0.37207f,
-0.0820312f, -0.404053f, 0.109863f, -0.436035f, 0.159668f, -0.453125f, 0.209473f,
--0.470215f, 0.263184f, -0.470215f, 0.328125f, -0.470215f, 0.365967f, -0.442627f,
-0.403809f, -0.415039f, 0.415039f, -0.382812f, 0.421875f, -0.362305f, 0.421875f, -0.288574f,
-0.421875f, -0.111328f, 0.421875f, -0.0800781f, 0.424316f, -0.0720215f, 0.426758f,
--0.0639648f, 0.431641f, -0.0600586f, 0.436523f, -0.0561523f, 0.442871f, -0.0561523f,
-0.455566f, -0.0561523f, 0.46875f, -0.0742188f, 0.483398f, -0.0625f, 0.458984f, -0.0263672f,
-0.432861f, -0.0100098f, 0.406738f, 0.00634766f, 0.373535f, 0.00634766f, 0.334473f,
-0.00634766f, 0.3125f, -0.0119629f, 0.290527f, -0.0302734f, 0.285645f, -0.0673828f,
-0.285645f, -0.103027f, 0.285645f, -0.255859f, 0.226562f, -0.221191f, 0.197754f, -0.181641f,
-0.178711f, -0.155273f, 0.178711f, -0.128418f, 0.178711f, -0.105957f, 0.194824f, -0.0888672f,
-0.207031f, -0.0756836f, 0.229004f, -0.0756836f, 0.253418f, -0.0756836f, 0.285645f,
--0.103027f, 0.210449f, -0.662109f, 0.210449f, -0.410645f, 0.268066f, -0.470215f,
-0.336426f, -0.470215f, 0.383301f, -0.470215f, 0.424805f, -0.442627f, 0.466309f, -0.415039f,
-0.489746f, -0.364258f, 0.513184f, -0.313477f, 0.513184f, -0.24707f, 0.513184f, -0.172363f,
-0.483398f, -0.111328f, 0.453613f, -0.050293f, 0.403809f, -0.0183105f, 0.354004f,
-0.0136719f, 0.290039f, 0.0136719f, 0.25293f, 0.0136719f, 0.224121f, 0.00195312f,
-0.195312f, -0.00976562f, 0.16748f, -0.0361328f, 0.0917969f, 0.0131836f, 0.0751953f,
-0.0131836f, 0.0751953f, -0.567383f, 0.0751953f, -0.606934f, 0.0717773f, -0.616211f,
-0.0668945f, -0.629883f, 0.0563965f, -0.636475f, 0.0458984f, -0.643066f, 0.0209961f,
--0.644043f, 0.0209961f, -0.662109f, 0.210449f, -0.367188f, 0.210449f, -0.164062f,
-0.210449f, -0.102051f, 0.213379f, -0.0849609f, 0.218262f, -0.0561523f, 0.236816f,
--0.0383301f, 0.255371f, -0.0205078f, 0.28418f, -0.0205078f, 0.309082f, -0.0205078f,
-0.326904f, -0.034668f, 0.344727f, -0.0488281f, 0.356689f, -0.0908203f, 0.368652f,
--0.132812f, 0.368652f, -0.242188f, 0.368652f, -0.347168f, 0.342285f, -0.38623f, 0.323242f,
--0.414551f, 0.291016f, -0.414551f, 0.249023f, -0.414551f, 0.210449f, -0.367188f,
-0.40625f, -0.117676f, 0.421387f, -0.105957f, 0.38916f, -0.0454102f, 0.341064f, -0.0158691f,
-0.292969f, 0.0136719f, 0.23877f, 0.0136719f, 0.147461f, 0.0136719f, 0.0927734f, -0.0551758f,
-0.0380859f, -0.124023f, 0.0380859f, -0.220703f, 0.0380859f, -0.313965f, 0.0878906f,
--0.384766f, 0.147949f, -0.470215f, 0.253418f, -0.470215f, 0.324219f, -0.470215f,
-0.365967f, -0.43457f, 0.407715f, -0.398926f, 0.407715f, -0.35498f, 0.407715f, -0.327148f,
-0.390869f, -0.310547f, 0.374023f, -0.293945f, 0.34668f, -0.293945f, 0.317871f, -0.293945f,
-0.299072f, -0.312988f, 0.280273f, -0.332031f, 0.275879f, -0.380859f, 0.272949f, -0.411621f,
-0.261719f, -0.423828f, 0.250488f, -0.436035f, 0.235352f, -0.436035f, 0.211914f, -0.436035f,
-0.195312f, -0.411133f, 0.169922f, -0.373535f, 0.169922f, -0.295898f, 0.169922f, -0.231445f,
-0.19043f, -0.172607f, 0.210938f, -0.11377f, 0.246582f, -0.0849609f, 0.273438f, -0.0639648f,
-0.310059f, -0.0639648f, 0.333984f, -0.0639648f, 0.355469f, -0.0751953f, 0.376953f,
--0.0864258f, 0.40625f, -0.117676f, 0.477539f, -0.662109f, 0.477539f, -0.136719f,
-0.477539f, -0.0834961f, 0.480469f, -0.0737305f, 0.484375f, -0.0576172f, 0.495361f,
--0.0498047f, 0.506348f, -0.0419922f, 0.533691f, -0.0400391f, 0.533691f, -0.0239258f,
-0.34082f, 0.0136719f, 0.34082f, -0.0585938f, 0.306152f, -0.0166016f, 0.279053f, -0.00146484f,
-0.251953f, 0.0136719f, 0.217773f, 0.0136719f, 0.130371f, 0.0136719f, 0.0795898f,
--0.0644531f, 0.0385742f, -0.12793f, 0.0385742f, -0.220215f, 0.0385742f, -0.293945f,
-0.0639648f, -0.352295f, 0.0893555f, -0.410645f, 0.133545f, -0.44043f, 0.177734f,
--0.470215f, 0.228516f, -0.470215f, 0.26123f, -0.470215f, 0.286621f, -0.45752f, 0.312012f,
--0.444824f, 0.34082f, -0.413086f, 0.34082f, -0.550781f, 0.34082f, -0.603027f, 0.336426f,
--0.61377f, 0.330566f, -0.62793f, 0.318848f, -0.634766f, 0.307129f, -0.641602f, 0.274902f,
--0.641602f, 0.274902f, -0.662109f, 0.34082f, -0.352539f, 0.304688f, -0.421875f, 0.252441f,
--0.421875f, 0.234375f, -0.421875f, 0.222656f, -0.412109f, 0.20459f, -0.396973f, 0.193115f,
--0.358887f, 0.181641f, -0.320801f, 0.181641f, -0.242188f, 0.181641f, -0.155762f,
-0.194336f, -0.114258f, 0.207031f, -0.0727539f, 0.229004f, -0.0541992f, 0.240234f,
--0.0449219f, 0.259766f, -0.0449219f, 0.302734f, -0.0449219f, 0.34082f, -0.112305f,
-0.42041f, -0.244629f, 0.169922f, -0.244629f, 0.174316f, -0.153809f, 0.218262f, -0.101074f,
-0.251953f, -0.0605469f, 0.299316f, -0.0605469f, 0.328613f, -0.0605469f, 0.352539f,
--0.0769043f, 0.376465f, -0.0932617f, 0.403809f, -0.135742f, 0.42041f, -0.125f, 0.383301f,
--0.0493164f, 0.338379f, -0.0178223f, 0.293457f, 0.0136719f, 0.234375f, 0.0136719f,
-0.132812f, 0.0136719f, 0.0805664f, -0.0644531f, 0.0385742f, -0.127441f, 0.0385742f,
--0.220703f, 0.0385742f, -0.334961f, 0.100342f, -0.402588f, 0.162109f, -0.470215f,
-0.245117f, -0.470215f, 0.314453f, -0.470215f, 0.365479f, -0.41333f, 0.416504f, -0.356445f,
-0.42041f, -0.244629f, 0.300293f, -0.277344f, 0.300293f, -0.355957f, 0.291748f, -0.385254f,
-0.283203f, -0.414551f, 0.265137f, -0.429688f, 0.254883f, -0.438477f, 0.237793f, -0.438477f,
-0.212402f, -0.438477f, 0.196289f, -0.413574f, 0.16748f, -0.370117f, 0.16748f, -0.294434f,
-0.16748f, -0.277344f, 0.233887f, -0.408691f, 0.233887f, -0.0917969f, 0.233887f, -0.0458984f,
-0.243652f, -0.0341797f, 0.259277f, -0.0161133f, 0.30127f, -0.0175781f, 0.30127f,
-0, 0.0322266f, 0, 0.0322266f, -0.0175781f, 0.0629883f, -0.0180664f, 0.0759277f, -0.0246582f,
-0.0888672f, -0.03125f, 0.09375f, -0.0429688f, 0.0986328f, -0.0546875f, 0.0986328f,
--0.0917969f, 0.0986328f, -0.408691f, 0.0322266f, -0.408691f, 0.0322266f, -0.456543f,
-0.0986328f, -0.456543f, 0.0986328f, -0.490234f, 0.0981445f, -0.513184f, 0.0981445f,
--0.583496f, 0.149658f, -0.630371f, 0.201172f, -0.677246f, 0.289062f, -0.677246f,
-0.349121f, -0.677246f, 0.378174f, -0.654785f, 0.407227f, -0.632324f, 0.407227f, -0.60498f,
-0.407227f, -0.583008f, 0.38916f, -0.566895f, 0.371094f, -0.550781f, 0.341309f, -0.550781f,
-0.315918f, -0.550781f, 0.301025f, -0.563965f, 0.286133f, -0.577148f, 0.286133f, -0.593262f,
-0.286133f, -0.597656f, 0.289062f, -0.611328f, 0.291016f, -0.619629f, 0.291016f, -0.626953f,
-0.291016f, -0.637207f, 0.285156f, -0.64209f, 0.277344f, -0.649414f, 0.266113f, -0.649414f,
-0.251953f, -0.649414f, 0.242432f, -0.637695f, 0.23291f, -0.625977f, 0.23291f, -0.600098f,
-0.233887f, -0.514648f, 0.233887f, -0.456543f, 0.30127f, -0.456543f, 0.30127f, -0.408691f,
-0.32666f, -0.451172f, 0.480469f, -0.451172f, 0.480469f, -0.397461f, 0.393066f, -0.397461f,
-0.416992f, -0.373535f, 0.42627f, -0.354004f, 0.437988f, -0.327637f, 0.437988f, -0.298828f,
-0.437988f, -0.25f, 0.410889f, -0.214111f, 0.383789f, -0.178223f, 0.337158f, -0.157959f,
-0.290527f, -0.137695f, 0.254395f, -0.137695f, 0.251465f, -0.137695f, 0.195801f, -0.140137f,
-0.173828f, -0.140137f, 0.158936f, -0.125732f, 0.144043f, -0.111328f, 0.144043f, -0.0913086f,
-0.144043f, -0.0737305f, 0.157471f, -0.0625f, 0.170898f, -0.0512695f, 0.201172f, -0.0512695f,
-0.285645f, -0.0522461f, 0.388184f, -0.0522461f, 0.426758f, -0.0297852f, 0.481934f,
-0.00146484f, 0.481934f, 0.0664062f, 0.481934f, 0.10791f, 0.456543f, 0.141846f, 0.431152f,
-0.175781f, 0.389648f, 0.191895f, 0.32666f, 0.21582f, 0.244629f, 0.21582f, 0.183105f,
-0.21582f, 0.132324f, 0.203857f, 0.081543f, 0.191895f, 0.0595703f, 0.170654f, 0.0375977f,
-0.149414f, 0.0375977f, 0.125977f, 0.0375977f, 0.103516f, 0.0544434f, 0.0856934f,
-0.0712891f, 0.0678711f, 0.117188f, 0.0556641f, 0.0537109f, 0.0244141f, 0.0537109f,
--0.03125f, 0.0537109f, -0.0649414f, 0.0795898f, -0.0966797f, 0.105469f, -0.128418f,
-0.161621f, -0.151855f, 0.0961914f, -0.175781f, 0.0668945f, -0.214844f, 0.0375977f,
--0.253906f, 0.0375977f, -0.305176f, 0.0375977f, -0.37207f, 0.0922852f, -0.421143f,
-0.146973f, -0.470215f, 0.23291f, -0.470215f, 0.27832f, -0.470215f, 0.32666f, -0.451172f,
-0.242188f, -0.439941f, 0.213867f, -0.439941f, 0.194336f, -0.411377f, 0.174805f, -0.382812f,
-0.174805f, -0.292969f, 0.174805f, -0.220215f, 0.194092f, -0.193115f, 0.213379f, -0.166016f,
-0.239746f, -0.166016f, 0.269043f, -0.166016f, 0.288574f, -0.192871f, 0.308105f, -0.219727f,
-0.308105f, -0.297363f, 0.308105f, -0.384766f, 0.286133f, -0.416504f, 0.270508f, -0.439941f,
-0.242188f, -0.439941f, 0.213379f, 0.0673828f, 0.163574f, 0.0673828f, 0.147461f, 0.0756836f,
-0.119629f, 0.0908203f, 0.119629f, 0.116699f, 0.119629f, 0.141602f, 0.148438f, 0.161865f,
-0.177246f, 0.182129f, 0.256836f, 0.182129f, 0.324707f, 0.182129f, 0.363525f, 0.164062f,
-0.402344f, 0.145996f, 0.402344f, 0.113281f, 0.402344f, 0.101074f, 0.39502f, 0.0927734f,
-0.381836f, 0.078125f, 0.355225f, 0.0727539f, 0.328613f, 0.0673828f, 0.213379f, 0.0673828f,
-0.220215f, -0.662109f, 0.220215f, -0.397949f, 0.257812f, -0.4375f, 0.289062f, -0.453857f,
-0.320312f, -0.470215f, 0.354004f, -0.470215f, 0.396973f, -0.470215f, 0.42749f, -0.445801f,
-0.458008f, -0.421387f, 0.468018f, -0.388428f, 0.478027f, -0.355469f, 0.478027f, -0.277344f,
-0.478027f, -0.0991211f, 0.478027f, -0.046875f, 0.487793f, -0.0339355f, 0.497559f,
--0.0209961f, 0.527344f, -0.0175781f, 0.527344f, 0, 0.295898f, 0, 0.295898f, -0.0175781f,
-0.320312f, -0.0209961f, 0.33252f, -0.0371094f, 0.341309f, -0.0498047f, 0.341309f,
--0.0991211f, 0.341309f, -0.302734f, 0.341309f, -0.359375f, 0.336914f, -0.373779f,
-0.33252f, -0.388184f, 0.322021f, -0.39624f, 0.311523f, -0.404297f, 0.29834f, -0.404297f,
-0.278809f, -0.404297f, 0.260254f, -0.390869f, 0.241699f, -0.377441f, 0.220215f, -0.34375f,
-0.220215f, -0.0991211f, 0.220215f, -0.050293f, 0.227539f, -0.0380859f, 0.236816f,
--0.0214844f, 0.265625f, -0.0175781f, 0.265625f, 0, 0.0341797f, 0, 0.0341797f, -0.0175781f,
-0.0629883f, -0.0205078f, 0.0751953f, -0.0361328f, 0.0834961f, -0.046875f, 0.0834961f,
--0.0991211f, 0.0834961f, -0.562988f, 0.0834961f, -0.614746f, 0.0739746f, -0.627441f,
-0.0644531f, -0.640137f, 0.0341797f, -0.644043f, 0.0341797f, -0.662109f, 0.143555f,
--0.677734f, 0.175293f, -0.677734f, 0.197266f, -0.655518f, 0.219238f, -0.633301f,
-0.219238f, -0.602051f, 0.219238f, -0.570801f, 0.197021f, -0.548828f, 0.174805f, -0.526855f,
-0.143555f, -0.526855f, 0.112305f, -0.526855f, 0.090332f, -0.548828f, 0.0683594f,
--0.570801f, 0.0683594f, -0.602051f, 0.0683594f, -0.633301f, 0.090332f, -0.655518f,
-0.112305f, -0.677734f, 0.143555f, -0.677734f, 0.211914f, -0.456543f, 0.211914f, -0.0947266f,
-0.211914f, -0.0463867f, 0.223145f, -0.032959f, 0.234375f, -0.0195312f, 0.26709f,
--0.0175781f, 0.26709f, 0, 0.0205078f, 0, 0.0205078f, -0.0175781f, 0.0507812f, -0.0185547f,
-0.0654297f, -0.0351562f, 0.0751953f, -0.0463867f, 0.0751953f, -0.0947266f, 0.0751953f,
--0.361328f, 0.0751953f, -0.409668f, 0.0639648f, -0.423096f, 0.0527344f, -0.436523f,
-0.0205078f, -0.438477f, 0.0205078f, -0.456543f, 0.173828f, -0.677246f, 0.205078f,
--0.677246f, 0.226807f, -0.655518f, 0.248535f, -0.633789f, 0.248535f, -0.603027f,
-0.248535f, -0.571777f, 0.226562f, -0.549805f, 0.20459f, -0.527832f, 0.173828f, -0.527832f,
-0.143066f, -0.527832f, 0.121094f, -0.549805f, 0.0991211f, -0.571777f, 0.0991211f,
--0.603027f, 0.0991211f, -0.633789f, 0.12085f, -0.655518f, 0.142578f, -0.677246f,
-0.173828f, -0.677246f, 0.242188f, -0.456543f, 0.242188f, 0.0161133f, 0.242188f, 0.0825195f,
-0.233887f, 0.114258f, 0.22168f, 0.160156f, 0.185303f, 0.187988f, 0.148926f, 0.21582f,
-0.0893555f, 0.21582f, 0.0292969f, 0.21582f, 0.000732422f, 0.191406f, -0.027832f,
-0.166992f, -0.027832f, 0.132324f, -0.027832f, 0.11084f, -0.0129395f, 0.0949707f,
-0.00195312f, 0.0791016f, 0.0219727f, 0.0791016f, 0.0405273f, 0.0791016f, 0.0512695f,
-0.0900879f, 0.0620117f, 0.101074f, 0.0620117f, 0.123047f, 0.0620117f, 0.128906f,
-0.0615234f, 0.136719f, 0.0605469f, 0.146973f, 0.0605469f, 0.150879f, 0.0605469f,
-0.167969f, 0.0683594f, 0.17627f, 0.0761719f, 0.18457f, 0.0883789f, 0.18457f, 0.0996094f,
-0.18457f, 0.107666f, 0.174805f, 0.115723f, 0.165039f, 0.115723f, 0.146973f, 0.115723f,
-0.137207f, 0.112793f, 0.107422f, 0.10791f, 0.0532227f, 0.107422f, 0.0419922f, 0.105957f,
--0.0737305f, 0.105957f, -0.355957f, 0.106445f, -0.381348f, 0.106445f, -0.412109f,
-0.0959473f, -0.423584f, 0.0854492f, -0.435059f, 0.0517578f, -0.438477f, 0.0517578f,
--0.456543f, 0.219238f, -0.662109f, 0.219238f, -0.226562f, 0.325195f, -0.330566f,
-0.35791f, -0.362305f, 0.365967f, -0.376465f, 0.374023f, -0.390625f, 0.374023f, -0.403809f,
-0.374023f, -0.416992f, 0.363281f, -0.425781f, 0.352539f, -0.43457f, 0.321289f, -0.438477f,
-0.321289f, -0.456543f, 0.525879f, -0.456543f, 0.525879f, -0.438477f, 0.496582f, -0.437012f,
-0.474609f, -0.424561f, 0.452637f, -0.412109f, 0.388672f, -0.349609f, 0.338867f, -0.300781f,
-0.446289f, -0.143555f, 0.51123f, -0.0478516f, 0.523438f, -0.0361328f, 0.540039f,
--0.0195312f, 0.56543f, -0.0175781f, 0.56543f, 0, 0.32959f, 0, 0.32959f, -0.0175781f,
-0.345215f, -0.0175781f, 0.352295f, -0.0234375f, 0.359375f, -0.0292969f, 0.359375f,
--0.0361328f, 0.359375f, -0.0473633f, 0.338867f, -0.0776367f, 0.248535f, -0.209961f,
-0.219238f, -0.181152f, 0.219238f, -0.0991211f, 0.219238f, -0.046875f, 0.229004f,
--0.0339355f, 0.23877f, -0.0209961f, 0.269043f, -0.0175781f, 0.269043f, 0, 0.0332031f,
-0, 0.0332031f, -0.0175781f, 0.0620117f, -0.0205078f, 0.0742188f, -0.0361328f, 0.0825195f,
--0.046875f, 0.0825195f, -0.0991211f, 0.0825195f, -0.562988f, 0.0825195f, -0.614746f,
-0.072998f, -0.627441f, 0.0634766f, -0.640137f, 0.0332031f, -0.644043f, 0.0332031f,
--0.662109f, 0.212402f, -0.662109f, 0.212402f, -0.0947266f, 0.212402f, -0.0463867f,
-0.223633f, -0.032959f, 0.234863f, -0.0195312f, 0.267578f, -0.0175781f, 0.267578f,
-0, 0.0209961f, 0, 0.0209961f, -0.0175781f, 0.0512695f, -0.0185547f, 0.065918f, -0.0351562f,
-0.0756836f, -0.0463867f, 0.0756836f, -0.0947266f, 0.0756836f, -0.567383f, 0.0756836f,
--0.615234f, 0.0644531f, -0.628662f, 0.0532227f, -0.64209f, 0.0209961f, -0.644043f,
-0.0209961f, -0.662109f, 0.223145f, -0.456543f, 0.223145f, -0.396484f, 0.260742f,
--0.4375f, 0.292725f, -0.453857f, 0.324707f, -0.470215f, 0.362793f, -0.470215f, 0.406738f,
--0.470215f, 0.436523f, -0.449707f, 0.466309f, -0.429199f, 0.482422f, -0.387207f,
-0.521484f, -0.431152f, 0.557373f, -0.450684f, 0.593262f, -0.470215f, 0.632324f, -0.470215f,
-0.679688f, -0.470215f, 0.707764f, -0.448486f, 0.73584f, -0.426758f, 0.746826f, -0.393311f,
-0.757812f, -0.359863f, 0.757812f, -0.286621f, 0.757812f, -0.0996094f, 0.757812f,
--0.046875f, 0.767334f, -0.0341797f, 0.776855f, -0.0214844f, 0.807129f, -0.0175781f,
-0.807129f, 0, 0.571289f, 0, 0.571289f, -0.0175781f, 0.599121f, -0.0200195f, 0.612305f,
--0.0390625f, 0.621094f, -0.0522461f, 0.621094f, -0.0996094f, 0.621094f, -0.295898f,
-0.621094f, -0.356934f, 0.616211f, -0.373535f, 0.611328f, -0.390137f, 0.60083f, -0.398193f,
-0.590332f, -0.40625f, 0.576172f, -0.40625f, 0.555176f, -0.40625f, 0.533691f, -0.390869f,
-0.512207f, -0.375488f, 0.490234f, -0.344727f, 0.490234f, -0.0996094f, 0.490234f,
--0.050293f, 0.498535f, -0.0375977f, 0.509766f, -0.0195312f, 0.541504f, -0.0175781f,
-0.541504f, 0, 0.305176f, 0, 0.305176f, -0.0175781f, 0.324219f, -0.0185547f, 0.335205f,
--0.0270996f, 0.346191f, -0.0356445f, 0.349854f, -0.0476074f, 0.353516f, -0.0595703f,
-0.353516f, -0.0996094f, 0.353516f, -0.295898f, 0.353516f, -0.35791f, 0.348633f, -0.373535f,
-0.34375f, -0.38916f, 0.332275f, -0.397949f, 0.320801f, -0.406738f, 0.307617f, -0.406738f,
-0.288086f, -0.406738f, 0.271973f, -0.396484f, 0.249023f, -0.381348f, 0.223145f, -0.344727f,
-0.223145f, -0.0996094f, 0.223145f, -0.0512695f, 0.232666f, -0.0358887f, 0.242188f,
--0.0205078f, 0.272461f, -0.0175781f, 0.272461f, 0, 0.0371094f, 0, 0.0371094f, -0.0175781f,
-0.065918f, -0.0205078f, 0.078125f, -0.0361328f, 0.0864258f, -0.046875f, 0.0864258f,
--0.0996094f, 0.0864258f, -0.357422f, 0.0864258f, -0.40918f, 0.0769043f, -0.421875f,
-0.0673828f, -0.43457f, 0.0371094f, -0.438477f, 0.0371094f, -0.456543f, 0.220215f,
--0.456543f, 0.220215f, -0.397461f, 0.255371f, -0.435547f, 0.287598f, -0.452881f,
-0.319824f, -0.470215f, 0.356934f, -0.470215f, 0.401367f, -0.470215f, 0.430664f, -0.445557f,
-0.459961f, -0.420898f, 0.469727f, -0.384277f, 0.477539f, -0.356445f, 0.477539f, -0.277344f,
-0.477539f, -0.0996094f, 0.477539f, -0.046875f, 0.487061f, -0.0339355f, 0.496582f,
--0.0209961f, 0.526855f, -0.0175781f, 0.526855f, 0, 0.295898f, 0, 0.295898f, -0.0175781f,
-0.321777f, -0.0209961f, 0.333008f, -0.0390625f, 0.34082f, -0.0512695f, 0.34082f,
--0.0996094f, 0.34082f, -0.302734f, 0.34082f, -0.358887f, 0.336426f, -0.373535f, 0.332031f,
--0.388184f, 0.321533f, -0.39624f, 0.311035f, -0.404297f, 0.29834f, -0.404297f, 0.256348f,
--0.404297f, 0.220215f, -0.344238f, 0.220215f, -0.0996094f, 0.220215f, -0.0483398f,
-0.229736f, -0.034668f, 0.239258f, -0.0209961f, 0.265137f, -0.0175781f, 0.265137f,
-0, 0.0341797f, 0, 0.0341797f, -0.0175781f, 0.0629883f, -0.0205078f, 0.0751953f, -0.0361328f,
-0.0834961f, -0.046875f, 0.0834961f, -0.0996094f, 0.0834961f, -0.357422f, 0.0834961f,
--0.40918f, 0.0739746f, -0.421875f, 0.0644531f, -0.43457f, 0.0341797f, -0.438477f,
-0.0341797f, -0.456543f, 0.249023f, -0.470215f, 0.308594f, -0.470215f, 0.359863f,
--0.439453f, 0.411133f, -0.408691f, 0.437744f, -0.352051f, 0.464355f, -0.29541f, 0.464355f,
--0.228027f, 0.464355f, -0.130859f, 0.415039f, -0.0654297f, 0.355469f, 0.0136719f,
-0.250488f, 0.0136719f, 0.147461f, 0.0136719f, 0.0917969f, -0.0585938f, 0.0361328f,
--0.130859f, 0.0361328f, -0.226074f, 0.0361328f, -0.324219f, 0.0930176f, -0.397217f,
-0.149902f, -0.470215f, 0.249023f, -0.470215f, 0.250977f, -0.435547f, 0.226074f, -0.435547f,
-0.208252f, -0.416748f, 0.19043f, -0.397949f, 0.184814f, -0.342529f, 0.179199f, -0.287109f,
-0.179199f, -0.188477f, 0.179199f, -0.13623f, 0.186035f, -0.0908203f, 0.191406f, -0.0561523f,
-0.208984f, -0.0380859f, 0.226562f, -0.0200195f, 0.249023f, -0.0200195f, 0.270996f,
--0.0200195f, 0.285645f, -0.0322266f, 0.304688f, -0.0488281f, 0.311035f, -0.0786133f,
-0.320801f, -0.125f, 0.320801f, -0.266113f, 0.320801f, -0.349121f, 0.311523f, -0.380127f,
-0.302246f, -0.411133f, 0.28418f, -0.425293f, 0.271484f, -0.435547f, 0.250977f, -0.435547f,
-0.210449f, -0.0463867f, 0.210449f, 0.123535f, 0.210449f, 0.158691f, 0.216064f, 0.171387f,
-0.22168f, 0.184082f, 0.233398f, 0.189941f, 0.245117f, 0.195801f, 0.279297f, 0.195801f,
-0.279297f, 0.213867f, 0.019043f, 0.213867f, 0.019043f, 0.195801f, 0.0493164f, 0.194824f,
-0.0639648f, 0.178711f, 0.0737305f, 0.16748f, 0.0737305f, 0.120605f, 0.0737305f, -0.361328f,
-0.0737305f, -0.409668f, 0.0625f, -0.423096f, 0.0512695f, -0.436523f, 0.019043f, -0.438477f,
-0.019043f, -0.456543f, 0.210449f, -0.456543f, 0.210449f, -0.396484f, 0.234375f, -0.431641f,
-0.259277f, -0.447266f, 0.294922f, -0.470215f, 0.336914f, -0.470215f, 0.387207f, -0.470215f,
-0.428467f, -0.438477f, 0.469727f, -0.406738f, 0.491211f, -0.35083f, 0.512695f, -0.294922f,
-0.512695f, -0.230469f, 0.512695f, -0.161133f, 0.490479f, -0.10376f, 0.468262f, -0.0463867f,
-0.426025f, -0.0163574f, 0.383789f, 0.0136719f, 0.332031f, 0.0136719f, 0.294434f,
-0.0136719f, 0.261719f, -0.00292969f, 0.237305f, -0.015625f, 0.210449f, -0.0463867f,
-0.210449f, -0.0957031f, 0.252441f, -0.0361328f, 0.300293f, -0.0361328f, 0.32666f,
--0.0361328f, 0.34375f, -0.0639648f, 0.369141f, -0.10498f, 0.369141f, -0.220215f,
-0.369141f, -0.338379f, 0.341309f, -0.381836f, 0.322754f, -0.410645f, 0.291504f, -0.410645f,
-0.242188f, -0.410645f, 0.210449f, -0.339355f, 0.340332f, -0.0478516f, 0.310547f,
--0.0166016f, 0.284668f, -0.00390625f, 0.250488f, 0.0136719f, 0.213379f, 0.0136719f,
-0.127441f, 0.0136719f, 0.0776367f, -0.0629883f, 0.0380859f, -0.124023f, 0.0380859f,
--0.208984f, 0.0380859f, -0.279785f, 0.0681152f, -0.342041f, 0.0981445f, -0.404297f,
-0.150635f, -0.437256f, 0.203125f, -0.470215f, 0.261719f, -0.470215f, 0.300781f, -0.470215f,
-0.331299f, -0.457031f, 0.361816f, -0.443848f, 0.383789f, -0.416992f, 0.460449f, -0.470215f,
-0.477051f, -0.470215f, 0.477051f, 0.121094f, 0.477051f, 0.166016f, 0.484863f, 0.177246f,
-0.497559f, 0.195312f, 0.536133f, 0.195801f, 0.536133f, 0.213867f, 0.272461f, 0.213867f,
-0.272461f, 0.195801f, 0.302734f, 0.195801f, 0.316406f, 0.188965f, 0.330078f, 0.182129f,
-0.335205f, 0.170898f, 0.340332f, 0.159668f, 0.340332f, 0.125f, 0.340332f, -0.0922852f,
-0.340332f, -0.280273f, 0.340332f, -0.358887f, 0.331787f, -0.384277f, 0.323242f, -0.409668f,
-0.300293f, -0.428223f, 0.288574f, -0.4375f, 0.270508f, -0.4375f, 0.233398f, -0.4375f,
-0.212891f, -0.404785f, 0.180664f, -0.354492f, 0.180664f, -0.217773f, 0.180664f, -0.112793f,
-0.208496f, -0.0703125f, 0.227539f, -0.0415039f, 0.257812f, -0.0415039f, 0.275391f,
--0.0415039f, 0.297607f, -0.0537109f, 0.319824f, -0.065918f, 0.340332f, -0.0922852f,
-0.223145f, -0.456543f, 0.223145f, -0.353027f, 0.268555f, -0.423828f, 0.302734f, -0.447021f,
-0.336914f, -0.470215f, 0.368652f, -0.470215f, 0.395996f, -0.470215f, 0.412354f, -0.453369f,
-0.428711f, -0.436523f, 0.428711f, -0.405762f, 0.428711f, -0.373047f, 0.412842f, -0.35498f,
-0.396973f, -0.336914f, 0.374512f, -0.336914f, 0.348633f, -0.336914f, 0.32959f, -0.353516f,
-0.310547f, -0.370117f, 0.307129f, -0.37207f, 0.302246f, -0.375f, 0.295898f, -0.375f,
-0.281738f, -0.375f, 0.269043f, -0.364258f, 0.249023f, -0.347656f, 0.23877f, -0.316895f,
-0.223145f, -0.269531f, 0.223145f, -0.212402f, 0.223145f, -0.107422f, 0.223633f, -0.0800781f,
-0.223633f, -0.0522461f, 0.227051f, -0.0444336f, 0.23291f, -0.03125f, 0.244385f, -0.0251465f,
-0.255859f, -0.019043f, 0.283203f, -0.0175781f, 0.283203f, 0, 0.0366211f, 0, 0.0366211f,
--0.0175781f, 0.0664062f, -0.0200195f, 0.0769043f, -0.0339355f, 0.0874023f, -0.0478516f,
-0.0874023f, -0.107422f, 0.0874023f, -0.359863f, 0.0874023f, -0.398926f, 0.0834961f,
--0.409668f, 0.0786133f, -0.42334f, 0.0693359f, -0.429688f, 0.0600586f, -0.436035f,
-0.0366211f, -0.438477f, 0.0366211f, -0.456543f, 0.322266f, -0.469238f, 0.32959f,
--0.313477f, 0.312988f, -0.313477f, 0.283203f, -0.382812f, 0.251221f, -0.408203f,
-0.219238f, -0.433594f, 0.1875f, -0.433594f, 0.16748f, -0.433594f, 0.15332f, -0.420166f,
-0.13916f, -0.406738f, 0.13916f, -0.38916f, 0.13916f, -0.375977f, 0.148926f, -0.36377f,
-0.164551f, -0.34375f, 0.236328f, -0.295166f, 0.308105f, -0.246582f, 0.330811f, -0.212646f,
-0.353516f, -0.178711f, 0.353516f, -0.136719f, 0.353516f, -0.0986328f, 0.334473f,
--0.0620117f, 0.31543f, -0.0253906f, 0.280762f, -0.00585938f, 0.246094f, 0.0136719f,
-0.204102f, 0.0136719f, 0.171387f, 0.0136719f, 0.116699f, -0.00683594f, 0.102051f,
--0.012207f, 0.0966797f, -0.012207f, 0.0805664f, -0.012207f, 0.0698242f, 0.012207f,
-0.0537109f, 0.012207f, 0.0458984f, -0.151855f, 0.0625f, -0.151855f, 0.0844727f, -0.0874023f,
-0.122803f, -0.0551758f, 0.161133f, -0.0229492f, 0.195312f, -0.0229492f, 0.21875f,
--0.0229492f, 0.233643f, -0.0373535f, 0.248535f, -0.0517578f, 0.248535f, -0.0722656f,
-0.248535f, -0.0957031f, 0.233887f, -0.112793f, 0.219238f, -0.129883f, 0.168457f,
--0.164551f, 0.09375f, -0.216309f, 0.0717773f, -0.243652f, 0.0395508f, -0.283691f,
-0.0395508f, -0.332031f, 0.0395508f, -0.384766f, 0.0759277f, -0.42749f, 0.112305f,
--0.470215f, 0.181152f, -0.470215f, 0.218262f, -0.470215f, 0.25293f, -0.452148f, 0.266113f,
--0.444824f, 0.274414f, -0.444824f, 0.283203f, -0.444824f, 0.288574f, -0.448486f,
-0.293945f, -0.452148f, 0.305664f, -0.469238f, 0.214844f, -0.623535f, 0.214844f, -0.456543f,
-0.323242f, -0.456543f, 0.323242f, -0.408203f, 0.214844f, -0.408203f, 0.214844f, -0.126465f,
-0.214844f, -0.0869141f, 0.218506f, -0.0754395f, 0.222168f, -0.0639648f, 0.231445f,
--0.0568848f, 0.240723f, -0.0498047f, 0.248535f, -0.0498047f, 0.280273f, -0.0498047f,
-0.308594f, -0.0981445f, 0.323242f, -0.0874023f, 0.283691f, 0.00634766f, 0.194824f,
-0.00634766f, 0.151367f, 0.00634766f, 0.121338f, -0.0178223f, 0.0913086f, -0.0419922f,
-0.0830078f, -0.0717773f, 0.078125f, -0.0883789f, 0.078125f, -0.161621f, 0.078125f,
--0.408203f, 0.0185547f, -0.408203f, 0.0185547f, -0.425293f, 0.0800781f, -0.46875f,
-0.123291f, -0.516602f, 0.166504f, -0.564453f, 0.19873f, -0.623535f, 0.474609f, -0.456543f,
-0.474609f, -0.0991211f, 0.474609f, -0.046875f, 0.484375f, -0.0339355f, 0.494141f,
--0.0209961f, 0.523926f, -0.0175781f, 0.523926f, 0, 0.337891f, 0, 0.337891f, -0.0610352f,
-0.305176f, -0.0219727f, 0.272461f, -0.00415039f, 0.239746f, 0.0136719f, 0.199219f,
-0.0136719f, 0.160645f, 0.0136719f, 0.130615f, -0.0100098f, 0.100586f, -0.0336914f,
-0.090332f, -0.0654297f, 0.0800781f, -0.097168f, 0.0800781f, -0.17627f, 0.0800781f,
--0.357422f, 0.0800781f, -0.40918f, 0.0705566f, -0.421875f, 0.0610352f, -0.43457f,
-0.0307617f, -0.438477f, 0.0307617f, -0.456543f, 0.216797f, -0.456543f, 0.216797f,
--0.144531f, 0.216797f, -0.0957031f, 0.221436f, -0.081543f, 0.226074f, -0.0673828f,
-0.236084f, -0.0600586f, 0.246094f, -0.0527344f, 0.259277f, -0.0527344f, 0.276855f,
--0.0527344f, 0.291016f, -0.0620117f, 0.310547f, -0.074707f, 0.337891f, -0.113281f,
-0.337891f, -0.357422f, 0.337891f, -0.40918f, 0.328369f, -0.421875f, 0.318848f, -0.43457f,
-0.288574f, -0.438477f, 0.288574f, -0.456543f, 0.239746f, 0.0136719f, 0.0859375f,
--0.340332f, 0.0581055f, -0.404297f, 0.0424805f, -0.421387f, 0.03125f, -0.434082f,
-0.00927734f, -0.438477f, 0.00927734f, -0.456543f, 0.251953f, -0.456543f, 0.251953f,
--0.438477f, 0.229004f, -0.438477f, 0.220703f, -0.430176f, 0.208984f, -0.419434f,
-0.208984f, -0.404785f, 0.208984f, -0.386719f, 0.230469f, -0.336914f, 0.305664f, -0.165527f,
-0.365723f, -0.313477f, 0.391602f, -0.376953f, 0.391602f, -0.40332f, 0.391602f, -0.418457f,
-0.380615f, -0.427979f, 0.369629f, -0.4375f, 0.341797f, -0.438477f, 0.341797f, -0.456543f,
-0.491211f, -0.456543f, 0.491211f, -0.438477f, 0.469727f, -0.435547f, 0.456055f, -0.422363f,
-0.442383f, -0.40918f, 0.415039f, -0.344727f, 0.262695f, 0.0136719f, 0.486328f, 0.0136719f,
-0.361328f, -0.321289f, 0.23877f, 0.0136719f, 0.213379f, 0.0136719f, 0.0917969f, -0.317383f,
-0.0644531f, -0.393066f, 0.0454102f, -0.416016f, 0.0332031f, -0.431641f, 0.00830078f,
--0.438477f, 0.00830078f, -0.456543f, 0.23877f, -0.456543f, 0.23877f, -0.438477f,
-0.215332f, -0.438477f, 0.206543f, -0.431641f, 0.197754f, -0.424805f, 0.197754f, -0.416016f,
-0.197754f, -0.407715f, 0.213379f, -0.366211f, 0.280273f, -0.187988f, 0.344727f, -0.366211f,
-0.339844f, -0.37793f, 0.325195f, -0.414551f, 0.314209f, -0.424561f, 0.303223f, -0.43457f,
-0.280273f, -0.438477f, 0.280273f, -0.456543f, 0.51416f, -0.456543f, 0.51416f, -0.438477f,
-0.486816f, -0.437012f, 0.479492f, -0.430908f, 0.472168f, -0.424805f, 0.472168f, -0.413574f,
-0.472168f, -0.402832f, 0.486328f, -0.366211f, 0.550781f, -0.187988f, 0.609375f, -0.352051f,
-0.62207f, -0.387207f, 0.62207f, -0.399902f, 0.62207f, -0.418945f, 0.612793f, -0.427734f,
-0.603516f, -0.436523f, 0.57666f, -0.438477f, 0.57666f, -0.456543f, 0.711914f, -0.456543f,
-0.711914f, -0.438477f, 0.689453f, -0.435547f, 0.67627f, -0.422607f, 0.663086f, -0.409668f,
-0.64209f, -0.349121f, 0.51416f, 0.0136719f, 0.303711f, -0.279785f, 0.382812f, -0.129395f,
-0.423828f, -0.0507812f, 0.447754f, -0.0297852f, 0.460938f, -0.0185547f, 0.483887f,
--0.0175781f, 0.483887f, 0, 0.229492f, 0, 0.229492f, -0.0175781f, 0.259277f, -0.0200195f,
-0.266357f, -0.0253906f, 0.273438f, -0.0307617f, 0.273438f, -0.0400391f, 0.273438f,
--0.0537109f, 0.257812f, -0.0830078f, 0.218262f, -0.157227f, 0.18457f, -0.10791f,
-0.161621f, -0.0742188f, 0.158691f, -0.0678711f, 0.154785f, -0.0585938f, 0.154785f,
--0.0512695f, 0.154785f, -0.0400391f, 0.159424f, -0.0324707f, 0.164062f, -0.0249023f,
-0.172119f, -0.0212402f, 0.180176f, -0.0175781f, 0.20166f, -0.0175781f, 0.20166f,
-0, 0.0229492f, 0, 0.0229492f, -0.0175781f, 0.0561523f, -0.0175781f, 0.0837402f, -0.0358887f,
-0.111328f, -0.0541992f, 0.164062f, -0.131836f, 0.20166f, -0.1875f, 0.123047f, -0.333008f,
-0.0844727f, -0.404297f, 0.0654297f, -0.42041f, 0.0463867f, -0.436523f, 0.0229492f,
--0.438477f, 0.0229492f, -0.456543f, 0.275879f, -0.456543f, 0.275879f, -0.438477f,
-0.262695f, -0.437988f, 0.237305f, -0.429199f, 0.233398f, -0.425781f, 0.233398f, -0.417969f,
-0.233398f, -0.410645f, 0.23584f, -0.402832f, 0.237305f, -0.399414f, 0.249512f, -0.376465f,
-0.285156f, -0.310059f, 0.303711f, -0.336426f, 0.342773f, -0.390137f, 0.342773f, -0.411621f,
-0.342773f, -0.421875f, 0.334229f, -0.428955f, 0.325684f, -0.436035f, 0.303711f, -0.438477f,
-0.303711f, -0.456543f, 0.465332f, -0.456543f, 0.465332f, -0.438477f, 0.435547f, -0.4375f,
-0.409668f, -0.420166f, 0.383789f, -0.402832f, 0.351562f, -0.353027f, 0.243164f, 0.0185547f,
-0.0957031f, -0.319824f, 0.0625f, -0.396484f, 0.0466309f, -0.414062f, 0.0307617f,
--0.431641f, 0.00830078f, -0.438477f, 0.00830078f, -0.456543f, 0.250977f, -0.456543f,
-0.250977f, -0.438477f, 0.227051f, -0.4375f, 0.217285f, -0.429199f, 0.20752f, -0.420898f,
-0.20752f, -0.40918f, 0.20752f, -0.390625f, 0.231934f, -0.335938f, 0.310059f, -0.157227f,
-0.363281f, -0.29541f, 0.39209f, -0.369141f, 0.39209f, -0.397949f, 0.39209f, -0.416016f,
-0.380127f, -0.426758f, 0.368164f, -0.4375f, 0.337891f, -0.438477f, 0.337891f, -0.456543f,
-0.490723f, -0.456543f, 0.490723f, -0.438477f, 0.468262f, -0.436035f, 0.454102f, -0.421143f,
-0.439941f, -0.40625f, 0.406738f, -0.319824f, 0.276367f, 0.0185547f, 0.227051f, 0.145508f,
-0.203125f, 0.174805f, 0.169434f, 0.21582f, 0.118652f, 0.21582f, 0.078125f, 0.21582f,
-0.0529785f, 0.192627f, 0.027832f, 0.169434f, 0.027832f, 0.136719f, 0.027832f, 0.108398f,
-0.045166f, 0.0898438f, 0.0625f, 0.0712891f, 0.0878906f, 0.0712891f, 0.112305f, 0.0712891f,
-0.127197f, 0.0869141f, 0.14209f, 0.102539f, 0.142578f, 0.135254f, 0.143066f, 0.153809f,
-0.146973f, 0.15918f, 0.150879f, 0.164551f, 0.158203f, 0.164551f, 0.169922f, 0.164551f,
-0.183105f, 0.150391f, 0.202637f, 0.129883f, 0.229004f, 0.0566406f, 0.407715f, 0,
-0.0102539f, 0, 0.0102539f, -0.0107422f, 0.26123f, -0.426758f, 0.187988f, -0.426758f,
-0.140625f, -0.426758f, 0.120117f, -0.418213f, 0.0996094f, -0.409668f, 0.0869141f,
--0.390869f, 0.0742188f, -0.37207f, 0.0605469f, -0.32373f, 0.043457f, -0.32373f, 0.043457f,
--0.456543f, 0.427734f, -0.456543f, 0.427734f, -0.443359f, 0.178711f, -0.03125f, 0.209961f,
--0.03125f, 0.303711f, -0.03125f, 0.345215f, -0.0581055f, 0.386719f, -0.0849609f,
-0.407715f, -0.15625f, 0.421387f, -0.15625f
-};
-
-const unsigned char TimesNewRomankBoldVerbs[] = {
-6, 0, 1, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1,
-1, 2, 2, 2, 2, 2, 2, 5, 0, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1, 1, 1, 5, 6,
-0, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 5, 6,
-0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1,
-1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 5, 6, 0, 1, 2,
-2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 1, 1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 1,
-1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0,
-1, 1, 1, 5, 0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1,
-1, 1, 2, 2, 2, 2, 5, 0, 1, 1, 5, 6, 0, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1,
-1, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 5, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2,
-1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2,
-2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1,
-1, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1,
-1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1,
-1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2,
-1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 1,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 5, 6, 0, 1, 2, 2,
-1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1,
-2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2,
-1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 1,
-2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
-1, 2, 2, 2, 1, 1, 1, 5, 6, 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1,
-1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2,
-2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2,
-2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 5, 0, 1, 1, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1,
-1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 5, 6, 0, 1, 2,
-2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2,
-2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2,
-2, 2, 1, 1, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1,
-1, 2, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2,
-1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2,
-2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1,
-5, 6, 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 1, 1, 1, 5, 6,
-0, 1, 1, 1, 5, 6, 0, 1, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2,
-5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 5, 0, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1,
-5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
-5, 0, 2, 2, 2, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2,
-2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1,
-5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 5, 6,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1,
-1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1,
-1, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2,
-2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1,
-1, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2,
-2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 5, 0, 1, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1,
-2, 2, 1, 2, 2, 2, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
-1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 1, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1,
-2, 2, 2, 1, 1, 1, 2, 2, 1, 5, 6, 0, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1,
-2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 1, 1,
-1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2,
-2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2,
-2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 1, 2,
-2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 5, 6
-};
-
-const unsigned TimesNewRomankBoldCharCodes[] = {
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
-43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
-63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
-83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
-103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
-119, 120, 121, 122
-};
-
-const SkFixed TimesNewRomankBoldWidths[] = {
-0x00004000, 0x00005540, 0x00008e20, 0x00008000, 0x00008000, 0x00010000, 0x0000d540,
-0x00004720, 0x00005540, 0x00005540, 0x00008000, 0x000091e0, 0x00004000, 0x00005540,
-0x00004000, 0x00004720, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000,
-0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00005540, 0x00005540,
-0x000091e0, 0x000091e0, 0x000091e0, 0x00008000, 0x0000ee20, 0x0000b8e0, 0x0000aac0,
-0x0000b8e0, 0x0000b8e0, 0x0000aac0, 0x00009c60, 0x0000c720, 0x0000c720, 0x000063a0,
-0x00008000, 0x0000c720, 0x0000aac0, 0x0000f1a0, 0x0000b8e0, 0x0000c720, 0x00009c60,
-0x0000c720, 0x0000b8e0, 0x00008e60, 0x0000aac0, 0x0000b8e0, 0x0000b8e0, 0x00010000,
-0x0000b8e0, 0x0000b8e0, 0x0000aac0, 0x00005540, 0x00004720, 0x00005540, 0x000094c0,
-0x00008000, 0x00005540, 0x00008000, 0x00008e60, 0x000071a0, 0x00008e60, 0x000071a0,
-0x00005540, 0x00008000, 0x00008e60, 0x00004720, 0x00005540, 0x00008e60, 0x00004720,
-0x0000d540, 0x00008e60, 0x00008000, 0x00008e60, 0x00008e60, 0x000071a0, 0x000063a0,
-0x00005540, 0x00008e60, 0x00008000, 0x0000b8e0, 0x00008000, 0x00008000, 0x000071a0
-};
-
-const int TimesNewRomankBoldCharCodesCount = (int) SK_ARRAY_COUNT(TimesNewRomankBoldCharCodes);
-
-const SkPaint::FontMetrics TimesNewRomankBoldMetrics = {
-0x08636967, -1.02588f, -0.891113f, 0.216309f, 0.306641f, 0.0424805f, 2.55811f, 2.57616e+24f,
--0.558105f, 2, 0.470215f, 4.25072e-38f, 0.0952148f, 0.108887f
-};
-
-const SkScalar TimesNewRomankItalicPoints[] = {
-0.515137f, -0.677246f, 0.464844f, -0.126465f, 0.460938f, -0.0878906f, 0.460938f, -0.0756836f,
-0.460938f, -0.0561523f, 0.468262f, -0.0458984f, 0.477539f, -0.0317383f, 0.493408f,
--0.0249023f, 0.509277f, -0.0180664f, 0.546875f, -0.0180664f, 0.541504f, 0, 0.280762f,
-0, 0.286133f, -0.0180664f, 0.297363f, -0.0180664f, 0.329102f, -0.0180664f, 0.349121f,
--0.0317383f, 0.363281f, -0.0410156f, 0.371094f, -0.0625f, 0.376465f, -0.0776367f,
-0.381348f, -0.133789f, 0.38916f, -0.217773f, 0.199707f, -0.217773f, 0.132324f, -0.126465f,
-0.109375f, -0.0957031f, 0.103516f, -0.0822754f, 0.0976562f, -0.0688477f, 0.0976562f,
--0.0571289f, 0.0976562f, -0.0415039f, 0.110352f, -0.0302734f, 0.123047f, -0.019043f,
-0.152344f, -0.0180664f, 0.146973f, 0, -0.0488281f, 0, -0.043457f, -0.0180664f, -0.00732422f,
--0.0195312f, 0.0202637f, -0.0422363f, 0.0478516f, -0.0649414f, 0.102539f, -0.13916f,
-0.498047f, -0.677246f, 0.418457f, -0.514648f, 0.226562f, -0.253418f, 0.393066f, -0.253418f,
-0.246582f, -0.366699f, 0.552246f, -0.366699f, 0.600586f, -0.530273f, 0.614258f, -0.578125f,
-0.614258f, -0.604492f, 0.614258f, -0.617188f, 0.608154f, -0.626221f, 0.602051f, -0.635254f,
-0.589355f, -0.639648f, 0.57666f, -0.644043f, 0.539551f, -0.644043f, 0.544434f, -0.662109f,
-0.811035f, -0.662109f, 0.805176f, -0.644043f, 0.771484f, -0.644531f, 0.754883f, -0.637207f,
-0.731445f, -0.626953f, 0.720215f, -0.61084f, 0.704102f, -0.587891f, 0.6875f, -0.530273f,
-0.570801f, -0.130371f, 0.556152f, -0.0805664f, 0.556152f, -0.059082f, 0.556152f,
--0.0405273f, 0.569092f, -0.0310059f, 0.582031f, -0.0214844f, 0.630859f, -0.0180664f,
-0.625488f, 0, 0.367676f, 0, 0.374512f, -0.0180664f, 0.412598f, -0.019043f, 0.425293f,
--0.0249023f, 0.444824f, -0.0336914f, 0.453613f, -0.0473633f, 0.466309f, -0.0664062f,
-0.484863f, -0.130371f, 0.544434f, -0.333008f, 0.237305f, -0.333008f, 0.177246f, -0.130371f,
-0.163086f, -0.081543f, 0.163086f, -0.059082f, 0.163086f, -0.0405273f, 0.175781f,
--0.0310059f, 0.188477f, -0.0214844f, 0.237305f, -0.0180664f, 0.233398f, 0, -0.0263672f,
-0, -0.0200195f, -0.0180664f, 0.0185547f, -0.019043f, 0.03125f, -0.0249023f, 0.0507812f,
--0.0336914f, 0.0600586f, -0.0473633f, 0.0727539f, -0.0673828f, 0.0913086f, -0.130371f,
-0.208496f, -0.530273f, 0.222656f, -0.579102f, 0.222656f, -0.604492f, 0.222656f, -0.617188f,
-0.216553f, -0.626221f, 0.210449f, -0.635254f, 0.19751f, -0.639648f, 0.18457f, -0.644043f,
-0.146973f, -0.644043f, 0.152832f, -0.662109f, 0.414062f, -0.662109f, 0.408691f, -0.644043f,
-0.375977f, -0.644531f, 0.360352f, -0.637207f, 0.337402f, -0.627441f, 0.32666f, -0.611328f,
-0.312012f, -0.589844f, 0.294434f, -0.530273f, 0.146484f, -0.662109f, 0.649414f, -0.662109f,
-0.595215f, -0.486328f, 0.57666f, -0.486328f, 0.585938f, -0.524902f, 0.585938f, -0.555176f,
-0.585938f, -0.59082f, 0.563965f, -0.608887f, 0.547363f, -0.622559f, 0.478516f, -0.622559f,
-0.42627f, -0.622559f, 0.29541f, -0.166504f, 0.270508f, -0.0805664f, 0.270508f, -0.0605469f,
-0.270508f, -0.0419922f, 0.286133f, -0.0300293f, 0.301758f, -0.0180664f, 0.341309f,
--0.0180664f, 0.36377f, -0.0180664f, 0.35791f, 0, 0.0698242f, 0, 0.0751953f, -0.0180664f,
-0.0878906f, -0.0180664f, 0.125977f, -0.0180664f, 0.146484f, -0.0302734f, 0.160645f,
--0.0385742f, 0.172119f, -0.0603027f, 0.183594f, -0.0820312f, 0.204102f, -0.152344f,
-0.341309f, -0.622559f, 0.301758f, -0.622559f, 0.244629f, -0.622559f, 0.209717f, -0.60791f,
-0.174805f, -0.593262f, 0.15332f, -0.56543f, 0.131836f, -0.537598f, 0.118164f, -0.486328f,
-0.100098f, -0.486328f, 0.135254f, 0.0151367f, 0.192383f, -0.536621f, 0.195801f, -0.568359f,
-0.195801f, -0.585449f, 0.195801f, -0.61377f, 0.179688f, -0.628418f, 0.163574f, -0.643066f,
-0.121582f, -0.644043f, 0.126953f, -0.662109f, 0.375f, -0.662109f, 0.369629f, -0.644043f,
-0.319824f, -0.644531f, 0.301514f, -0.626221f, 0.283203f, -0.60791f, 0.276367f, -0.536621f,
-0.239746f, -0.179199f, 0.491211f, -0.567383f, 0.491699f, -0.577148f, 0.491699f, -0.583984f,
-0.491699f, -0.611328f, 0.475586f, -0.625977f, 0.459473f, -0.640625f, 0.40625f, -0.644043f,
-0.410156f, -0.662109f, 0.678223f, -0.662109f, 0.672852f, -0.644043f, 0.626465f, -0.643555f,
-0.610352f, -0.63623f, 0.598633f, -0.630859f, 0.590576f, -0.618896f, 0.58252f, -0.606934f,
-0.577637f, -0.578125f, 0.576172f, -0.569824f, 0.565674f, -0.464844f, 0.555176f, -0.359863f,
-0.53418f, -0.179199f, 0.743652f, -0.497559f, 0.777832f, -0.549805f, 0.786621f, -0.570801f,
-0.79541f, -0.591797f, 0.79541f, -0.606445f, 0.79541f, -0.620117f, 0.783691f, -0.630615f,
-0.771973f, -0.641113f, 0.743652f, -0.644043f, 0.747559f, -0.662109f, 0.943848f, -0.662109f,
-0.938965f, -0.644043f, 0.913086f, -0.64209f, 0.893066f, -0.631348f, 0.873047f, -0.620605f,
-0.845703f, -0.590332f, 0.830078f, -0.572754f, 0.78125f, -0.497559f, 0.44873f, 0.0151367f,
-0.430664f, 0.0151367f, 0.484375f, -0.497559f, 0.151855f, 0.0151367f, 0.349609f, -0.352051f,
-0.475586f, -0.52832f, 0.524414f, -0.597168f, 0.524414f, -0.616211f, 0.524414f, -0.626953f,
-0.513916f, -0.634033f, 0.503418f, -0.641113f, 0.454102f, -0.644043f, 0.458984f, -0.662109f,
-0.666992f, -0.662109f, 0.663086f, -0.644043f, 0.632812f, -0.640137f, 0.621582f, -0.635742f,
-0.604004f, -0.628418f, 0.586914f, -0.612793f, 0.563965f, -0.592285f, 0.520508f, -0.532227f,
-0.358398f, -0.308594f, 0.30957f, -0.14502f, 0.291504f, -0.0834961f, 0.291504f, -0.0600586f,
-0.291504f, -0.0449219f, 0.297119f, -0.0371094f, 0.302734f, -0.0292969f, 0.316895f,
--0.0244141f, 0.335449f, -0.0185547f, 0.373535f, -0.0180664f, 0.368652f, 0, 0.0898438f,
-0, 0.0957031f, -0.0180664f, 0.137207f, -0.019043f, 0.150879f, -0.0249023f, 0.172852f,
--0.0336914f, 0.183594f, -0.0483398f, 0.200195f, -0.0708008f, 0.217773f, -0.128906f,
-0.275879f, -0.322266f, 0.205078f, -0.550781f, 0.186035f, -0.611328f, 0.170166f, -0.625977f,
-0.154297f, -0.640625f, 0.114746f, -0.644043f, 0.119629f, -0.662109f, 0.364258f, -0.662109f,
-0.358398f, -0.644043f, 0.3125f, -0.640625f, 0.306152f, -0.638184f, 0.29541f, -0.634766f,
-0.288574f, -0.624512f, 0.281738f, -0.614258f, 0.281738f, -0.600586f, 0.281738f, -0.580566f,
-0.295898f, -0.532227f, 0.469238f, -0.441895f, 0.374023f, -0.11084f, 0.363281f, -0.0664062f,
-0.361816f, -0.0600586f, 0.361816f, -0.0556641f, 0.361816f, -0.0478516f, 0.366699f,
--0.0419922f, 0.370605f, -0.0375977f, 0.376465f, -0.0375977f, 0.382812f, -0.0375977f,
-0.393066f, -0.0454102f, 0.412109f, -0.0595703f, 0.443848f, -0.104004f, 0.460449f,
--0.0922852f, 0.426758f, -0.0415039f, 0.391113f, -0.0148926f, 0.355469f, 0.0117188f,
-0.325195f, 0.0117188f, 0.304199f, 0.0117188f, 0.293701f, 0.0012207f, 0.283203f, -0.00927734f,
-0.283203f, -0.0292969f, 0.283203f, -0.0532227f, 0.293945f, -0.0922852f, 0.304199f,
--0.128906f, 0.240234f, -0.0454102f, 0.186523f, -0.012207f, 0.147949f, 0.0117188f,
-0.11084f, 0.0117188f, 0.0751953f, 0.0117188f, 0.0493164f, -0.0178223f, 0.0234375f,
--0.0473633f, 0.0234375f, -0.0991211f, 0.0234375f, -0.176758f, 0.0700684f, -0.262939f,
-0.116699f, -0.349121f, 0.188477f, -0.400879f, 0.244629f, -0.441895f, 0.294434f, -0.441895f,
-0.324219f, -0.441895f, 0.343994f, -0.42627f, 0.36377f, -0.410645f, 0.374023f, -0.374512f,
-0.391602f, -0.430176f, 0.29541f, -0.416504f, 0.26416f, -0.416504f, 0.229004f, -0.387207f,
-0.179199f, -0.345703f, 0.140381f, -0.26416f, 0.101562f, -0.182617f, 0.101562f, -0.116699f,
-0.101562f, -0.0834961f, 0.118164f, -0.064209f, 0.134766f, -0.0449219f, 0.15625f,
--0.0449219f, 0.209473f, -0.0449219f, 0.271973f, -0.123535f, 0.355469f, -0.228027f,
-0.355469f, -0.337891f, 0.355469f, -0.379395f, 0.339355f, -0.397949f, 0.323242f, -0.416504f,
-0.29541f, -0.416504f, 0.288574f, -0.694336f, 0.192383f, -0.356934f, 0.239258f, -0.405762f,
-0.27417f, -0.423828f, 0.309082f, -0.441895f, 0.347168f, -0.441895f, 0.400879f, -0.441895f,
-0.435059f, -0.40625f, 0.469238f, -0.370605f, 0.469238f, -0.30957f, 0.469238f, -0.230957f,
-0.424316f, -0.153076f, 0.379395f, -0.0751953f, 0.311523f, -0.0317383f, 0.243652f,
-0.0117188f, 0.177734f, 0.0117188f, 0.104004f, 0.0117188f, 0.0263672f, -0.043457f,
-0.174805f, -0.554688f, 0.191895f, -0.61377f, 0.191895f, -0.624023f, 0.191895f, -0.636719f,
-0.184082f, -0.643066f, 0.172852f, -0.651855f, 0.150879f, -0.651855f, 0.140625f, -0.651855f,
-0.119629f, -0.648438f, 0.119629f, -0.666992f, 0.0996094f, -0.0380859f, 0.148438f,
--0.0112305f, 0.185547f, -0.0112305f, 0.228516f, -0.0112305f, 0.274658f, -0.0427246f,
-0.320801f, -0.0742188f, 0.354736f, -0.148926f, 0.388672f, -0.223633f, 0.388672f,
--0.299805f, 0.388672f, -0.344727f, 0.366455f, -0.370117f, 0.344238f, -0.395508f,
-0.313965f, -0.395508f, 0.268555f, -0.395508f, 0.225098f, -0.359131f, 0.181641f, -0.322754f,
-0.163086f, -0.257812f, 0.119141f, -0.184082f, 0.115723f, -0.159668f, 0.115723f, -0.143555f,
-0.115723f, -0.100098f, 0.146484f, -0.0695801f, 0.177246f, -0.0390625f, 0.221191f,
--0.0390625f, 0.256348f, -0.0390625f, 0.288818f, -0.0534668f, 0.321289f, -0.0678711f,
-0.385254f, -0.117188f, 0.395508f, -0.103027f, 0.279785f, 0.0117188f, 0.174805f, 0.0117188f,
-0.103516f, 0.0117188f, 0.0673828f, -0.0332031f, 0.03125f, -0.078125f, 0.03125f, -0.132324f,
-0.03125f, -0.205078f, 0.0761719f, -0.28125f, 0.121094f, -0.357422f, 0.188965f, -0.399658f,
-0.256836f, -0.441895f, 0.328613f, -0.441895f, 0.380371f, -0.441895f, 0.405273f, -0.420898f,
-0.430176f, -0.399902f, 0.430176f, -0.371094f, 0.430176f, -0.330566f, 0.397949f, -0.293457f,
-0.355469f, -0.245117f, 0.272949f, -0.215332f, 0.218262f, -0.195312f, 0.119141f, -0.184082f,
-0.122559f, -0.208008f, 0.194824f, -0.216309f, 0.240234f, -0.236328f, 0.300293f, -0.263184f,
-0.330322f, -0.300537f, 0.360352f, -0.337891f, 0.360352f, -0.371582f, 0.360352f, -0.39209f,
-0.347412f, -0.404785f, 0.334473f, -0.41748f, 0.310547f, -0.41748f, 0.260742f, -0.41748f,
-0.204834f, -0.364502f, 0.148926f, -0.311523f, 0.122559f, -0.208008f, 0.296387f, -0.430176f,
-0.287598f, -0.397949f, 0.216309f, -0.397949f, 0.162598f, -0.18457f, 0.126953f, -0.043457f,
-0.0908203f, 0.0336914f, 0.0395508f, 0.142578f, -0.0195312f, 0.184082f, -0.0644531f,
-0.21582f, -0.109375f, 0.21582f, -0.138672f, 0.21582f, -0.15918f, 0.198242f, -0.174316f,
-0.186035f, -0.174316f, 0.166504f, -0.174316f, 0.150879f, -0.161865f, 0.139404f, -0.149414f,
-0.12793f, -0.131348f, 0.12793f, -0.118164f, 0.12793f, -0.109131f, 0.13623f, -0.100098f,
-0.144531f, -0.100098f, 0.155273f, -0.100098f, 0.166016f, -0.110352f, 0.175293f, -0.118164f,
-0.182129f, -0.118164f, 0.185547f, -0.118164f, 0.189941f, -0.114746f, 0.192383f, -0.110352f,
-0.195801f, -0.101074f, 0.195801f, -0.0800781f, 0.195801f, -0.0568848f, 0.182617f,
--0.0336914f, 0.169434f, -0.015625f, 0.143311f, 0.00244141f, 0.117188f, 0.0185547f,
-0.0678711f, 0.0253906f, 0.0473633f, 0.0551758f, -0.0673828f, 0.140137f, -0.397949f,
-0.0551758f, -0.397949f, 0.0620117f, -0.430176f, 0.102539f, -0.430176f, 0.118652f,
--0.435791f, 0.134766f, -0.441406f, 0.148193f, -0.457275f, 0.161621f, -0.473145f,
-0.183105f, -0.516602f, 0.211914f, -0.575195f, 0.238281f, -0.607422f, 0.274414f, -0.650879f,
-0.314209f, -0.672607f, 0.354004f, -0.694336f, 0.38916f, -0.694336f, 0.42627f, -0.694336f,
-0.44873f, -0.675537f, 0.471191f, -0.656738f, 0.471191f, -0.634766f, 0.471191f, -0.617676f,
-0.459961f, -0.605957f, 0.44873f, -0.594238f, 0.431152f, -0.594238f, 0.416016f, -0.594238f,
-0.406494f, -0.603027f, 0.396973f, -0.611816f, 0.396973f, -0.624023f, 0.396973f, -0.631836f,
-0.40332f, -0.643311f, 0.409668f, -0.654785f, 0.409668f, -0.658691f, 0.409668f, -0.665527f,
-0.405273f, -0.668945f, 0.398926f, -0.673828f, 0.386719f, -0.673828f, 0.355957f, -0.673828f,
-0.331543f, -0.654297f, 0.298828f, -0.628418f, 0.272949f, -0.573242f, 0.259766f, -0.544434f,
-0.224609f, -0.430176f, 0.520996f, -0.411621f, 0.506836f, -0.36084f, 0.425293f, -0.36084f,
-0.43457f, -0.334473f, 0.43457f, -0.311523f, 0.43457f, -0.24707f, 0.379883f, -0.196777f,
-0.324707f, -0.146484f, 0.228516f, -0.141113f, 0.176758f, -0.125488f, 0.150879f, -0.104004f,
-0.141113f, -0.0961914f, 0.141113f, -0.0878906f, 0.141113f, -0.078125f, 0.149902f,
--0.0700684f, 0.158691f, -0.0620117f, 0.194336f, -0.0537109f, 0.289062f, -0.0317383f,
-0.367676f, -0.0131836f, 0.393066f, 0.012207f, 0.417969f, 0.0380859f, 0.417969f, 0.0717773f,
-0.417969f, 0.111816f, 0.388428f, 0.14502f, 0.358887f, 0.178223f, 0.302002f, 0.197021f,
-0.245117f, 0.21582f, 0.17627f, 0.21582f, 0.115723f, 0.21582f, 0.065918f, 0.201416f,
-0.0161133f, 0.187012f, -0.00537109f, 0.162598f, -0.0268555f, 0.138184f, -0.0268555f,
-0.112305f, -0.0268555f, 0.0913086f, -0.0129395f, 0.0686035f, 0.000976562f, 0.0458984f,
-0.0219727f, 0.03125f, 0.0351562f, 0.0219727f, 0.0966797f, -0.0126953f, 0.0742188f,
--0.0302734f, 0.0742188f, -0.0512695f, 0.0742188f, -0.0708008f, 0.0939941f, -0.0927734f,
-0.11377f, -0.114746f, 0.177734f, -0.141113f, 0.124023f, -0.151367f, 0.0925293f, -0.186035f,
-0.0610352f, -0.220703f, 0.0610352f, -0.263184f, 0.0610352f, -0.33252f, 0.121826f,
--0.387207f, 0.182617f, -0.441895f, 0.283691f, -0.441895f, 0.320312f, -0.441895f,
-0.34375f, -0.43457f, 0.367188f, -0.427246f, 0.38916f, -0.411621f, 0.351562f, -0.334961f,
-0.351562f, -0.374023f, 0.329834f, -0.396484f, 0.308105f, -0.418945f, 0.272949f, -0.418945f,
-0.217773f, -0.418945f, 0.181885f, -0.363525f, 0.145996f, -0.308105f, 0.145996f, -0.248047f,
-0.145996f, -0.210449f, 0.168945f, -0.186523f, 0.191895f, -0.162598f, 0.224609f, -0.162598f,
-0.250488f, -0.162598f, 0.274658f, -0.176758f, 0.298828f, -0.190918f, 0.31543f, -0.21582f,
-0.332031f, -0.240723f, 0.341797f, -0.279297f, 0.351562f, -0.317871f, 0.351562f, -0.334961f,
-0.117676f, 0, 0.078125f, 0.0180664f, 0.0578613f, 0.0463867f, 0.0375977f, 0.074707f,
-0.0375977f, 0.102051f, 0.0375977f, 0.134277f, 0.0668945f, 0.155273f, 0.108887f, 0.185547f,
-0.189941f, 0.185547f, 0.259766f, 0.185547f, 0.309326f, 0.161865f, 0.358887f, 0.138184f,
-0.358887f, 0.100586f, 0.358887f, 0.081543f, 0.340576f, 0.0644531f, 0.322266f, 0.0473633f,
-0.269531f, 0.0366211f, 0.240723f, 0.0307617f, 0.117676f, 0, 0.216797f, -0.441895f,
-0.15332f, -0.22168f, 0.195801f, -0.299316f, 0.225586f, -0.338379f, 0.271973f, -0.398926f,
-0.315918f, -0.42627f, 0.341797f, -0.441895f, 0.370117f, -0.441895f, 0.394531f, -0.441895f,
-0.410645f, -0.42627f, 0.426758f, -0.410645f, 0.426758f, -0.38623f, 0.426758f, -0.362305f,
-0.415527f, -0.32373f, 0.380859f, -0.199707f, 0.460449f, -0.348633f, 0.531738f, -0.408691f,
-0.571289f, -0.441895f, 0.609863f, -0.441895f, 0.632324f, -0.441895f, 0.646729f, -0.426514f,
-0.661133f, -0.411133f, 0.661133f, -0.378906f, 0.661133f, -0.350586f, 0.652344f, -0.318848f,
-0.598633f, -0.128906f, 0.581055f, -0.0668945f, 0.581055f, -0.0600586f, 0.581055f,
--0.0532227f, 0.585449f, -0.0483398f, 0.588379f, -0.0449219f, 0.593262f, -0.0449219f,
-0.598145f, -0.0449219f, 0.610352f, -0.0541992f, 0.638184f, -0.0756836f, 0.662598f,
--0.11084f, 0.678711f, -0.100586f, 0.666504f, -0.0810547f, 0.635498f, -0.046875f,
-0.604492f, -0.0126953f, 0.58252f, -0.000488281f, 0.560547f, 0.0117188f, 0.541992f,
-0.0117188f, 0.524902f, 0.0117188f, 0.513428f, 0, 0.501953f, -0.0117188f, 0.501953f,
--0.0288086f, 0.501953f, -0.0522461f, 0.521973f, -0.123047f, 0.566406f, -0.279785f,
-0.581543f, -0.333984f, 0.58252f, -0.339844f, 0.583984f, -0.349121f, 0.583984f, -0.35791f,
-0.583984f, -0.370117f, 0.578613f, -0.376953f, 0.572754f, -0.383789f, 0.56543f, -0.383789f,
-0.544922f, -0.383789f, 0.521973f, -0.362793f, 0.45459f, -0.300781f, 0.395996f, -0.188965f,
-0.357422f, -0.115234f, 0.32373f, 0, 0.25f, 0, 0.333496f, -0.29541f, 0.347168f, -0.343262f,
-0.347168f, -0.359375f, 0.347168f, -0.372559f, 0.341797f, -0.378906f, 0.336426f, -0.385254f,
-0.328613f, -0.385254f, 0.3125f, -0.385254f, 0.294434f, -0.373535f, 0.265137f, -0.354492f,
-0.218994f, -0.291992f, 0.172852f, -0.229492f, 0.147461f, -0.172363f, 0.135254f, -0.145508f,
-0.0893555f, 0, 0.0170898f, 0, 0.107422f, -0.316406f, 0.119141f, -0.357422f, 0.122559f,
--0.366699f, 0.122559f, -0.371094f, 0.122559f, -0.381836f, 0.112793f, -0.390381f,
-0.103027f, -0.398926f, 0.0878906f, -0.398926f, 0.081543f, -0.398926f, 0.0527344f,
--0.393066f, 0.0483398f, -0.411133f, 0.220703f, -0.441895f, 0.155762f, -0.219727f,
-0.24707f, -0.355957f, 0.295654f, -0.398926f, 0.344238f, -0.441895f, 0.38916f, -0.441895f,
-0.413574f, -0.441895f, 0.429443f, -0.425781f, 0.445312f, -0.409668f, 0.445312f, -0.383789f,
-0.445312f, -0.354492f, 0.431152f, -0.305664f, 0.371582f, -0.100098f, 0.361328f, -0.0644531f,
-0.361328f, -0.0566406f, 0.361328f, -0.0498047f, 0.365234f, -0.045166f, 0.369141f,
--0.0405273f, 0.373535f, -0.0405273f, 0.379395f, -0.0405273f, 0.387695f, -0.046875f,
-0.413574f, -0.0673828f, 0.444336f, -0.109375f, 0.459473f, -0.100098f, 0.414062f,
--0.0351562f, 0.373535f, -0.00732422f, 0.345215f, 0.0117188f, 0.322754f, 0.0117188f,
-0.304688f, 0.0117188f, 0.293945f, 0.000732422f, 0.283203f, -0.0102539f, 0.283203f,
--0.0288086f, 0.283203f, -0.0522461f, 0.299805f, -0.109375f, 0.356445f, -0.305664f,
-0.367188f, -0.342285f, 0.367188f, -0.362793f, 0.367188f, -0.372559f, 0.36084f, -0.378662f,
-0.354492f, -0.384766f, 0.345215f, -0.384766f, 0.331543f, -0.384766f, 0.3125f, -0.373047f,
-0.276367f, -0.351074f, 0.237305f, -0.300537f, 0.198242f, -0.25f, 0.154785f, -0.171387f,
-0.131836f, -0.129883f, 0.116699f, -0.0805664f, 0.0922852f, 0, 0.019043f, 0, 0.10791f,
--0.305664f, 0.123535f, -0.36084f, 0.123535f, -0.37207f, 0.123535f, -0.382812f, 0.11499f,
--0.390869f, 0.106445f, -0.398926f, 0.09375f, -0.398926f, 0.0878906f, -0.398926f,
-0.0732422f, -0.396973f, 0.0546875f, -0.394043f, 0.0517578f, -0.411621f, 0.462402f,
--0.289062f, 0.462402f, -0.21582f, 0.423584f, -0.144043f, 0.384766f, -0.0722656f,
-0.31543f, -0.0302734f, 0.246094f, 0.0117188f, 0.180664f, 0.0117188f, 0.11377f, 0.0117188f,
-0.0715332f, -0.0310059f, 0.0292969f, -0.0737305f, 0.0292969f, -0.141602f, 0.0292969f,
--0.213379f, 0.0705566f, -0.285645f, 0.111816f, -0.35791f, 0.180908f, -0.399902f,
-0.25f, -0.441895f, 0.314453f, -0.441895f, 0.378906f, -0.441895f, 0.420654f, -0.399414f,
-0.462402f, -0.356934f, 0.462402f, -0.289062f, 0.381348f, -0.322754f, 0.381348f, -0.368164f,
-0.359131f, -0.392334f, 0.336914f, -0.416504f, 0.301758f, -0.416504f, 0.22998f, -0.416504f,
-0.169678f, -0.313721f, 0.109375f, -0.210938f, 0.109375f, -0.109375f, 0.109375f, -0.0629883f,
-0.132812f, -0.0378418f, 0.15625f, -0.0126953f, 0.191895f, -0.0126953f, 0.260742f,
--0.0126953f, 0.321045f, -0.11499f, 0.381348f, -0.217285f, 0.381348f, -0.322754f,
-0.221191f, -0.441895f, 0.1875f, -0.32959f, 0.240723f, -0.39209f, 0.282471f, -0.416992f,
-0.324219f, -0.441895f, 0.367676f, -0.441895f, 0.411133f, -0.441895f, 0.441895f, -0.407471f,
-0.472656f, -0.373047f, 0.472656f, -0.317871f, 0.472656f, -0.210449f, 0.385254f, -0.0993652f,
-0.297852f, 0.0117188f, 0.181641f, 0.0117188f, 0.157227f, 0.0117188f, 0.138428f, 0.00634766f,
-0.119629f, 0.000976562f, 0.0961914f, -0.0126953f, 0.0605469f, 0.113281f, 0.0498047f,
-0.150391f, 0.0498047f, 0.161621f, 0.0498047f, 0.172363f, 0.0554199f, 0.179932f, 0.0610352f,
-0.1875f, 0.0737305f, 0.19165f, 0.0864258f, 0.195801f, 0.124023f, 0.195801f, 0.119629f,
-0.213867f, -0.110352f, 0.213867f, -0.105469f, 0.195801f, -0.0600586f, 0.193848f,
--0.0441895f, 0.180176f, -0.0283203f, 0.166504f, -0.0107422f, 0.104492f, 0.112793f,
--0.323242f, 0.124023f, -0.36377f, 0.124023f, -0.373535f, 0.124023f, -0.386719f, 0.116455f,
--0.394043f, 0.108887f, -0.401367f, 0.0932617f, -0.401367f, 0.0791016f, -0.401367f,
-0.0537109f, -0.397949f, 0.0537109f, -0.416992f, 0.107422f, -0.0512695f, 0.137695f,
--0.0151367f, 0.188965f, -0.0151367f, 0.214355f, -0.0151367f, 0.240723f, -0.0292969f,
-0.26709f, -0.043457f, 0.292236f, -0.0712891f, 0.317383f, -0.0991211f, 0.337402f,
--0.135498f, 0.357422f, -0.171875f, 0.373291f, -0.221191f, 0.38916f, -0.270508f, 0.38916f,
--0.318848f, 0.38916f, -0.35791f, 0.371338f, -0.378662f, 0.353516f, -0.399414f, 0.32959f,
--0.399414f, 0.276855f, -0.399414f, 0.225342f, -0.338867f, 0.173828f, -0.27832f, 0.149902f,
--0.197266f, 0.0522461f, -0.414551f, 0.220703f, -0.441895f, 0.150391f, -0.20459f,
-0.23584f, -0.350586f, 0.305664f, -0.408691f, 0.345215f, -0.441895f, 0.370117f, -0.441895f,
-0.38623f, -0.441895f, 0.395508f, -0.432373f, 0.404785f, -0.422852f, 0.404785f, -0.404785f,
-0.404785f, -0.372559f, 0.388184f, -0.343262f, 0.376465f, -0.321289f, 0.354492f, -0.321289f,
-0.343262f, -0.321289f, 0.335205f, -0.328613f, 0.327148f, -0.335938f, 0.325195f, -0.351074f,
-0.324219f, -0.360352f, 0.320801f, -0.363281f, 0.316895f, -0.367188f, 0.311523f, -0.367188f,
-0.303223f, -0.367188f, 0.295898f, -0.363281f, 0.283203f, -0.356445f, 0.257324f, -0.325195f,
-0.216797f, -0.277344f, 0.169434f, -0.201172f, 0.148926f, -0.168945f, 0.134277f, -0.128418f,
-0.11377f, -0.0727539f, 0.11084f, -0.0615234f, 0.0952148f, 0, 0.0205078f, 0, 0.11084f,
--0.303223f, 0.126465f, -0.355957f, 0.126465f, -0.378418f, 0.126465f, -0.387207f,
-0.119141f, -0.393066f, 0.109375f, -0.400879f, 0.0932617f, -0.400879f, 0.0830078f,
--0.400879f, 0.0556641f, -0.396484f, 0.362793f, -0.441895f, 0.333008f, -0.291992f,
-0.314941f, -0.291992f, 0.3125f, -0.357422f, 0.287109f, -0.387207f, 0.261719f, -0.416992f,
-0.224121f, -0.416992f, 0.193848f, -0.416992f, 0.176025f, -0.400391f, 0.158203f, -0.383789f,
-0.158203f, -0.360352f, 0.158203f, -0.344238f, 0.165283f, -0.32959f, 0.172363f, -0.314941f,
-0.196289f, -0.288574f, 0.259766f, -0.219238f, 0.27832f, -0.184082f, 0.296875f, -0.148926f,
-0.296875f, -0.117676f, 0.296875f, -0.0668945f, 0.254639f, -0.0275879f, 0.212402f,
-0.0117188f, 0.147949f, 0.0117188f, 0.112793f, 0.0117188f, 0.0668945f, -0.00488281f,
-0.0507812f, -0.0107422f, 0.0419922f, -0.0107422f, 0.0200195f, -0.0107422f, 0.00878906f,
-0.0117188f, -0.00927734f, 0.0117188f, 0.0205078f, -0.146484f, 0.0385742f, -0.146484f,
-0.0415039f, -0.0722656f, 0.0693359f, -0.0415039f, 0.097168f, -0.0107422f, 0.145508f,
--0.0107422f, 0.182617f, -0.0107422f, 0.204346f, -0.0314941f, 0.226074f, -0.0522461f,
-0.226074f, -0.0825195f, 0.226074f, -0.102051f, 0.218262f, -0.118652f, 0.20459f, -0.147949f,
-0.160889f, -0.199707f, 0.117188f, -0.251465f, 0.104736f, -0.277344f, 0.0922852f,
--0.303223f, 0.0922852f, -0.329102f, 0.0922852f, -0.376465f, 0.126709f, -0.40918f,
-0.161133f, -0.441895f, 0.215332f, -0.441895f, 0.230957f, -0.441895f, 0.243652f, -0.439453f,
-0.250488f, -0.437988f, 0.275635f, -0.428467f, 0.300781f, -0.418945f, 0.309082f, -0.418945f,
-0.330078f, -0.418945f, 0.344238f, -0.441895f, 0.470703f, -0.430176f, 0.385742f, -0.13916f,
-0.366699f, -0.0742188f, 0.366699f, -0.0571289f, 0.366699f, -0.0483398f, 0.369873f,
--0.0441895f, 0.373047f, -0.0400391f, 0.378418f, -0.0400391f, 0.386719f, -0.0400391f,
-0.396729f, -0.0476074f, 0.406738f, -0.0551758f, 0.447266f, -0.10791f, 0.461914f,
--0.0966797f, 0.42334f, -0.0356445f, 0.382812f, -0.00683594f, 0.355957f, 0.0117188f,
-0.331055f, 0.0117188f, 0.312012f, 0.0117188f, 0.30127f, 0.000976562f, 0.290527f,
--0.00976562f, 0.290527f, -0.0268555f, 0.290527f, -0.043457f, 0.296875f, -0.0708008f,
-0.304688f, -0.106934f, 0.341309f, -0.228027f, 0.258301f, -0.0917969f, 0.202393f,
--0.0400391f, 0.146484f, 0.0117188f, 0.0986328f, 0.0117188f, 0.0761719f, 0.0117188f,
-0.0605469f, -0.00390625f, 0.0449219f, -0.0195312f, 0.0449219f, -0.043457f, 0.0449219f,
--0.0800781f, 0.0664062f, -0.155762f, 0.108887f, -0.306641f, 0.124512f, -0.36084f,
-0.124512f, -0.374023f, 0.124512f, -0.379883f, 0.120361f, -0.384033f, 0.116211f, -0.388184f,
-0.111328f, -0.388184f, 0.101074f, -0.388184f, 0.0908203f, -0.380859f, 0.0805664f,
--0.373535f, 0.0444336f, -0.32666f, 0.0292969f, -0.337402f, 0.065918f, -0.394043f,
-0.106934f, -0.420898f, 0.138184f, -0.441895f, 0.164551f, -0.441895f, 0.182617f, -0.441895f,
-0.194092f, -0.43042f, 0.205566f, -0.418945f, 0.205566f, -0.400879f, 0.205566f, -0.374512f,
-0.186035f, -0.306641f, 0.140137f, -0.148926f, 0.121094f, -0.0844727f, 0.121094f,
--0.0673828f, 0.121094f, -0.0581055f, 0.127197f, -0.0524902f, 0.133301f, -0.046875f,
-0.143555f, -0.046875f, 0.159668f, -0.046875f, 0.185547f, -0.0629883f, 0.211426f,
--0.0791016f, 0.254639f, -0.134521f, 0.297852f, -0.189941f, 0.325928f, -0.238525f,
-0.354004f, -0.287109f, 0.385742f, -0.393066f, 0.396484f, -0.430176f, 0.159668f, -0.441895f,
-0.17627f, -0.413574f, 0.182617f, -0.388916f, 0.188965f, -0.364258f, 0.195312f, -0.291992f,
-0.216797f, -0.0517578f, 0.246094f, -0.0869141f, 0.301758f, -0.163086f, 0.328613f,
--0.200195f, 0.368164f, -0.26416f, 0.39209f, -0.303223f, 0.397461f, -0.318848f, 0.400391f,
--0.32666f, 0.400391f, -0.334961f, 0.400391f, -0.340332f, 0.396973f, -0.34375f, 0.393555f,
--0.347168f, 0.37915f, -0.351807f, 0.364746f, -0.356445f, 0.355225f, -0.368896f, 0.345703f,
--0.381348f, 0.345703f, -0.397461f, 0.345703f, -0.41748f, 0.357422f, -0.429688f, 0.369141f,
--0.441895f, 0.386719f, -0.441895f, 0.408203f, -0.441895f, 0.42334f, -0.424072f, 0.438477f,
--0.40625f, 0.438477f, -0.375f, 0.438477f, -0.336426f, 0.412109f, -0.286865f, 0.385742f,
--0.237305f, 0.310547f, -0.134766f, 0.235352f, -0.0322266f, 0.128418f, 0.0888672f,
-0.0546875f, 0.172363f, 0.019043f, 0.194092f, -0.0166016f, 0.21582f, -0.0419922f,
-0.21582f, -0.0571289f, 0.21582f, -0.0686035f, 0.204346f, -0.0800781f, 0.192871f,
--0.0800781f, 0.177734f, -0.0800781f, 0.158691f, -0.064209f, 0.143066f, -0.0483398f,
-0.127441f, -0.0297852f, 0.127441f, -0.0200195f, 0.127441f, -0.0136719f, 0.131836f,
--0.00976562f, 0.134277f, -0.00512695f, 0.145752f, -0.000488281f, 0.157227f, 0.00341797f,
-0.161133f, 0.00585938f, 0.163574f, 0.00927734f, 0.163574f, 0.012207f, 0.163574f,
-0.0195312f, 0.158691f, 0.0463867f, 0.14209f, 0.0820312f, 0.105957f, 0.128906f, 0.0581055f,
-0.151367f, 0.027832f, 0.124023f, -0.281738f, 0.117188f, -0.358398f, 0.103516f, -0.375f,
-0.0898438f, -0.391602f, 0.0576172f, -0.391602f, 0.0473633f, -0.391602f, 0.0209961f,
--0.388672f, 0.0166016f, -0.406738f
-};
-
-const unsigned char TimesNewRomankItalicVerbs[] = {
-6, 0, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1,
-5, 0, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 5, 6,
-0, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 5,
-6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1,
-2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2,
-2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 0, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 5, 0, 2, 2,
-2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-0, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
-6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2,
-1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0,
-2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1,
-1, 2, 2, 1, 2, 2, 2, 2, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 5, 6, 0, 1, 1, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
-2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 5, 6, 0, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
-2, 1, 5, 6
-};
-
-const unsigned TimesNewRomankItalicCharCodes[] = {
-32, 65, 72, 84, 87, 89, 97, 98, 101, 102, 103, 109, 110, 111, 112, 114,
-115, 117, 121
-};
-
-const SkFixed TimesNewRomankItalicWidths[] = {
-0x00004000, 0x00009c60, 0x0000b8e0, 0x00008e60, 0x0000d540, 0x00008e60, 0x00008000,
-0x00008000, 0x000071a0, 0x00004720, 0x00008000, 0x0000b8e0, 0x00008000, 0x00008000,
-0x00008000, 0x000063a0, 0x000063a0, 0x00008000, 0x000071a0
-};
-
-const int TimesNewRomankItalicCharCodesCount = (int) SK_ARRAY_COUNT(TimesNewRomankItalicCharCodes);
-
-const SkPaint::FontMetrics TimesNewRomankItalicMetrics = {
-0x00000003, -1.02344f, -0.891113f, 0.216309f, 0.306641f, 0.0424805f, 1.8501f, 0, -0.497559f,
-1.35254f, 0.453613f, 0, 0.0488281f, 0.108887f
-};
-
-const SkScalar TimesNewRomankBoldItalicPoints[] = {
-0.405273f, -0.213379f, 0.200195f, -0.213379f, 0.15918f, -0.162598f, 0.112305f, -0.106445f,
-0.0986328f, -0.0883789f, 0.0922852f, -0.0737305f, 0.0874023f, -0.0625f, 0.0874023f,
--0.0512695f, 0.0874023f, -0.0395508f, 0.0998535f, -0.029541f, 0.112305f, -0.0195312f,
-0.141113f, -0.0180664f, 0.141113f, 0, -0.0566406f, 0, -0.0517578f, -0.0180664f, -0.0253906f,
--0.0224609f, -0.00488281f, -0.0366211f, 0.0224609f, -0.0561523f, 0.0737305f, -0.117188f,
-0.542969f, -0.677246f, 0.564941f, -0.677246f, 0.542969f, -0.135254f, 0.541504f, -0.0927734f,
-0.541504f, -0.0839844f, 0.541504f, -0.0507812f, 0.554932f, -0.0356445f, 0.568359f,
--0.0205078f, 0.599609f, -0.0180664f, 0.594727f, 0, 0.308105f, 0, 0.313477f, -0.0180664f,
-0.355957f, -0.0219727f, 0.362305f, -0.0249023f, 0.375977f, -0.0317383f, 0.387207f,
--0.0534668f, 0.398438f, -0.0751953f, 0.400879f, -0.128906f, 0.405273f, -0.253418f,
-0.417969f, -0.469238f, 0.233887f, -0.253418f, 0.297363f, -0.357422f, 0.539551f, -0.357422f,
-0.593262f, -0.54248f, 0.604004f, -0.580566f, 0.604004f, -0.600586f, 0.604004f, -0.620117f,
-0.59082f, -0.630371f, 0.577637f, -0.640625f, 0.527344f, -0.644043f, 0.532715f, -0.662109f,
-0.861816f, -0.662109f, 0.856445f, -0.644043f, 0.808105f, -0.644043f, 0.783203f, -0.623535f,
-0.758301f, -0.603027f, 0.740723f, -0.54248f, 0.617676f, -0.118652f, 0.605469f, -0.0771484f,
-0.605469f, -0.059082f, 0.605469f, -0.0410156f, 0.618652f, -0.0317383f, 0.635742f,
--0.019043f, 0.680664f, -0.0180664f, 0.675781f, 0, 0.353027f, 0, 0.360352f, -0.0180664f,
-0.407227f, -0.0180664f, 0.429443f, -0.036377f, 0.45166f, -0.0546875f, 0.470215f,
--0.118652f, 0.527344f, -0.315918f, 0.286133f, -0.315918f, 0.229492f, -0.118652f,
-0.217285f, -0.078125f, 0.217285f, -0.0585938f, 0.217285f, -0.0410156f, 0.232178f,
--0.0300293f, 0.24707f, -0.019043f, 0.291016f, -0.0180664f, 0.286133f, 0, -0.0322266f,
-0, -0.0268555f, -0.0180664f, 0.0200195f, -0.0180664f, 0.041748f, -0.036377f, 0.0634766f,
--0.0546875f, 0.0820312f, -0.118652f, 0.205078f, -0.54248f, 0.21582f, -0.579102f,
-0.21582f, -0.600098f, 0.21582f, -0.620117f, 0.202881f, -0.630371f, 0.189941f, -0.640625f,
-0.141113f, -0.644043f, 0.146484f, -0.662109f, 0.470215f, -0.662109f, 0.462891f, -0.644043f,
-0.417969f, -0.644043f, 0.39502f, -0.624756f, 0.37207f, -0.605469f, 0.353027f, -0.54248f,
-0.160156f, -0.662109f, 0.692871f, -0.662109f, 0.642578f, -0.483887f, 0.625f, -0.483887f,
-0.625977f, -0.498047f, 0.625977f, -0.508789f, 0.625977f, -0.55957f, 0.596191f, -0.587646f,
-0.566406f, -0.615723f, 0.495605f, -0.619629f, 0.348145f, -0.121094f, 0.335938f, -0.0795898f,
-0.335938f, -0.0595703f, 0.335938f, -0.0410156f, 0.351074f, -0.0300293f, 0.366211f,
--0.019043f, 0.412598f, -0.0180664f, 0.408203f, 0, 0.0795898f, 0, 0.0854492f, -0.0180664f,
-0.135742f, -0.0180664f, 0.158691f, -0.0368652f, 0.181641f, -0.0556641f, 0.200684f,
--0.121094f, 0.348145f, -0.619629f, 0.271973f, -0.617188f, 0.220703f, -0.586426f,
-0.169434f, -0.555664f, 0.126953f, -0.483887f, 0.10791f, -0.483887f, 0.130371f, 0.0151367f,
-0.175293f, -0.55127f, 0.177246f, -0.576172f, 0.177246f, -0.592285f, 0.177246f, -0.618164f,
-0.165283f, -0.630371f, 0.15332f, -0.642578f, 0.123047f, -0.644043f, 0.130371f, -0.662109f,
-0.397949f, -0.662109f, 0.392578f, -0.644043f, 0.379395f, -0.644043f, 0.353027f, -0.644043f,
-0.33667f, -0.626709f, 0.320312f, -0.609375f, 0.316895f, -0.562012f, 0.291016f, -0.226074f,
-0.490723f, -0.499023f, 0.495605f, -0.562012f, 0.497559f, -0.581543f, 0.497559f, -0.593262f,
-0.497559f, -0.617188f, 0.484619f, -0.629883f, 0.47168f, -0.642578f, 0.441895f, -0.644043f,
-0.446777f, -0.662109f, 0.716309f, -0.662109f, 0.710938f, -0.644043f, 0.675293f, -0.644043f,
-0.658203f, -0.626709f, 0.641113f, -0.609375f, 0.637207f, -0.562012f, 0.611816f, -0.226074f,
-0.804199f, -0.490723f, 0.853516f, -0.558594f, 0.865234f, -0.583008f, 0.873535f, -0.599609f,
-0.873535f, -0.611328f, 0.873535f, -0.622559f, 0.862549f, -0.631592f, 0.851562f, -0.640625f,
-0.820312f, -0.644043f, 0.825195f, -0.662109f, 1.00195f, -0.662109f, 0.997559f, -0.644043f,
-0.973633f, -0.639648f, 0.958008f, -0.627441f, 0.936035f, -0.610352f, 0.900879f, -0.562012f,
-0.480469f, 0.0151367f, 0.45166f, 0.0151367f, 0.485352f, -0.431641f, 0.159668f, 0.0151367f,
-0.264648f, -0.29248f, 0.208984f, -0.533691f, 0.194824f, -0.596191f, 0.174805f, -0.619141f,
-0.159668f, -0.636719f, 0.119629f, -0.644043f, 0.125f, -0.662109f, 0.442871f, -0.662109f,
-0.437012f, -0.644043f, 0.390625f, -0.644043f, 0.369385f, -0.625244f, 0.348145f, -0.606445f,
-0.348145f, -0.580566f, 0.348145f, -0.564453f, 0.356934f, -0.524414f, 0.399902f, -0.328613f,
-0.506836f, -0.476074f, 0.547852f, -0.532715f, 0.558105f, -0.555908f, 0.568359f, -0.579102f,
-0.568359f, -0.59668f, 0.568359f, -0.614258f, 0.555176f, -0.627441f, 0.541992f, -0.640625f,
-0.512695f, -0.644043f, 0.518066f, -0.662109f, 0.716797f, -0.662109f, 0.716797f, -0.644043f,
-0.689941f, -0.641113f, 0.67041f, -0.626465f, 0.650879f, -0.611816f, 0.594238f, -0.533691f,
-0.40625f, -0.274902f, 0.362305f, -0.121582f, 0.348145f, -0.0742188f, 0.348145f, -0.0664062f,
-0.348145f, -0.0454102f, 0.364258f, -0.0317383f, 0.380371f, -0.0180664f, 0.418457f,
--0.0180664f, 0.437012f, -0.0180664f, 0.431641f, 0, 0.0927734f, 0, 0.0976562f, -0.0180664f,
-0.134766f, -0.0175781f, 0.157227f, -0.0280762f, 0.179688f, -0.0385742f, 0.190918f,
--0.0551758f, 0.19873f, -0.0668945f, 0.213867f, -0.117676f, 0.479004f, -0.445801f,
-0.384277f, -0.121094f, 0.374512f, -0.081543f, 0.373047f, -0.0742188f, 0.373047f,
--0.0708008f, 0.373047f, -0.0649414f, 0.377197f, -0.0605469f, 0.381348f, -0.0561523f,
-0.385742f, -0.0561523f, 0.395996f, -0.0561523f, 0.414062f, -0.0717773f, 0.421387f,
--0.078125f, 0.449219f, -0.116699f, 0.466309f, -0.10791f, 0.431641f, -0.0444336f,
-0.392334f, -0.0153809f, 0.353027f, 0.0136719f, 0.307617f, 0.0136719f, 0.279785f,
-0.0136719f, 0.265137f, -0.000732422f, 0.250488f, -0.0151367f, 0.250488f, -0.0371094f,
-0.250488f, -0.0561523f, 0.266113f, -0.10791f, 0.277832f, -0.147461f, 0.221191f, -0.050293f,
-0.168945f, -0.00976562f, 0.138672f, 0.0136719f, 0.104492f, 0.0136719f, 0.0595703f,
-0.0136719f, 0.0395508f, -0.0231934f, 0.0195312f, -0.0600586f, 0.0195312f, -0.106445f,
-0.0195312f, -0.175293f, 0.0615234f, -0.264404f, 0.103516f, -0.353516f, 0.171875f,
--0.407715f, 0.228027f, -0.452637f, 0.277344f, -0.452637f, 0.304688f, -0.452637f,
-0.321289f, -0.436768f, 0.337891f, -0.420898f, 0.345703f, -0.378906f, 0.363281f, -0.438965f,
-0.322754f, -0.353027f, 0.322754f, -0.392578f, 0.310547f, -0.410156f, 0.301758f, -0.422363f,
-0.286621f, -0.422363f, 0.271484f, -0.422363f, 0.255371f, -0.407715f, 0.222656f, -0.377441f,
-0.184814f, -0.284912f, 0.146973f, -0.192383f, 0.146973f, -0.125f, 0.146973f, -0.0991211f,
-0.155518f, -0.0876465f, 0.164062f, -0.0761719f, 0.174316f, -0.0761719f, 0.196289f,
--0.0761719f, 0.21875f, -0.101562f, 0.250977f, -0.137695f, 0.276855f, -0.189941f,
-0.322754f, -0.281738f, 0.322754f, -0.353027f, 0.315918f, -0.677246f, 0.231445f, -0.382812f,
-0.27002f, -0.424805f, 0.295898f, -0.438721f, 0.321777f, -0.452637f, 0.352051f, -0.452637f,
-0.410645f, -0.452637f, 0.439697f, -0.4104f, 0.46875f, -0.368164f, 0.46875f, -0.312988f,
-0.46875f, -0.181152f, 0.373047f, -0.0776367f, 0.288086f, 0.0136719f, 0.179688f, 0.0136719f,
-0.0991211f, 0.0136719f, 0.00927734f, -0.0336914f, 0.158691f, -0.551758f, 0.169434f,
--0.588379f, 0.169434f, -0.602051f, 0.169434f, -0.61377f, 0.159668f, -0.620605f, 0.145996f,
--0.630371f, 0.118164f, -0.628906f, 0.123535f, -0.648438f, 0.286621f, -0.677246f,
-0.128418f, -0.0288086f, 0.151367f, -0.0141602f, 0.169922f, -0.0141602f, 0.195801f,
--0.0141602f, 0.213379f, -0.0244141f, 0.241211f, -0.0410156f, 0.271729f, -0.0844727f,
-0.302246f, -0.12793f, 0.322754f, -0.189453f, 0.343262f, -0.250977f, 0.343262f, -0.312012f,
-0.343262f, -0.34668f, 0.327637f, -0.364746f, 0.312012f, -0.382812f, 0.291504f, -0.382812f,
-0.257324f, -0.382812f, 0.231934f, -0.349609f, 0.214844f, -0.328125f, 0.194824f, -0.258301f,
-0.15625f, -0.183105f, 0.151855f, -0.151367f, 0.151855f, -0.130859f, 0.151855f, -0.0942383f,
-0.173096f, -0.0722656f, 0.194336f, -0.050293f, 0.22998f, -0.050293f, 0.26416f, -0.050293f,
-0.298584f, -0.0668945f, 0.333008f, -0.0834961f, 0.378418f, -0.125f, 0.393066f, -0.111816f,
-0.336914f, -0.0439453f, 0.283691f, -0.0151367f, 0.230469f, 0.0136719f, 0.166016f,
-0.0136719f, 0.0844727f, 0.0136719f, 0.0532227f, -0.0253906f, 0.0219727f, -0.0644531f,
-0.0219727f, -0.115723f, 0.0219727f, -0.195801f, 0.0686035f, -0.275879f, 0.115234f,
--0.355957f, 0.195557f, -0.404297f, 0.275879f, -0.452637f, 0.356934f, -0.452637f,
-0.397949f, -0.452637f, 0.418945f, -0.433105f, 0.439941f, -0.413574f, 0.439941f, -0.383789f,
-0.439941f, -0.348145f, 0.419434f, -0.314453f, 0.391113f, -0.268555f, 0.348145f, -0.240479f,
-0.305176f, -0.212402f, 0.251953f, -0.197754f, 0.216309f, -0.187988f, 0.15625f, -0.183105f,
-0.160645f, -0.208496f, 0.203613f, -0.214844f, 0.227295f, -0.22583f, 0.250977f, -0.236816f,
-0.273682f, -0.260986f, 0.296387f, -0.285156f, 0.312988f, -0.322021f, 0.32959f, -0.358887f,
-0.32959f, -0.391113f, 0.32959f, -0.404785f, 0.322021f, -0.412598f, 0.314453f, -0.42041f,
-0.302734f, -0.42041f, 0.279297f, -0.42041f, 0.25f, -0.387695f, 0.196289f, -0.328125f,
-0.160645f, -0.208496f, 0.261719f, -0.381836f, 0.20459f, -0.15625f, 0.164551f, 0.00341797f,
-0.126465f, 0.0751953f, 0.0883789f, 0.146973f, 0.0373535f, 0.181396f, -0.0136719f,
-0.21582f, -0.0795898f, 0.21582f, -0.121094f, 0.21582f, -0.140625f, 0.199951f, -0.160156f,
-0.184082f, -0.160156f, 0.162598f, -0.160156f, 0.142578f, -0.144043f, 0.12793f, -0.12793f,
-0.113281f, -0.101562f, 0.113281f, -0.0795898f, 0.113281f, -0.0678711f, 0.124512f,
--0.0561523f, 0.135742f, -0.0561523f, 0.152832f, -0.0561523f, 0.168457f, -0.0634766f,
-0.176025f, -0.0708008f, 0.183594f, -0.0708008f, 0.186035f, -0.0683594f, 0.189453f,
--0.0654297f, 0.191895f, -0.0615234f, 0.191895f, -0.046875f, 0.191895f, -0.0366211f,
-0.182617f, -0.0107422f, 0.159668f, 0.00195312f, 0.126953f, 0.0107422f, 0.104492f,
-0.0356445f, 0.00830078f, 0.135254f, -0.381836f, 0.0673828f, -0.381836f, 0.0834961f,
--0.438965f, 0.120117f, -0.438477f, 0.136719f, -0.448242f, 0.15332f, -0.458008f, 0.171875f,
--0.492188f, 0.225586f, -0.591309f, 0.285156f, -0.634277f, 0.344727f, -0.677246f,
-0.417969f, -0.677246f, 0.464844f, -0.677246f, 0.486084f, -0.65918f, 0.507324f, -0.641113f,
-0.507324f, -0.612305f, 0.507324f, -0.586914f, 0.493164f, -0.572021f, 0.479004f, -0.557129f,
-0.458008f, -0.557129f, 0.438477f, -0.557129f, 0.425781f, -0.569336f, 0.413086f, -0.581543f,
-0.413086f, -0.598633f, 0.413086f, -0.61084f, 0.421143f, -0.624512f, 0.429199f, -0.638184f,
-0.429199f, -0.643066f, 0.429199f, -0.648438f, 0.425537f, -0.651855f, 0.421875f, -0.655273f,
-0.416016f, -0.655273f, 0.387207f, -0.655273f, 0.356934f, -0.619629f, 0.307129f, -0.5625f,
-0.276855f, -0.438965f, 0.347656f, -0.438965f, 0.330566f, -0.381836f, 0.386719f, -0.422852f,
-0.516602f, -0.422852f, 0.500977f, -0.369141f, 0.433594f, -0.369141f, 0.449219f, -0.340332f,
-0.449219f, -0.314453f, 0.449219f, -0.27002f, 0.425049f, -0.232422f, 0.400879f, -0.194824f,
-0.35376f, -0.172363f, 0.306641f, -0.149902f, 0.249023f, -0.149902f, 0.233887f, -0.149902f,
-0.215576f, -0.1521f, 0.197266f, -0.154297f, 0.175781f, -0.158203f, 0.143555f, -0.141602f,
-0.135254f, -0.131836f, 0.129395f, -0.125f, 0.129395f, -0.117676f, 0.129395f, -0.108887f,
-0.136719f, -0.102539f, 0.149414f, -0.0913086f, 0.174316f, -0.0859375f, 0.273926f,
--0.0644531f, 0.305664f, -0.0512695f, 0.349121f, -0.0332031f, 0.371338f, -0.00488281f,
-0.393555f, 0.0234375f, 0.393555f, 0.0634766f, 0.393555f, 0.124512f, 0.337402f, 0.170166f,
-0.28125f, 0.21582f, 0.163574f, 0.21582f, 0.0449219f, 0.21582f, -0.0112305f, 0.176758f,
--0.0517578f, 0.148438f, -0.0517578f, 0.109375f, -0.0517578f, 0.0795898f, -0.0251465f,
-0.0541992f, 0.00146484f, 0.0288086f, 0.0888672f, 0.00927734f, 0.059082f, -0.00732422f,
-0.0488281f, -0.0209961f, 0.034668f, -0.0395508f, 0.034668f, -0.0595703f, 0.034668f,
--0.0922852f, 0.060791f, -0.117188f, 0.0869141f, -0.14209f, 0.148438f, -0.166504f,
-0.100586f, -0.185547f, 0.0793457f, -0.215576f, 0.0581055f, -0.245605f, 0.0581055f,
--0.285645f, 0.0581055f, -0.328125f, 0.0837402f, -0.366455f, 0.109375f, -0.404785f,
-0.159424f, -0.428711f, 0.209473f, -0.452637f, 0.274414f, -0.452637f, 0.315918f, -0.452637f,
-0.348145f, -0.443359f, 0.364746f, -0.438477f, 0.386719f, -0.422852f, 0.284668f, -0.428711f,
-0.260742f, -0.428711f, 0.244141f, -0.413086f, 0.217773f, -0.38916f, 0.197998f, -0.333008f,
-0.178223f, -0.276855f, 0.178223f, -0.226562f, 0.178223f, -0.202637f, 0.192139f, -0.188721f,
-0.206055f, -0.174805f, 0.226562f, -0.174805f, 0.246582f, -0.174805f, 0.26123f, -0.188477f,
-0.289062f, -0.215332f, 0.30957f, -0.27417f, 0.330078f, -0.333008f, 0.330078f, -0.380859f,
-0.330078f, -0.402344f, 0.316895f, -0.415527f, 0.303711f, -0.428711f, 0.284668f, -0.428711f,
-0.116211f, 0.0205078f, 0.0698242f, 0.0385742f, 0.0529785f, 0.0595703f, 0.0361328f,
-0.0805664f, 0.0361328f, 0.10498f, 0.0361328f, 0.136719f, 0.0695801f, 0.162354f, 0.103027f,
-0.187988f, 0.17627f, 0.187988f, 0.237305f, 0.187988f, 0.264648f, 0.165771f, 0.291992f,
-0.143555f, 0.291992f, 0.11377f, 0.291992f, 0.0874023f, 0.266846f, 0.0708008f, 0.241699f,
-0.0541992f, 0.17041f, 0.0361328f, 0.137207f, 0.0273438f, 0.116211f, 0.0205078f, 0.265625f,
--0.452637f, 0.203125f, -0.242676f, 0.266113f, -0.339355f, 0.294922f, -0.373047f,
-0.337402f, -0.422363f, 0.36499f, -0.4375f, 0.392578f, -0.452637f, 0.42041f, -0.452637f,
-0.452148f, -0.452637f, 0.466309f, -0.433594f, 0.480469f, -0.414551f, 0.480469f, -0.391602f,
-0.480469f, -0.367676f, 0.467285f, -0.321289f, 0.445312f, -0.242676f, 0.508789f, -0.340332f,
-0.536621f, -0.372559f, 0.57959f, -0.422363f, 0.611328f, -0.439941f, 0.633301f, -0.452637f,
-0.658203f, -0.452637f, 0.684082f, -0.452637f, 0.701416f, -0.435303f, 0.71875f, -0.417969f,
-0.71875f, -0.390137f, 0.71875f, -0.358887f, 0.704102f, -0.309082f, 0.649902f, -0.126953f,
-0.637695f, -0.0864258f, 0.637695f, -0.074707f, 0.637695f, -0.0708008f, 0.640869f,
--0.0673828f, 0.644043f, -0.0639648f, 0.647949f, -0.0639648f, 0.65332f, -0.0639648f,
-0.657227f, -0.0673828f, 0.674805f, -0.081543f, 0.694336f, -0.108887f, 0.69873f, -0.114746f,
-0.70752f, -0.126953f, 0.724121f, -0.116211f, 0.69043f, -0.0532227f, 0.650146f, -0.0239258f,
-0.609863f, 0.00537109f, 0.575684f, 0.00537109f, 0.545898f, 0.00537109f, 0.527832f,
--0.0109863f, 0.509766f, -0.0273438f, 0.509766f, -0.0493164f, 0.509766f, -0.0703125f,
-0.521973f, -0.112793f, 0.577148f, -0.303223f, 0.588379f, -0.342773f, 0.588379f, -0.352539f,
-0.588379f, -0.355957f, 0.584961f, -0.359131f, 0.581543f, -0.362305f, 0.578125f, -0.362305f,
-0.571777f, -0.362305f, 0.56543f, -0.359375f, 0.556152f, -0.354492f, 0.536865f, -0.333984f,
-0.517578f, -0.313477f, 0.481445f, -0.260498f, 0.445312f, -0.20752f, 0.431396f, -0.177734f,
-0.41748f, -0.147949f, 0.403809f, -0.100586f, 0.374023f, 0, 0.250488f, 0, 0.341797f,
--0.318848f, 0.349121f, -0.344727f, 0.349121f, -0.354492f, 0.349121f, -0.35791f, 0.345947f,
--0.36084f, 0.342773f, -0.36377f, 0.339355f, -0.36377f, 0.321289f, -0.36377f, 0.282227f,
--0.316406f, 0.222656f, -0.243164f, 0.173828f, -0.140137f, 0.134277f, 0, 0.00976562f,
-0, 0.101562f, -0.313965f, 0.115234f, -0.360352f, 0.115234f, -0.379883f, 0.115234f,
--0.387695f, 0.111328f, -0.393311f, 0.107422f, -0.398926f, 0.0986328f, -0.4021f, 0.0898438f,
--0.405273f, 0.0649414f, -0.405273f, 0.0698242f, -0.423828f, 0.236328f, -0.452637f,
-0.26709f, -0.452637f, 0.206543f, -0.243164f, 0.267578f, -0.334961f, 0.297852f, -0.368652f,
-0.342285f, -0.41748f, 0.374512f, -0.435059f, 0.406738f, -0.452637f, 0.435059f, -0.452637f,
-0.460449f, -0.452637f, 0.478516f, -0.433838f, 0.496582f, -0.415039f, 0.496582f, -0.384766f,
-0.496582f, -0.357422f, 0.484863f, -0.318359f, 0.422363f, -0.109863f, 0.414551f, -0.0825195f,
-0.414551f, -0.0742188f, 0.414551f, -0.0693359f, 0.418213f, -0.0654297f, 0.421875f,
--0.0615234f, 0.425781f, -0.0615234f, 0.430664f, -0.0615234f, 0.436035f, -0.0654297f,
-0.453125f, -0.0795898f, 0.470703f, -0.105469f, 0.475098f, -0.112305f, 0.484863f,
--0.125977f, 0.503418f, -0.114746f, 0.431641f, 0.00585938f, 0.352539f, 0.00585938f,
-0.322266f, 0.00585938f, 0.305176f, -0.00976562f, 0.288086f, -0.0253906f, 0.288086f,
--0.0488281f, 0.288086f, -0.0693359f, 0.299805f, -0.109863f, 0.36084f, -0.318359f,
-0.367188f, -0.338867f, 0.367188f, -0.348633f, 0.367188f, -0.354004f, 0.362793f, -0.358154f,
-0.358398f, -0.362305f, 0.352539f, -0.362305f, 0.333984f, -0.362305f, 0.307617f, -0.336914f,
-0.240234f, -0.272461f, 0.177246f, -0.14502f, 0.137207f, 0, 0.0126953f, 0, 0.104004f,
--0.313477f, 0.117188f, -0.359863f, 0.117188f, -0.379395f, 0.117188f, -0.387695f,
-0.113281f, -0.393311f, 0.109375f, -0.398926f, 0.100586f, -0.4021f, 0.0917969f, -0.405273f,
-0.0673828f, -0.405273f, 0.0727539f, -0.423828f, 0.237305f, -0.452637f, 0.328613f,
--0.452637f, 0.367188f, -0.452637f, 0.401123f, -0.434814f, 0.435059f, -0.416992f,
-0.452393f, -0.385254f, 0.469727f, -0.353516f, 0.469727f, -0.314941f, 0.469727f, -0.23584f,
-0.425537f, -0.156738f, 0.381348f, -0.0776367f, 0.309082f, -0.0319824f, 0.236816f,
-0.0136719f, 0.163574f, 0.0136719f, 0.097168f, 0.0136719f, 0.060791f, -0.0258789f,
-0.0244141f, -0.0654297f, 0.0244141f, -0.122559f, 0.0244141f, -0.19043f, 0.0515137f,
--0.249756f, 0.0786133f, -0.309082f, 0.120361f, -0.353271f, 0.162109f, -0.397461f,
-0.216309f, -0.425049f, 0.270508f, -0.452637f, 0.328613f, -0.452637f, 0.308594f, -0.426758f,
-0.282715f, -0.426758f, 0.265625f, -0.411621f, 0.231445f, -0.380859f, 0.188477f, -0.267822f,
-0.145508f, -0.154785f, 0.145508f, -0.0639648f, 0.145508f, -0.0415039f, 0.15918f,
--0.0268555f, 0.172852f, -0.012207f, 0.191406f, -0.012207f, 0.210449f, -0.012207f,
-0.225098f, -0.0239258f, 0.246582f, -0.0415039f, 0.277832f, -0.102783f, 0.309082f,
--0.164062f, 0.329102f, -0.238037f, 0.349121f, -0.312012f, 0.349121f, -0.373535f,
-0.349121f, -0.398926f, 0.336914f, -0.412842f, 0.324707f, -0.426758f, 0.308594f, -0.426758f,
-0.0605469f, -0.425293f, 0.222168f, -0.452637f, 0.251465f, -0.452637f, 0.229492f,
--0.373047f, 0.280762f, -0.419922f, 0.313477f, -0.436279f, 0.346191f, -0.452637f,
-0.378418f, -0.452637f, 0.424316f, -0.452637f, 0.449219f, -0.417236f, 0.474121f, -0.381836f,
-0.474121f, -0.330566f, 0.474121f, -0.19043f, 0.376953f, -0.0820312f, 0.291016f, 0.0136719f,
-0.189453f, 0.0136719f, 0.171387f, 0.0136719f, 0.158691f, 0.0102539f, 0.145996f, 0.00683594f,
-0.123047f, -0.00488281f, 0.0976562f, 0.0830078f, 0.0839844f, 0.130859f, 0.0839844f,
-0.155762f, 0.0839844f, 0.171387f, 0.0947266f, 0.18042f, 0.105469f, 0.189453f, 0.14502f,
-0.195801f, 0.140625f, 0.213867f, -0.12207f, 0.213867f, -0.117188f, 0.195801f, -0.0859375f,
-0.194824f, -0.0651855f, 0.175781f, -0.0444336f, 0.156738f, -0.0263672f, 0.09375f,
-0.0927734f, -0.316895f, 0.105957f, -0.362793f, 0.105957f, -0.381836f, 0.105957f,
--0.390137f, 0.102051f, -0.395752f, 0.0981445f, -0.401367f, 0.090332f, -0.403809f,
-0.0825195f, -0.40625f, 0.0551758f, -0.40625f, 0.136719f, -0.050293f, 0.151367f, -0.0263672f,
-0.163086f, -0.0183105f, 0.174805f, -0.0102539f, 0.19043f, -0.0102539f, 0.206055f,
--0.0102539f, 0.220947f, -0.0187988f, 0.23584f, -0.0273438f, 0.257812f, -0.0532227f,
-0.279785f, -0.0791016f, 0.300049f, -0.119629f, 0.320312f, -0.160156f, 0.33252f, -0.21167f,
-0.344727f, -0.263184f, 0.344727f, -0.310059f, 0.344727f, -0.347656f, 0.331299f, -0.364746f,
-0.317871f, -0.381836f, 0.298828f, -0.381836f, 0.281738f, -0.381836f, 0.266602f, -0.373047f,
-0.244629f, -0.360352f, 0.214844f, -0.325684f, 0.236816f, -0.452637f, 0.163086f, -0.178223f,
-0.253906f, -0.378906f, 0.299805f, -0.425293f, 0.32666f, -0.452637f, 0.356445f, -0.452637f,
-0.376953f, -0.452637f, 0.389648f, -0.437744f, 0.402344f, -0.422852f, 0.402344f, -0.395508f,
-0.402344f, -0.348145f, 0.379395f, -0.315918f, 0.364746f, -0.29541f, 0.34668f, -0.29541f,
-0.327148f, -0.29541f, 0.317383f, -0.313477f, 0.307617f, -0.331543f, 0.303711f, -0.334717f,
-0.299805f, -0.337891f, 0.29541f, -0.337891f, 0.290527f, -0.337891f, 0.285156f, -0.334961f,
-0.274414f, -0.329102f, 0.25708f, -0.306396f, 0.239746f, -0.283691f, 0.214355f, -0.230469f,
-0.188965f, -0.177246f, 0.174805f, -0.140381f, 0.160645f, -0.103516f, 0.135254f, 0,
-0.0170898f, 0, 0.0976562f, -0.32373f, 0.106445f, -0.359863f, 0.106445f, -0.371582f,
-0.106445f, -0.384766f, 0.101807f, -0.39209f, 0.097168f, -0.399414f, 0.0891113f, -0.402832f,
-0.0810547f, -0.40625f, 0.0556641f, -0.40625f, 0.0600586f, -0.42041f, 0.20752f, -0.452637f,
-0.37207f, -0.452637f, 0.350586f, -0.301758f, 0.33252f, -0.301758f, 0.328613f, -0.360352f,
-0.296631f, -0.394043f, 0.264648f, -0.427734f, 0.228027f, -0.427734f, 0.205566f, -0.427734f,
-0.190918f, -0.414551f, 0.17627f, -0.401367f, 0.17627f, -0.382812f, 0.17627f, -0.367188f,
-0.182617f, -0.353516f, 0.188965f, -0.339844f, 0.210938f, -0.316406f, 0.288086f, -0.233398f,
-0.304688f, -0.202148f, 0.321289f, -0.170898f, 0.321289f, -0.135254f, 0.321289f, -0.0966797f,
-0.301758f, -0.0622559f, 0.282227f, -0.027832f, 0.243408f, -0.00708008f, 0.20459f,
-0.0136719f, 0.162598f, 0.0136719f, 0.134277f, 0.0136719f, 0.0927734f, 0.00244141f,
-0.0654297f, -0.00537109f, 0.0517578f, -0.00537109f, 0.0395508f, -0.00537109f, 0.0327148f,
--0.00170898f, 0.0258789f, 0.00195312f, 0.0175781f, 0.0136719f, -0.000488281f, 0.0136719f,
-0.0234375f, -0.148926f, 0.0390625f, -0.148926f, 0.0561523f, -0.0898438f, 0.0710449f,
--0.0646973f, 0.0859375f, -0.0395508f, 0.11084f, -0.0246582f, 0.135742f, -0.00976562f,
-0.158691f, -0.00976562f, 0.185547f, -0.00976562f, 0.203125f, -0.0266113f, 0.220703f,
--0.043457f, 0.220703f, -0.0668945f, 0.220703f, -0.0898438f, 0.209229f, -0.111328f,
-0.197754f, -0.132812f, 0.15625f, -0.178223f, 0.0991211f, -0.240234f, 0.0810547f,
--0.273926f, 0.0683594f, -0.29834f, 0.0683594f, -0.32959f, 0.0683594f, -0.382324f,
-0.106689f, -0.41748f, 0.14502f, -0.452637f, 0.214355f, -0.452637f, 0.244629f, -0.452637f,
-0.288574f, -0.441895f, 0.310547f, -0.436523f, 0.32373f, -0.436523f, 0.342773f, -0.436523f,
-0.354492f, -0.452637f, 0.265625f, -0.452637f, 0.170898f, -0.120605f, 0.164062f, -0.0976562f,
-0.164062f, -0.0888672f, 0.164062f, -0.0844727f, 0.16748f, -0.0820312f, 0.171387f,
--0.078125f, 0.176758f, -0.078125f, 0.199219f, -0.078125f, 0.236816f, -0.118164f,
-0.290527f, -0.17627f, 0.349609f, -0.285156f, 0.394043f, -0.43457f, 0.517578f, -0.438965f,
-0.423828f, -0.116699f, 0.412109f, -0.0756836f, 0.412109f, -0.0698242f, 0.412109f,
--0.065918f, 0.415771f, -0.0617676f, 0.419434f, -0.0576172f, 0.42334f, -0.0576172f,
-0.430176f, -0.0576172f, 0.436523f, -0.0634766f, 0.454102f, -0.0776367f, 0.48291f,
--0.120605f, 0.499512f, -0.108887f, 0.431641f, 0.0136719f, 0.350098f, 0.0136719f,
-0.319824f, 0.0136719f, 0.30249f, -0.00170898f, 0.285156f, -0.0170898f, 0.285156f,
--0.0419922f, 0.285156f, -0.0683594f, 0.297363f, -0.108887f, 0.321289f, -0.191406f,
-0.257812f, -0.0991211f, 0.229004f, -0.0668945f, 0.185059f, -0.0185547f, 0.155029f,
--0.00244141f, 0.125f, 0.0136719f, 0.0976562f, 0.0136719f, 0.0717773f, 0.0136719f,
-0.0529785f, -0.00537109f, 0.0341797f, -0.0244141f, 0.0341797f, -0.0537109f, 0.0341797f,
--0.0786133f, 0.0463867f, -0.120605f, 0.101562f, -0.315918f, 0.115234f, -0.36377f,
-0.115234f, -0.380371f, 0.115234f, -0.387695f, 0.111328f, -0.393311f, 0.107422f, -0.398926f,
-0.0983887f, -0.4021f, 0.0893555f, -0.405273f, 0.0649414f, -0.405273f, 0.0698242f,
--0.423828f, 0.236328f, -0.452637f, 0.0253906f, -0.408691f, 0.175781f, -0.452637f,
-0.193848f, -0.430176f, 0.201172f, -0.410156f, 0.214355f, -0.375488f, 0.219727f, -0.314453f,
-0.22998f, -0.194336f, 0.233887f, -0.0581055f, 0.286133f, -0.126953f, 0.353516f, -0.240234f,
-0.374023f, -0.274414f, 0.374023f, -0.304688f, 0.374023f, -0.32373f, 0.350342f, -0.34082f,
-0.32666f, -0.35791f, 0.320801f, -0.367432f, 0.314941f, -0.376953f, 0.314941f, -0.39209f,
-0.314941f, -0.416504f, 0.332764f, -0.43457f, 0.350586f, -0.452637f, 0.375977f, -0.452637f,
-0.402832f, -0.452637f, 0.422607f, -0.432129f, 0.442383f, -0.411621f, 0.442383f, -0.383789f,
-0.442383f, -0.351074f, 0.424072f, -0.307861f, 0.405762f, -0.264648f, 0.338379f, -0.159668f,
-0.251953f, -0.0253906f, 0.168945f, 0.0727539f, 0.115723f, 0.135254f, 0.0830078f,
-0.162842f, 0.050293f, 0.19043f, 0.0151367f, 0.206543f, -0.00585938f, 0.21582f, -0.0263672f,
-0.21582f, -0.0541992f, 0.21582f, -0.0739746f, 0.196289f, -0.09375f, 0.176758f, -0.09375f,
-0.149902f, -0.09375f, 0.123047f, -0.0759277f, 0.104492f, -0.0581055f, 0.0859375f,
--0.0341797f, 0.0859375f, -0.00439453f, 0.0859375f, 0.0205078f, 0.117188f, 0.0371094f,
-0.138184f, 0.0478516f, 0.138184f, 0.059082f, 0.138184f, 0.0698242f, 0.131836f, 0.0844727f,
-0.124023f, 0.11084f, 0.0957031f, 0.11377f, 0.034668f, 0.11377f, 0.00341797f, 0.11377f,
--0.0385742f, 0.109863f, -0.114746f, 0.101562f, -0.300781f, 0.097168f, -0.352051f,
-0.0795898f, -0.374512f, 0.065918f, -0.391113f, 0.0439453f, -0.391113f, 0.0356445f,
--0.391113f, 0.0253906f, -0.389648f
-};
-
-const unsigned char TimesNewRomankBoldItalicVerbs[] = {
-6, 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 5,
-0, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1,
-1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2,
-1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 5, 6, 0, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1,
-1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 5, 6,
-0, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1,
-1, 1, 1, 2, 2, 2, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2,
-2, 2, 1, 2, 2, 2, 1, 1, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 2, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0,
-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 1,
-2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2,
-2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1,
-1, 5, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 5, 6, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2,
-2, 2, 2, 5, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6,
-0, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
-1, 2, 2, 2, 2, 1, 1, 5, 6, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 5, 6
-};
-
-const unsigned TimesNewRomankBoldItalicCharCodes[] = {
-32, 65, 72, 84, 87, 89, 97, 98,
-101, 102, 103, 109, 110, 111, 112, 114, 115, 117, 121
-};
-
-const SkFixed TimesNewRomankBoldItalicWidths[] = {
-0x00004000, 0x0000aac0, 0x0000c720, 0x00009c60, 0x0000e3a0, 0x00009c60, 0x00008000,
-0x00008000, 0x000071a0, 0x00005540, 0x00008000, 0x0000c720, 0x00008e60, 0x00008000,
-0x00008000, 0x000063a0, 0x000063a0, 0x00008e60, 0x000071a0
-};
-
-const int TimesNewRomankBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(TimesNewRomankBoldItalicCharCodes);
-
-const SkPaint::FontMetrics TimesNewRomankBoldItalicMetrics = {
-0x3436342f, -1.03223f, -0.891113f, 0.216309f, 0.306641f, 0.0424805f, 1.94824f, 7.98734e-16f,
--0.547363f, 1.40088f, 0.466309f, 9.77694e-15f, 0.0952148f, 0.108887f
-};
-
-static SkTestFontData gTestFonts[] = {
- { CourierNewkNormalPoints, CourierNewkNormalVerbs, CourierNewkNormalCharCodes,
- CourierNewkNormalCharCodesCount, CourierNewkNormalWidths,
- CourierNewkNormalMetrics, "Courier New", SkTypeface::kNormal, nullptr
- },
- { CourierNewkBoldPoints, CourierNewkBoldVerbs, CourierNewkBoldCharCodes,
- CourierNewkBoldCharCodesCount, CourierNewkBoldWidths,
- CourierNewkBoldMetrics, "Courier New", SkTypeface::kBold, nullptr
- },
- { CourierNewkItalicPoints, CourierNewkItalicVerbs, CourierNewkItalicCharCodes,
- CourierNewkItalicCharCodesCount, CourierNewkItalicWidths,
- CourierNewkItalicMetrics, "Courier New", SkTypeface::kItalic, nullptr
- },
- { CourierNewkBoldItalicPoints, CourierNewkBoldItalicVerbs, CourierNewkBoldItalicCharCodes,
- CourierNewkBoldItalicCharCodesCount, CourierNewkBoldItalicWidths,
- CourierNewkBoldItalicMetrics, "Courier New", SkTypeface::kBoldItalic, nullptr
- },
- { LiberationSanskNormalPoints, LiberationSanskNormalVerbs, LiberationSanskNormalCharCodes,
- LiberationSanskNormalCharCodesCount, LiberationSanskNormalWidths,
- LiberationSanskNormalMetrics, "Liberation Sans", SkTypeface::kNormal, nullptr
- },
- { LiberationSanskBoldPoints, LiberationSanskBoldVerbs, LiberationSanskBoldCharCodes,
- LiberationSanskBoldCharCodesCount, LiberationSanskBoldWidths,
- LiberationSanskBoldMetrics, "Liberation Sans", SkTypeface::kBold, nullptr
- },
- { LiberationSanskItalicPoints, LiberationSanskItalicVerbs, LiberationSanskItalicCharCodes,
- LiberationSanskItalicCharCodesCount, LiberationSanskItalicWidths,
- LiberationSanskItalicMetrics, "Liberation Sans", SkTypeface::kItalic, nullptr
- },
- { LiberationSanskBoldItalicPoints, LiberationSanskBoldItalicVerbs, LiberationSanskBoldItalicCharCodes,
- LiberationSanskBoldItalicCharCodesCount, LiberationSanskBoldItalicWidths,
- LiberationSanskBoldItalicMetrics, "Liberation Sans", SkTypeface::kBoldItalic, nullptr
- },
- { HiraginoMaruGothicProkNormalPoints, HiraginoMaruGothicProkNormalVerbs, HiraginoMaruGothicProkNormalCharCodes,
- HiraginoMaruGothicProkNormalCharCodesCount, HiraginoMaruGothicProkNormalWidths,
- HiraginoMaruGothicProkNormalMetrics, "Hiragino Maru Gothic Pro", SkTypeface::kNormal, nullptr
- },
- { PapyruskNormalPoints, PapyruskNormalVerbs, PapyruskNormalCharCodes,
- PapyruskNormalCharCodesCount, PapyruskNormalWidths,
- PapyruskNormalMetrics, "Papyrus", SkTypeface::kNormal, nullptr
- },
- { TimesNewRomankNormalPoints, TimesNewRomankNormalVerbs, TimesNewRomankNormalCharCodes,
- TimesNewRomankNormalCharCodesCount, TimesNewRomankNormalWidths,
- TimesNewRomankNormalMetrics, "Times New Roman", SkTypeface::kNormal, nullptr
- },
- { TimesNewRomankBoldPoints, TimesNewRomankBoldVerbs, TimesNewRomankBoldCharCodes,
- TimesNewRomankBoldCharCodesCount, TimesNewRomankBoldWidths,
- TimesNewRomankBoldMetrics, "Times New Roman", SkTypeface::kBold, nullptr
- },
- { TimesNewRomankItalicPoints, TimesNewRomankItalicVerbs, TimesNewRomankItalicCharCodes,
- TimesNewRomankItalicCharCodesCount, TimesNewRomankItalicWidths,
- TimesNewRomankItalicMetrics, "Times New Roman", SkTypeface::kItalic, nullptr
- },
- { TimesNewRomankBoldItalicPoints, TimesNewRomankBoldItalicVerbs, TimesNewRomankBoldItalicCharCodes,
- TimesNewRomankBoldItalicCharCodesCount, TimesNewRomankBoldItalicWidths,
- TimesNewRomankBoldItalicMetrics, "Times New Roman", SkTypeface::kBoldItalic, nullptr
- },
-};
-
-const int gTestFontsCount = (int) SK_ARRAY_COUNT(gTestFonts);
-
-struct SubFont {
- const char* fName;
- SkTypeface::Style fStyle;
- SkTestFontData& fFont;
- const char* fFile;
-};
-
-const SubFont gSubFonts[] = {
- { "Courier New", SkTypeface::kNormal, gTestFonts[0], "Courier New.ttf"},
- { "Courier New", SkTypeface::kBold, gTestFonts[1], "Courier New Bold.ttf"},
- { "Courier New", SkTypeface::kItalic, gTestFonts[2], "Courier New Italic.ttf"},
- { "Courier New", SkTypeface::kBoldItalic, gTestFonts[3], "Courier New Bold Italic.ttf"},
- { "Helvetica", SkTypeface::kNormal, gTestFonts[4], "LiberationSans-Regular.ttf"},
- { "Helvetica", SkTypeface::kBold, gTestFonts[5], "LiberationSans-Bold.ttf"},
- { "Helvetica", SkTypeface::kItalic, gTestFonts[6], "LiberationSans-Italic.ttf"},
- { "Helvetica", SkTypeface::kBoldItalic, gTestFonts[7], "LiberationSans-BoldItalic.ttf"},
- { "Hiragino Maru Gothic Pro", SkTypeface::kNormal, gTestFonts[8], "Pro W4.otf"},
- { "Liberation Sans", SkTypeface::kNormal, gTestFonts[4], "LiberationSans-Regular.ttf"},
- { "Liberation Sans", SkTypeface::kBold, gTestFonts[5], "LiberationSans-Bold.ttf"},
- { "Liberation Sans", SkTypeface::kItalic, gTestFonts[6], "LiberationSans-Italic.ttf"},
- { "Liberation Sans", SkTypeface::kBoldItalic, gTestFonts[7], "LiberationSans-BoldItalic.ttf"},
- { "monospace", SkTypeface::kNormal, gTestFonts[0], "Courier New.ttf"},
- { "monospace", SkTypeface::kBold, gTestFonts[1], "Courier New Bold.ttf"},
- { "monospace", SkTypeface::kItalic, gTestFonts[2], "Courier New Italic.ttf"},
- { "monospace", SkTypeface::kBoldItalic, gTestFonts[3], "Courier New Bold Italic.ttf"},
- { "Papyrus", SkTypeface::kNormal, gTestFonts[9], "Papyrus.ttc"},
- { "sans-serif", SkTypeface::kNormal, gTestFonts[4], "LiberationSans-Regular.ttf"},
- { "sans-serif", SkTypeface::kBold, gTestFonts[5], "LiberationSans-Bold.ttf"},
- { "sans-serif", SkTypeface::kItalic, gTestFonts[6], "LiberationSans-Italic.ttf"},
- { "sans-serif", SkTypeface::kBoldItalic, gTestFonts[7], "LiberationSans-BoldItalic.ttf"},
- { "serif", SkTypeface::kNormal, gTestFonts[10], "Times New Roman.ttf"},
- { "serif", SkTypeface::kBold, gTestFonts[11], "Times New Roman Bold.ttf"},
- { "serif", SkTypeface::kItalic, gTestFonts[12], "Times New Roman Italic.ttf"},
- { "serif", SkTypeface::kBoldItalic, gTestFonts[13], "Times New Roman Bold Italic.ttf"},
- { "Times", SkTypeface::kNormal, gTestFonts[10], "Times New Roman.ttf"},
- { "Times", SkTypeface::kBold, gTestFonts[11], "Times New Roman Bold.ttf"},
- { "Times", SkTypeface::kItalic, gTestFonts[12], "Times New Roman Italic.ttf"},
- { "Times", SkTypeface::kBoldItalic, gTestFonts[13], "Times New Roman Bold Italic.ttf"},
- { "Times New Roman", SkTypeface::kNormal, gTestFonts[10], "Times New Roman.ttf"},
- { "Times New Roman", SkTypeface::kBold, gTestFonts[11], "Times New Roman Bold.ttf"},
- { "Times New Roman", SkTypeface::kItalic, gTestFonts[12], "Times New Roman Italic.ttf"},
- { "Times New Roman", SkTypeface::kBoldItalic, gTestFonts[13], "Times New Roman Bold Italic.ttf"},
- { "Times Roman", SkTypeface::kNormal, gTestFonts[4], "LiberationSans-Regular.ttf"},
-};
-
-const int gSubFontsCount = (int) SK_ARRAY_COUNT(gSubFonts);
-
-const int gDefaultFontIndex = 12;
diff --git a/src/third_party/skia/tools/test_font_data_chars.cpp b/src/third_party/skia/tools/test_font_data_chars.cpp
deleted file mode 100644
index ffbfa88..0000000
--- a/src/third_party/skia/tools/test_font_data_chars.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Auto-generated by sk_tool_utils_font.cpp
-
-const char gCourierNew[] =
- " !/<>ACHMTWYabcdefgilmnoprstuy";
-const char gCourierNew_Bold[] =
- " AHTWYabefgmnoprsuy";
-const char gCourierNew_Italic[] =
- " AHTWYabefgmnoprsuy";
-const char gCourierNew_BoldItalic[] =
- " AHTWYabefgmnoprsuy";
-const char gLiberationSans[] =
- " !#%&')*+-./1245679:;<=>?@ABCDEFHIJKLMNOPQRSTVWXYZ[\\]^`abcdefgilmnopqrstuvwxyz";
-const char gLiberationSans_Bold[] =
- " !\"#$%&'()*+-./012356789:;=>?ABCDEFGHIJLMORSTUVWXYZ[]^_abdefghijklmnopqrsuvwxyz";
-const char gLiberationSans_Italic[] =
- " AHTWYabefgmnoprsuy";
-const char gLiberationSans_BoldItalic[] =
- " !,-./012345689:ABCDEFGHIKLMNOPQRSTUWXYZ[\\]_abcdefghijklmnopqrstuvwxyz";
-const char gHiraginoMaruGothicPro[] =
- " !Tacefnprsuy" "\xE3" "\x83" "\xBC";
-const char gPapyrus[] =
- " !HTaceflnoprsuy";
-const char gTimesNewRoman[] =
- " !\"#$%&'()*+,-./123456789;<=>?@ABCDEFGHIJKLMNPQRSTVWXYZ[\\]^_`abcdefgijklmnopqrstuvwxyz";
-const char gTimesNewRoman_Bold[] =
- " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz";
-const char gTimesNewRoman_Italic[] =
- " AHTWYabefgmnoprsuy";
-const char gTimesNewRoman_BoldItalic[] =
- " AHTWYabefgmnoprsuy";
diff --git a/src/third_party/skia/tools/test_font_index.inc b/src/third_party/skia/tools/test_font_index.inc
deleted file mode 100644
index b52c004..0000000
--- a/src/third_party/skia/tools/test_font_index.inc
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Auto-generated by create_test_font.cpp
-
-static SkTestFontData gTestFonts[] = {
- { LiberationMonoNormalPoints, LiberationMonoNormalVerbs, LiberationMonoNormalCharCodes,
- LiberationMonoNormalCharCodesCount, LiberationMonoNormalWidths,
- LiberationMonoNormalMetrics, "Toy Liberation Mono", SkTypeface::kNormal, nullptr
- },
- { LiberationMonoBoldPoints, LiberationMonoBoldVerbs, LiberationMonoBoldCharCodes,
- LiberationMonoBoldCharCodesCount, LiberationMonoBoldWidths,
- LiberationMonoBoldMetrics, "Toy Liberation Mono", SkTypeface::kBold, nullptr
- },
- { LiberationMonoItalicPoints, LiberationMonoItalicVerbs, LiberationMonoItalicCharCodes,
- LiberationMonoItalicCharCodesCount, LiberationMonoItalicWidths,
- LiberationMonoItalicMetrics, "Toy Liberation Mono", SkTypeface::kItalic, nullptr
- },
- { LiberationMonoBoldItalicPoints, LiberationMonoBoldItalicVerbs, LiberationMonoBoldItalicCharCodes,
- LiberationMonoBoldItalicCharCodesCount, LiberationMonoBoldItalicWidths,
- LiberationMonoBoldItalicMetrics, "Toy Liberation Mono", SkTypeface::kBoldItalic, nullptr
- },
- { LiberationSansNormalPoints, LiberationSansNormalVerbs, LiberationSansNormalCharCodes,
- LiberationSansNormalCharCodesCount, LiberationSansNormalWidths,
- LiberationSansNormalMetrics, "Toy Liberation Sans", SkTypeface::kNormal, nullptr
- },
- { LiberationSansBoldPoints, LiberationSansBoldVerbs, LiberationSansBoldCharCodes,
- LiberationSansBoldCharCodesCount, LiberationSansBoldWidths,
- LiberationSansBoldMetrics, "Toy Liberation Sans", SkTypeface::kBold, nullptr
- },
- { LiberationSansItalicPoints, LiberationSansItalicVerbs, LiberationSansItalicCharCodes,
- LiberationSansItalicCharCodesCount, LiberationSansItalicWidths,
- LiberationSansItalicMetrics, "Toy Liberation Sans", SkTypeface::kItalic, nullptr
- },
- { LiberationSansBoldItalicPoints, LiberationSansBoldItalicVerbs, LiberationSansBoldItalicCharCodes,
- LiberationSansBoldItalicCharCodesCount, LiberationSansBoldItalicWidths,
- LiberationSansBoldItalicMetrics, "Toy Liberation Sans", SkTypeface::kBoldItalic, nullptr
- },
- { LiberationSerifNormalPoints, LiberationSerifNormalVerbs, LiberationSerifNormalCharCodes,
- LiberationSerifNormalCharCodesCount, LiberationSerifNormalWidths,
- LiberationSerifNormalMetrics, "Toy Liberation Serif", SkTypeface::kNormal, nullptr
- },
- { LiberationSerifBoldPoints, LiberationSerifBoldVerbs, LiberationSerifBoldCharCodes,
- LiberationSerifBoldCharCodesCount, LiberationSerifBoldWidths,
- LiberationSerifBoldMetrics, "Toy Liberation Serif", SkTypeface::kBold, nullptr
- },
- { LiberationSerifItalicPoints, LiberationSerifItalicVerbs, LiberationSerifItalicCharCodes,
- LiberationSerifItalicCharCodesCount, LiberationSerifItalicWidths,
- LiberationSerifItalicMetrics, "Toy Liberation Serif", SkTypeface::kItalic, nullptr
- },
- { LiberationSerifBoldItalicPoints, LiberationSerifBoldItalicVerbs, LiberationSerifBoldItalicCharCodes,
- LiberationSerifBoldItalicCharCodesCount, LiberationSerifBoldItalicWidths,
- LiberationSerifBoldItalicMetrics, "Toy Liberation Serif", SkTypeface::kBoldItalic, nullptr
- },
-};
-
-const int gTestFontsCount = (int) SK_ARRAY_COUNT(gTestFonts);
-
-struct SubFont {
- const char* fName;
- SkFontStyle fStyle;
- SkTestFontData& fFont;
- const char* fFile;
-};
-
-const SubFont gSubFonts[] = {
- { "monospace", SkFontStyle(), gTestFonts[0], "LiberationMono-Regular.ttf" },
- { "monospace", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[1], "LiberationMono-Bold.ttf" },
- { "monospace", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[2], "LiberationMono-Italic.ttf" },
- { "monospace", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[3], "LiberationMono-BoldItalic.ttf" },
- { "sans-serif", SkFontStyle(), gTestFonts[4], "LiberationSans-Regular.ttf" },
- { "sans-serif", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[5], "LiberationSans-Bold.ttf" },
- { "sans-serif", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[6], "LiberationSans-Italic.ttf" },
- { "sans-serif", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[7], "LiberationSans-BoldItalic.ttf" },
- { "serif", SkFontStyle(), gTestFonts[8], "LiberationSerif-Regular.ttf" },
- { "serif", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[9], "LiberationSerif-Bold.ttf" },
- { "serif", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[10], "LiberationSerif-Italic.ttf" },
- { "serif", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[11], "LiberationSerif-BoldItalic.ttf" },
- { "Toy Liberation Mono", SkFontStyle(), gTestFonts[0], "LiberationMono-Regular.ttf" },
- { "Toy Liberation Mono", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[1], "LiberationMono-Bold.ttf" },
- { "Toy Liberation Mono", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[2], "LiberationMono-Italic.ttf" },
- { "Toy Liberation Mono", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[3], "LiberationMono-BoldItalic.ttf" },
- { "Toy Liberation Sans", SkFontStyle(), gTestFonts[4], "LiberationSans-Regular.ttf" },
- { "Toy Liberation Sans", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[5], "LiberationSans-Bold.ttf" },
- { "Toy Liberation Sans", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[6], "LiberationSans-Italic.ttf" },
- { "Toy Liberation Sans", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[7], "LiberationSans-BoldItalic.ttf" },
- { "Toy Liberation Serif", SkFontStyle(), gTestFonts[8], "LiberationSerif-Regular.ttf" },
- { "Toy Liberation Serif", SkFontStyle::FromOldStyle(SkTypeface::kBold), gTestFonts[9], "LiberationSerif-Bold.ttf" },
- { "Toy Liberation Serif", SkFontStyle::FromOldStyle(SkTypeface::kItalic), gTestFonts[10], "LiberationSerif-Italic.ttf" },
- { "Toy Liberation Serif", SkFontStyle::FromOldStyle(SkTypeface::kBoldItalic), gTestFonts[11], "LiberationSerif-BoldItalic.ttf" },
-};
-
-const int gSubFontsCount = (int) SK_ARRAY_COUNT(gSubFonts);
-
-const int gDefaultFontIndex = 4;
diff --git a/src/third_party/skia/tools/test_gpuveto.py b/src/third_party/skia/tools/test_gpuveto.py
deleted file mode 100755
index fbb29ae..0000000
--- a/src/third_party/skia/tools/test_gpuveto.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2014 Google Inc.
-#
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Script to test out suitableForGpuRasterization (via gpuveto)"""
-
-import argparse
-import glob
-import os
-import re
-import subprocess
-import sys
-
-# Set the PYTHONPATH to include the tools directory.
-sys.path.append(
- os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
-import find_run_binary
-
-def list_files(dir_or_file):
- """Returns a list of all the files from the provided argument
-
- @param dir_or_file: either a directory or skp file
-
- @returns a list containing the files in the directory or a single file
- """
- files = []
- for globbedpath in glob.iglob(dir_or_file): # useful on win32
- if os.path.isdir(globbedpath):
- for filename in os.listdir(globbedpath):
- newpath = os.path.join(globbedpath, filename)
- if os.path.isfile(newpath):
- files.append(newpath)
- elif os.path.isfile(globbedpath):
- files.append(globbedpath)
- return files
-
-
-def execute_program(args):
- """Executes a process and waits for it to complete.
-
- @param args: is passed into subprocess.Popen().
-
- @returns a tuple of the process output (returncode, output)
- """
- proc = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- output, _ = proc.communicate()
- errcode = proc.returncode
- return (errcode, output)
-
-
-class GpuVeto(object):
-
- def __init__(self):
- self.bench_pictures = find_run_binary.find_path_to_program(
- 'bench_pictures')
- sys.stdout.write('Running: %s\n' % (self.bench_pictures))
- self.gpuveto = find_run_binary.find_path_to_program('gpuveto')
- assert os.path.isfile(self.bench_pictures)
- assert os.path.isfile(self.gpuveto)
- self.indeterminate = 0
- self.truePositives = 0
- self.falsePositives = 0
- self.trueNegatives = 0
- self.falseNegatives = 0
-
- def process_skps(self, dir_or_file):
- for skp in enumerate(dir_or_file):
- self.process_skp(skp[1])
-
- sys.stdout.write('TP %d FP %d TN %d FN %d IND %d\n' % (self.truePositives,
- self.falsePositives,
- self.trueNegatives,
- self.falseNegatives,
- self.indeterminate))
-
-
- def process_skp(self, skp_file):
- assert os.path.isfile(skp_file)
- #print skp_file
-
- # run gpuveto on the skp
- args = [self.gpuveto, '-r', skp_file]
- returncode, output = execute_program(args)
- if (returncode != 0):
- return
-
- if ('unsuitable' in output):
- suitable = False
- else:
- assert 'suitable' in output
- suitable = True
-
- # run raster config
- args = [self.bench_pictures, '-r', skp_file,
- '--repeat', '20',
- '--timers', 'w',
- '--config', '8888']
- returncode, output = execute_program(args)
- if (returncode != 0):
- return
-
- matches = re.findall('[\d]+\.[\d]+', output)
- if len(matches) != 1:
- return
-
- rasterTime = float(matches[0])
-
- # run gpu config
- args2 = [self.bench_pictures, '-r', skp_file,
- '--repeat', '20',
- '--timers', 'w',
- '--config', 'gpu']
- returncode, output = execute_program(args2)
- if (returncode != 0):
- return
-
- matches = re.findall('[\d]+\.[\d]+', output)
- if len(matches) != 1:
- return
-
- gpuTime = float(matches[0])
-
- # happens if page is too big it will not render
- if 0 == gpuTime:
- return
-
- tolerance = 0.05
- tol_range = tolerance * gpuTime
-
-
- if rasterTime > gpuTime - tol_range and rasterTime < gpuTime + tol_range:
- result = "NONE"
- self.indeterminate += 1
- elif suitable:
- if gpuTime < rasterTime:
- self.truePositives += 1
- result = "TP"
- else:
- self.falsePositives += 1
- result = "FP"
- else:
- if gpuTime < rasterTime:
- self.falseNegatives += 1
- result = "FN"
- else:
- self.trueNegatives += 1
- result = "TN"
-
-
- sys.stdout.write('%s: gpuveto: %d raster %.2f gpu: %.2f Result: %s\n' % (
- skp_file, suitable, rasterTime, gpuTime, result))
-
-def main(main_argv):
- parser = argparse.ArgumentParser()
- parser.add_argument('--skp_path',
- help='Path to the SKP(s). Can either be a directory ' \
- 'containing SKPs or a single SKP.',
- required=True)
-
- args = parser.parse_args()
- GpuVeto().process_skps(list_files(args.skp_path))
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1]))
diff --git a/src/third_party/skia/tools/timer/TimeUtils.h b/src/third_party/skia/tools/timer/TimeUtils.h
new file mode 100644
index 0000000..5638f83
--- /dev/null
+++ b/src/third_party/skia/tools/timer/TimeUtils.h
@@ -0,0 +1,62 @@
+// Copyright 2019 Google LLC
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TimeUtils_DEFINED
+#define TimeUtils_DEFINED
+
+#include "include/core/SkTypes.h"
+#include "include/private/SkFloatingPoint.h"
+
+#include <cmath>
+
+namespace TimeUtils {
+ // Returns 0 if the timer is stopped. Behavior is undefined if the timer
+ // has been running longer than SK_MSecMax.
+ static inline SkMSec NanosToMSec(double nanos) {
+ const double msec = nanos * 1e-6;
+ SkASSERT(SK_MSecMax >= msec);
+ return static_cast<SkMSec>(msec);
+ }
+
+ static inline double NanosToSeconds(double nanos) {
+ return nanos * 1e-9;
+ }
+
+ // Return the time scaled by "speed" and (if not zero) mod by period.
+ static inline float Scaled(float time, float speed, float period = 0) {
+ double value = time * speed;
+ if (period) {
+ value = ::fmod(value, (double)(period));
+ }
+ return (float)value;
+ }
+
+ // Transitions from ends->mid->ends linearly over period time. The phase
+ // specifies a phase shift in time units.
+ static inline float PingPong(double time,
+ float period,
+ float phase,
+ float ends,
+ float mid) {
+ double value = ::fmod(time + phase, period);
+ double half = period / 2.0;
+ double diff = ::fabs(value - half);
+ return (float)(ends + (1.0 - diff / half) * (mid - ends));
+ }
+
+ static inline float SineWave(double time,
+ float periodInSecs,
+ float phaseInSecs,
+ float min,
+ float max) {
+ if (periodInSecs < 0.f) {
+ return (min + max) / 2.f;
+ }
+ double t = NanosToSeconds(time) + phaseInSecs;
+ t *= 2 * SK_FloatPI / periodInSecs;
+ float halfAmplitude = (max - min) / 2.f;
+ return halfAmplitude * std::sin(t) + halfAmplitude + min;
+ }
+} // namespace TimeUtils
+#endif
diff --git a/src/third_party/skia/tools/timer/Timer.cpp b/src/third_party/skia/tools/timer/Timer.cpp
index 28841cd..fe214c4 100644
--- a/src/third_party/skia/tools/timer/Timer.cpp
+++ b/src/third_party/skia/tools/timer/Timer.cpp
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "Timer.h"
+#include "tools/timer/Timer.h"
SkString HumanizeMs(double ms) {
if (ms > 60e+3) return SkStringPrintf("%.3gm", ms/60e+3);
diff --git a/src/third_party/skia/tools/timer/Timer.h b/src/third_party/skia/tools/timer/Timer.h
index 446eb25..d461c58 100644
--- a/src/third_party/skia/tools/timer/Timer.h
+++ b/src/third_party/skia/tools/timer/Timer.h
@@ -7,19 +7,7 @@
#ifndef Timer_DEFINED
#define Timer_DEFINED
-#include "SkString.h"
-#include "SkTime.h"
-#include "SkTypes.h"
-
-class WallTimer {
-public:
- WallTimer() : fWall(-1) {}
-
- void start() { fWall = SkTime::GetNSecs(); }
- void end() { fWall = (SkTime::GetNSecs() - fWall) * 1e-6; }
-
- double fWall; // Milliseconds.
-};
+#include "include/core/SkString.h"
SkString HumanizeMs(double);
diff --git a/src/third_party/skia/tools/trace/ChromeTracingTracer.cpp b/src/third_party/skia/tools/trace/ChromeTracingTracer.cpp
new file mode 100644
index 0000000..530c3c3
--- /dev/null
+++ b/src/third_party/skia/tools/trace/ChromeTracingTracer.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkStream.h"
+#include "include/private/SkThreadID.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkTraceEvent.h"
+#include "src/utils/SkJSONWriter.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/trace/ChromeTracingTracer.h"
+
+#include <chrono>
+
+namespace {
+
+/**
+ * All events have a fixed block of information (TraceEvent), plus variable length payload:
+ * {TraceEvent} {TraceEventArgs} {Inline Payload}
+ */
+struct TraceEventArg {
+ uint8_t fArgType;
+ const char* fArgName;
+ uint64_t fArgValue;
+};
+
+// These fields are ordered to minimize size due to alignment. Argument types could be packed
+// better, but very few events have many arguments, so the net loss is pretty small.
+struct TraceEvent {
+ char fPhase;
+ uint8_t fNumArgs;
+ uint32_t fSize;
+
+ const char* fName;
+ // TODO: Merge fID and fClockEnd (never used together)
+ uint64_t fID;
+ uint64_t fClockBegin;
+ uint64_t fClockEnd;
+ SkThreadID fThreadID;
+
+ TraceEvent* next() {
+ return reinterpret_cast<TraceEvent*>(reinterpret_cast<char*>(this) + fSize);
+ }
+ TraceEventArg* args() { return reinterpret_cast<TraceEventArg*>(this + 1); }
+ char* stringTable() { return reinterpret_cast<char*>(this->args() + fNumArgs); }
+};
+
+} // namespace
+
+ChromeTracingTracer::ChromeTracingTracer(const char* filename) : fFilename(filename) {
+ this->createBlock();
+}
+
+ChromeTracingTracer::~ChromeTracingTracer() { this->flush(); }
+
+void ChromeTracingTracer::createBlock() {
+ fCurBlock.fBlock = BlockPtr(new uint8_t[kBlockSize]);
+ fCurBlock.fEventsInBlock = 0;
+ fCurBlockUsed = 0;
+}
+
+SkEventTracer::Handle ChromeTracingTracer::appendEvent(const void* data, size_t size) {
+ SkASSERT(size > 0 && size <= kBlockSize);
+
+ SkAutoSpinlock lock(fMutex);
+ if (fCurBlockUsed + size > kBlockSize) {
+ fBlocks.push_back(std::move(fCurBlock));
+ this->createBlock();
+ }
+ memcpy(fCurBlock.fBlock.get() + fCurBlockUsed, data, size);
+ Handle handle = reinterpret_cast<Handle>(fCurBlock.fBlock.get() + fCurBlockUsed);
+ fCurBlockUsed += size;
+ fCurBlock.fEventsInBlock++;
+ return handle;
+}
+
+SkEventTracer::Handle ChromeTracingTracer::addTraceEvent(char phase,
+ const uint8_t* categoryEnabledFlag,
+ const char* name,
+ uint64_t id,
+ int numArgs,
+ const char** argNames,
+ const uint8_t* argTypes,
+ const uint64_t* argValues,
+ uint8_t flags) {
+ // TODO: Respect flags (or assert). INSTANT events encode scope in flags, should be stored
+ // using "s" key in JSON. COPY flag should be supported or rejected.
+
+ // Figure out how much extra storage we need for copied strings
+ int size = static_cast<int>(sizeof(TraceEvent) + numArgs * sizeof(TraceEventArg));
+ for (int i = 0; i < numArgs; ++i) {
+ if (TRACE_VALUE_TYPE_COPY_STRING == argTypes[i]) {
+ skia::tracing_internals::TraceValueUnion value;
+ value.as_uint = argValues[i];
+ size += strlen(value.as_string) + 1;
+ }
+ }
+
+ size = SkAlign8(size);
+
+ SkSTArray<128, uint8_t, true> storage;
+ uint8_t* storagePtr = storage.push_back_n(size);
+
+ TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(storagePtr);
+ traceEvent->fPhase = phase;
+ traceEvent->fNumArgs = numArgs;
+ traceEvent->fSize = size;
+ traceEvent->fName = name;
+ traceEvent->fID = id;
+ traceEvent->fClockBegin = std::chrono::steady_clock::now().time_since_epoch().count();
+ traceEvent->fClockEnd = 0;
+ traceEvent->fThreadID = SkGetThreadID();
+
+ TraceEventArg* traceEventArgs = traceEvent->args();
+ char* stringTableBase = traceEvent->stringTable();
+ char* stringTable = stringTableBase;
+ for (int i = 0; i < numArgs; ++i) {
+ traceEventArgs[i].fArgName = argNames[i];
+ traceEventArgs[i].fArgType = argTypes[i];
+ if (TRACE_VALUE_TYPE_COPY_STRING == argTypes[i]) {
+ // Just write an offset into the arguments array
+ traceEventArgs[i].fArgValue = stringTable - stringTableBase;
+
+ // Copy string into our buffer (and advance)
+ skia::tracing_internals::TraceValueUnion value;
+ value.as_uint = argValues[i];
+ while (*value.as_string) {
+ *stringTable++ = *value.as_string++;
+ }
+ *stringTable++ = 0;
+ } else {
+ traceEventArgs[i].fArgValue = argValues[i];
+ }
+ }
+
+ return this->appendEvent(storagePtr, size);
+}
+
+void ChromeTracingTracer::updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+ const char* name,
+ SkEventTracer::Handle handle) {
+ // We could probably get away with not locking here, but let's be totally safe.
+ SkAutoSpinlock lock(fMutex);
+ TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(handle);
+ traceEvent->fClockEnd = std::chrono::steady_clock::now().time_since_epoch().count();
+}
+
+static void trace_value_to_json(SkJSONWriter* writer,
+ uint64_t argValue,
+ uint8_t argType,
+ const char* stringTableBase) {
+ skia::tracing_internals::TraceValueUnion value;
+ value.as_uint = argValue;
+
+ switch (argType) {
+ case TRACE_VALUE_TYPE_BOOL: writer->appendBool(value.as_bool); break;
+ case TRACE_VALUE_TYPE_UINT: writer->appendU64(value.as_uint); break;
+ case TRACE_VALUE_TYPE_INT: writer->appendS64(value.as_int); break;
+ case TRACE_VALUE_TYPE_DOUBLE: writer->appendDouble(value.as_double); break;
+ case TRACE_VALUE_TYPE_POINTER: writer->appendPointer(value.as_pointer); break;
+ case TRACE_VALUE_TYPE_STRING: writer->appendString(value.as_string); break;
+ case TRACE_VALUE_TYPE_COPY_STRING:
+ writer->appendString(stringTableBase + value.as_uint);
+ break;
+ default: writer->appendString("<unknown type>"); break;
+ }
+}
+
+namespace {
+
+struct TraceEventSerializationState {
+ TraceEventSerializationState(uint64_t clockOffset)
+ : fClockOffset(clockOffset), fNextThreadID(0) {}
+
+ int getShortThreadID(SkThreadID id) {
+ if (int* shortIDPtr = fShortThreadIDMap.find(id)) {
+ return *shortIDPtr;
+ }
+ int shortID = fNextThreadID++;
+ fShortThreadIDMap.set(id, shortID);
+ return shortID;
+ }
+
+ uint64_t fClockOffset;
+ SkTHashMap<uint64_t, const char*> fBaseTypeResolver;
+ int fNextThreadID;
+ SkTHashMap<SkThreadID, int> fShortThreadIDMap;
+};
+
+} // namespace
+
+static void trace_event_to_json(SkJSONWriter* writer,
+ TraceEvent* traceEvent,
+ TraceEventSerializationState* serializationState) {
+ // We track the original (creation time) "name" of each currently live object, so we can
+ // automatically insert "base_name" fields in object snapshot events.
+ auto baseTypeResolver = &(serializationState->fBaseTypeResolver);
+ if (TRACE_EVENT_PHASE_CREATE_OBJECT == traceEvent->fPhase) {
+ SkASSERT(nullptr == baseTypeResolver->find(traceEvent->fID));
+ baseTypeResolver->set(traceEvent->fID, traceEvent->fName);
+ } else if (TRACE_EVENT_PHASE_DELETE_OBJECT == traceEvent->fPhase) {
+ SkASSERT(nullptr != baseTypeResolver->find(traceEvent->fID));
+ baseTypeResolver->remove(traceEvent->fID);
+ }
+
+ writer->beginObject();
+
+ char phaseString[2] = {traceEvent->fPhase, 0};
+ writer->appendString("ph", phaseString);
+ writer->appendString("name", traceEvent->fName);
+ if (0 != traceEvent->fID) {
+ // IDs are (almost) always pointers
+ writer->appendPointer("id", reinterpret_cast<void*>(traceEvent->fID));
+ }
+
+ // Offset timestamps to reduce JSON length, then convert nanoseconds to microseconds
+ // (standard time unit for tracing JSON files).
+ uint64_t relativeTimestamp =
+ static_cast<int64_t>(traceEvent->fClockBegin - serializationState->fClockOffset);
+ writer->appendDouble("ts", static_cast<double>(relativeTimestamp) * 1E-3);
+ if (0 != traceEvent->fClockEnd) {
+ double dur = static_cast<double>(traceEvent->fClockEnd - traceEvent->fClockBegin) * 1E-3;
+ writer->appendDouble("dur", dur);
+ }
+
+ writer->appendS64("tid", serializationState->getShortThreadID(traceEvent->fThreadID));
+ // Trace events *must* include a process ID, but for internal tools this isn't particularly
+ // important (and certainly not worth adding a cross-platform API to get it).
+ writer->appendS32("pid", 0);
+
+ if (traceEvent->fNumArgs) {
+ writer->beginObject("args");
+ const char* stringTable = traceEvent->stringTable();
+ bool addedSnapshot = false;
+ if (TRACE_EVENT_PHASE_SNAPSHOT_OBJECT == traceEvent->fPhase &&
+ baseTypeResolver->find(traceEvent->fID) &&
+ 0 != strcmp(*baseTypeResolver->find(traceEvent->fID), traceEvent->fName)) {
+ // Special handling for snapshots where the name differs from creation.
+ writer->beginObject("snapshot");
+ writer->appendString("base_type", *baseTypeResolver->find(traceEvent->fID));
+ addedSnapshot = true;
+ }
+
+ for (int i = 0; i < traceEvent->fNumArgs; ++i) {
+ const TraceEventArg* arg = traceEvent->args() + i;
+ // TODO: Skip '#'
+ writer->appendName(arg->fArgName);
+
+ if (arg->fArgName && '#' == arg->fArgName[0]) {
+ writer->beginObject();
+ writer->appendName("id_ref");
+ trace_value_to_json(writer, arg->fArgValue, arg->fArgType, stringTable);
+ writer->endObject();
+ } else {
+ trace_value_to_json(writer, arg->fArgValue, arg->fArgType, stringTable);
+ }
+ }
+
+ if (addedSnapshot) {
+ writer->endObject();
+ }
+
+ writer->endObject();
+ }
+
+ writer->endObject();
+}
+
+void ChromeTracingTracer::flush() {
+ SkAutoSpinlock lock(fMutex);
+
+ SkString dirname = SkOSPath::Dirname(fFilename.c_str());
+ if (!dirname.isEmpty() && !sk_exists(dirname.c_str(), kWrite_SkFILE_Flag)) {
+ if (!sk_mkdir(dirname.c_str())) {
+ SkDebugf("Failed to create directory.");
+ }
+ }
+
+ SkFILEWStream fileStream(fFilename.c_str());
+ SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kFast);
+ writer.beginArray();
+
+ uint64_t clockOffset = 0;
+ if (fBlocks.count() > 0) {
+ clockOffset = reinterpret_cast<TraceEvent*>(fBlocks[0].fBlock.get())->fClockBegin;
+ } else if (fCurBlock.fEventsInBlock > 0) {
+ clockOffset = reinterpret_cast<TraceEvent*>(fCurBlock.fBlock.get())->fClockBegin;
+ }
+
+ TraceEventSerializationState serializationState(clockOffset);
+
+ auto event_block_to_json = [](SkJSONWriter* writer,
+ const TraceEventBlock& block,
+ TraceEventSerializationState* serializationState) {
+ TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(block.fBlock.get());
+ for (int i = 0; i < block.fEventsInBlock; ++i) {
+ trace_event_to_json(writer, traceEvent, serializationState);
+ traceEvent = traceEvent->next();
+ }
+ };
+
+ for (int i = 0; i < fBlocks.count(); ++i) {
+ event_block_to_json(&writer, fBlocks[i], &serializationState);
+ }
+ event_block_to_json(&writer, fCurBlock, &serializationState);
+
+ writer.endArray();
+ writer.flush();
+ fileStream.flush();
+}
diff --git a/src/third_party/skia/tools/trace/ChromeTracingTracer.h b/src/third_party/skia/tools/trace/ChromeTracingTracer.h
new file mode 100644
index 0000000..56eed32
--- /dev/null
+++ b/src/third_party/skia/tools/trace/ChromeTracingTracer.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef ChromeTracingTracer_DEFINED
+#define ChromeTracingTracer_DEFINED
+
+#include "include/core/SkString.h"
+#include "include/private/SkSpinlock.h"
+#include "include/private/SkTHash.h"
+#include "include/utils/SkEventTracer.h"
+#include "tools/trace/EventTracingPriv.h"
+
+class SkJSONWriter;
+
+/**
+ * A SkEventTracer implementation that logs events to JSON for viewing with chrome://tracing.
+ */
+class ChromeTracingTracer : public SkEventTracer {
+public:
+ ChromeTracingTracer(const char* filename);
+ ~ChromeTracingTracer() override;
+
+ SkEventTracer::Handle addTraceEvent(char phase,
+ const uint8_t* categoryEnabledFlag,
+ const char* name,
+ uint64_t id,
+ int numArgs,
+ const char** argNames,
+ const uint8_t* argTypes,
+ const uint64_t* argValues,
+ uint8_t flags) override;
+
+ void updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+ const char* name,
+ SkEventTracer::Handle handle) override;
+
+ const uint8_t* getCategoryGroupEnabled(const char* name) override {
+ return fCategories.getCategoryGroupEnabled(name);
+ }
+
+ const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override {
+ return fCategories.getCategoryGroupName(categoryEnabledFlag);
+ }
+
+private:
+ void flush();
+
+ enum {
+ // Events are variable size, but most commonly 48 bytes, assuming 64-bit pointers and
+ // reasonable packing. This is a first guess at a number that balances memory usage vs.
+ // time overhead of allocating blocks.
+ kBlockSize = 512 * 1024,
+ };
+
+ typedef std::unique_ptr<uint8_t[]> BlockPtr;
+ struct TraceEventBlock {
+ BlockPtr fBlock;
+ int fEventsInBlock;
+ };
+
+ void createBlock();
+
+ Handle appendEvent(const void* data, size_t size);
+
+ SkString fFilename;
+ SkSpinlock fMutex;
+ SkEventTracingCategories fCategories;
+
+ TraceEventBlock fCurBlock;
+ size_t fCurBlockUsed;
+
+ SkTArray<TraceEventBlock> fBlocks;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/trace/EventTracingPriv.cpp b/src/third_party/skia/tools/trace/EventTracingPriv.cpp
new file mode 100644
index 0000000..47a7f52
--- /dev/null
+++ b/src/third_party/skia/tools/trace/EventTracingPriv.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/trace/EventTracingPriv.h"
+
+#include "include/utils/SkEventTracer.h"
+#include "src/core/SkATrace.h"
+#include "src/core/SkTraceEvent.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/trace/ChromeTracingTracer.h"
+#include "tools/trace/SkDebugfTracer.h"
+
+static DEFINE_string(trace,
+ "",
+ "Log trace events in one of several modes:\n"
+ " debugf : Show events using SkDebugf\n"
+ " atrace : Send events to Android ATrace\n"
+ " <filename> : Any other string is interpreted as a filename. Writes\n"
+ " trace events to specified file as JSON, for viewing\n"
+ " with chrome://tracing");
+
+static DEFINE_string(traceMatch,
+ "",
+ "Filter which categories are traced.\n"
+ "Uses same format as --match\n");
+
+void initializeEventTracingForTools(const char* traceFlag) {
+ if (!traceFlag) {
+ if (FLAGS_trace.isEmpty()) {
+ return;
+ }
+ traceFlag = FLAGS_trace[0];
+ }
+
+ SkEventTracer* eventTracer = nullptr;
+ if (0 == strcmp(traceFlag, "atrace")) {
+ eventTracer = new SkATrace();
+ } else if (0 == strcmp(traceFlag, "debugf")) {
+ eventTracer = new SkDebugfTracer();
+ } else {
+ eventTracer = new ChromeTracingTracer(traceFlag);
+ }
+
+ SkAssertResult(SkEventTracer::SetInstance(eventTracer));
+}
+
+uint8_t* SkEventTracingCategories::getCategoryGroupEnabled(const char* name) {
+ static_assert(0 == offsetof(CategoryState, fEnabled), "CategoryState");
+
+ // We ignore the "disabled-by-default-" prefix in our internal tools
+ if (SkStrStartsWith(name, TRACE_CATEGORY_PREFIX)) {
+ name += strlen(TRACE_CATEGORY_PREFIX);
+ }
+
+ // Chrome's implementation of this API does a two-phase lookup (once without a lock, then again
+ // with a lock. But the tracing macros avoid calling these functions more than once per site,
+ // so just do something simple (and easier to reason about):
+ SkAutoMutexExclusive lock(fMutex);
+ for (int i = 0; i < fNumCategories; ++i) {
+ if (0 == strcmp(name, fCategories[i].fName)) {
+ return reinterpret_cast<uint8_t*>(&fCategories[i]);
+ }
+ }
+
+ if (fNumCategories >= kMaxCategories) {
+ SkDEBUGFAIL("Exhausted event tracing categories. Increase kMaxCategories.");
+ return reinterpret_cast<uint8_t*>(&fCategories[0]);
+ }
+
+ fCategories[fNumCategories].fEnabled =
+ CommandLineFlags::ShouldSkip(FLAGS_traceMatch, name)
+ ? 0
+ : SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags;
+
+ fCategories[fNumCategories].fName = name;
+ return reinterpret_cast<uint8_t*>(&fCategories[fNumCategories++]);
+}
+
+const char* SkEventTracingCategories::getCategoryGroupName(const uint8_t* categoryEnabledFlag) {
+ if (categoryEnabledFlag) {
+ return reinterpret_cast<const CategoryState*>(categoryEnabledFlag)->fName;
+ }
+ return nullptr;
+}
diff --git a/src/third_party/skia/tools/trace/EventTracingPriv.h b/src/third_party/skia/tools/trace/EventTracingPriv.h
new file mode 100644
index 0000000..44fc9f4
--- /dev/null
+++ b/src/third_party/skia/tools/trace/EventTracingPriv.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef EventTracingPriv_DEFINED
+#define EventTracingPriv_DEFINED
+
+#include "include/private/SkMutex.h"
+
+/**
+ * Construct and install an SkEventTracer, based on the mode,
+ * defaulting to the --trace command line argument.
+ */
+void initializeEventTracingForTools(const char* mode = nullptr);
+
+/**
+ * Helper class used by internal implementations of SkEventTracer to manage categories.
+ */
+class SkEventTracingCategories {
+public:
+ SkEventTracingCategories() : fNumCategories(0) {}
+
+ uint8_t* getCategoryGroupEnabled(const char* name);
+ const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag);
+
+private:
+ enum { kMaxCategories = 256 };
+
+ struct CategoryState {
+ uint8_t fEnabled;
+ const char* fName;
+ };
+
+ CategoryState fCategories[kMaxCategories];
+ int fNumCategories;
+ SkMutex fMutex;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/trace/SkDebugfTracer.cpp b/src/third_party/skia/tools/trace/SkDebugfTracer.cpp
index 272af78..bd2feea 100644
--- a/src/third_party/skia/tools/trace/SkDebugfTracer.cpp
+++ b/src/third_party/skia/tools/trace/SkDebugfTracer.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#include "SkDebugfTracer.h"
-#include "SkTraceEvent.h"
+#include "src/core/SkTraceEvent.h"
+#include "tools/trace/SkDebugfTracer.h"
SkEventTracer::Handle SkDebugfTracer::addTraceEvent(char phase,
const uint8_t* categoryEnabledFlag,
@@ -24,11 +24,11 @@
} else {
args.append(" ");
}
+ skia::tracing_internals::TraceValueUnion value;
+ value.as_uint = argValues[i];
switch (argTypes[i]) {
case TRACE_VALUE_TYPE_BOOL:
- args.appendf("%s=%s",
- argNames[i],
- (*reinterpret_cast<bool*>(argValues[i]) ? "true" : "false"));
+ args.appendf("%s=%s", argNames[i], value.as_bool ? "true" : "false");
break;
case TRACE_VALUE_TYPE_UINT:
args.appendf("%s=%u", argNames[i], static_cast<uint32_t>(argValues[i]));
@@ -37,16 +37,15 @@
args.appendf("%s=%d", argNames[i], static_cast<int32_t>(argValues[i]));
break;
case TRACE_VALUE_TYPE_DOUBLE:
- args.appendf("%s=%g", argNames[i], *SkTCast<const double*>(&argValues[i]));
+ args.appendf("%s=%g", argNames[i], value.as_double);
break;
case TRACE_VALUE_TYPE_POINTER:
- args.appendf("%s=0x%p", argNames[i], reinterpret_cast<void*>(argValues[i]));
+ args.appendf("%s=0x%p", argNames[i], value.as_pointer);
break;
case TRACE_VALUE_TYPE_STRING:
case TRACE_VALUE_TYPE_COPY_STRING: {
static constexpr size_t kMaxLen = 20;
- const char* str = reinterpret_cast<const char*>(argValues[i]);
- SkString string(str);
+ SkString string(value.as_string);
size_t truncAt = string.size();
size_t newLineAt = SkStrFind(string.c_str(), "\n");
if (newLineAt > 0) {
@@ -67,8 +66,9 @@
}
bool open = (phase == TRACE_EVENT_PHASE_COMPLETE);
if (open) {
- SkDebugf(
- "[% 2d]%s %s%s #%d {\n", fIndent.size(), fIndent.c_str(), name, args.c_str(), fCnt);
+ const char* category = this->getCategoryGroupName(categoryEnabledFlag);
+ SkDebugf("[% 2d]%s <%s> %s%s #%d {\n", fIndent.size(), fIndent.c_str(), category, name,
+ args.c_str(), fCnt);
fIndent.append(" ");
} else {
SkDebugf("%s%s #%d\n", name, args.c_str(), fCnt);
@@ -83,8 +83,3 @@
fIndent.resize(fIndent.size() - 1);
SkDebugf("[% 2d]%s } %s\n", fIndent.size(), fIndent.c_str(), name);
}
-
-const uint8_t* SkDebugfTracer::getCategoryGroupEnabled(const char* name) {
- static uint8_t yes = SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags;
- return &yes;
-}
diff --git a/src/third_party/skia/tools/trace/SkDebugfTracer.h b/src/third_party/skia/tools/trace/SkDebugfTracer.h
index 4350d1a..bd19f51 100644
--- a/src/third_party/skia/tools/trace/SkDebugfTracer.h
+++ b/src/third_party/skia/tools/trace/SkDebugfTracer.h
@@ -8,8 +8,9 @@
#ifndef SkDebugfTracer_DEFINED
#define SkDebugfTracer_DEFINED
-#include "SkEventTracer.h"
-#include "SkString.h"
+#include "include/core/SkString.h"
+#include "include/utils/SkEventTracer.h"
+#include "tools/trace/EventTracingPriv.h"
/**
* A SkEventTracer implementation that logs events using SkDebugf.
@@ -32,16 +33,18 @@
const char* name,
SkEventTracer::Handle handle) override;
- const uint8_t* getCategoryGroupEnabled(const char* name) override;
+ const uint8_t* getCategoryGroupEnabled(const char* name) override {
+ return fCategories.getCategoryGroupEnabled(name);
+ }
const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override {
- static const char* category = "category?";
- return category;
+ return fCategories.getCategoryGroupName(categoryEnabledFlag);
}
private:
SkString fIndent;
int fCnt = 0;
+ SkEventTracingCategories fCategories;
};
#endif
diff --git a/src/third_party/skia/tools/using_skia_and_harfbuzz.cpp b/src/third_party/skia/tools/using_skia_and_harfbuzz.cpp
index d405c71..03fcf30 100644
--- a/src/third_party/skia/tools/using_skia_and_harfbuzz.cpp
+++ b/src/third_party/skia/tools/using_skia_and_harfbuzz.cpp
@@ -16,12 +16,12 @@
#include <string>
#include <vector>
-#include "SkCanvas.h"
-#include "SkDocument.h"
-#include "SkShaper.h"
-#include "SkStream.h"
-#include "SkTextBlob.h"
-#include "SkTypeface.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTextBlob.h"
+#include "include/core/SkTypeface.h"
+#include "include/docs/SkPDFDocument.h"
+#include "modules/skshaper/include/SkShaper.h"
// Options /////////////////////////////////////////////////////////////////////
@@ -42,8 +42,8 @@
template <class T>
struct Option : BaseOption {
T value;
- Option(std::string selector, std::string description, T defaultValue)
- : BaseOption(selector, description), value(defaultValue) {}
+ Option(std::string _selector, std::string _description, T defaultValue)
+ : BaseOption(_selector, _description), value(defaultValue) {}
};
void BaseOption::Init(const std::vector<BaseOption*> &option_list,
@@ -83,19 +83,19 @@
stm << value;
return stm.str();
}
- DoubleOption(std::string selector,
- std::string description,
+ DoubleOption(std::string _selector,
+ std::string _description,
double defaultValue)
- : Option<double>(selector, description, defaultValue) {}
+ : Option<double>(_selector, _description, defaultValue) {}
};
struct StringOption : Option<std::string> {
virtual void set(std::string _value) { value = _value; }
virtual std::string valueToString() { return value; }
- StringOption(std::string selector,
- std::string description,
+ StringOption(std::string _selector,
+ std::string _description,
std::string defaultValue)
- : Option<std::string>(selector, description, defaultValue) {}
+ : Option<std::string>(_selector, _description, defaultValue) {}
};
// Config //////////////////////////////////////////////////////////////////////
@@ -112,7 +112,7 @@
DoubleOption font_size = DoubleOption("-z", "Font size", 8.0f);
DoubleOption left_margin = DoubleOption("-m", "Left margin", 20.0f);
DoubleOption line_spacing_ratio =
- DoubleOption("-h", "Line spacing ratio", 1.5f);
+ DoubleOption("-h", "Line spacing ratio", 0.25f);
StringOption output_file_name =
StringOption("-o", ".pdf output file name", "out-skiahf.pdf");
@@ -132,13 +132,23 @@
: config(conf), document(doc), pageCanvas(nullptr) {
white_paint.setColor(SK_ColorWHITE);
glyph_paint.setColor(SK_ColorBLACK);
- glyph_paint.setFlags(SkPaint::kAntiAlias_Flag |
- SkPaint::kSubpixelText_Flag);
- glyph_paint.setTextSize(SkDoubleToScalar(config->font_size.value));
+ glyph_paint.setAntiAlias(true);
+ font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ font.setSubpixel(true);
+ font.setSize(SkDoubleToScalar(config->font_size.value));
}
void WriteLine(const SkShaper& shaper, const char *text, size_t textBytes) {
- if (!pageCanvas || current_y > config->page_height.value) {
+ SkTextBlobBuilderRunHandler textBlobBuilder(text, {0, 0});
+ shaper.shape(text, textBytes, font, true,
+ config->page_width.value - 2*config->left_margin.value, &textBlobBuilder);
+ SkPoint endPoint = textBlobBuilder.endPoint();
+ sk_sp<const SkTextBlob> blob = textBlobBuilder.makeBlob();
+ // If we don't have a page, or if we're not at the start of the page and the blob won't fit
+ if (!pageCanvas ||
+ (current_y > config->line_spacing_ratio.value * config->font_size.value &&
+ current_y + endPoint.y() > config->page_height.value)
+ ) {
if (pageCanvas) {
document->endPage();
}
@@ -149,14 +159,11 @@
current_x = config->left_margin.value;
current_y = config->line_spacing_ratio.value * config->font_size.value;
}
- SkTextBlobBuilder textBlobBuilder;
- shaper.shape(&textBlobBuilder, glyph_paint, text, textBytes, SkPoint{0, 0});
- sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
pageCanvas->drawTextBlob(
blob.get(), SkDoubleToScalar(current_x),
SkDoubleToScalar(current_y), glyph_paint);
// Advance to the next line.
- current_y += config->line_spacing_ratio.value * config->font_size.value;
+ current_y += endPoint.y() + config->line_spacing_ratio.value * config->font_size.value;
}
private:
@@ -165,32 +172,28 @@
SkCanvas *pageCanvas;
SkPaint white_paint;
SkPaint glyph_paint;
+ SkFont font;
double current_x;
double current_y;
};
////////////////////////////////////////////////////////////////////////////////
-static sk_sp<SkDocument> MakePDFDocument(const Config &config,
- SkWStream *wStream) {
- SkDocument::PDFMetadata pdf_info;
+static sk_sp<SkDocument> MakePDFDocument(const Config &config, SkWStream *wStream) {
+ SkPDF::Metadata pdf_info;
pdf_info.fTitle = config.title.value.c_str();
pdf_info.fAuthor = config.author.value.c_str();
pdf_info.fSubject = config.subject.value.c_str();
pdf_info.fKeywords = config.keywords.value.c_str();
pdf_info.fCreator = config.creator.value.c_str();
- bool pdfa = false;
#if 0
SkTime::DateTime now;
SkTime::GetDateTime(&now);
- pdf_info.fCreation.fEnabled = true;
- pdf_info.fCreation.fDateTime = now;
- pdf_info.fModified.fEnabled = true;
- pdf_info.fModified.fDateTime = now;
- pdfa = true;
+ pdf_info.fCreation = now;
+ pdf_info.fModified = now;
+ pdf_info.fPDFA = true;
#endif
- return SkDocument::MakePDF(wStream, SK_ScalarDefaultRasterDPI, pdf_info,
- nullptr, pdfa);
+ return SkPDF::MakeDocument(wStream, pdf_info);
}
int main(int argc, char **argv) {
@@ -205,12 +208,15 @@
if (font_file.size() > 0) {
typeface = SkTypeface::MakeFromFile(font_file.c_str(), 0 /* index */);
}
- SkShaper shaper(typeface);
- assert(shaper.good());
+ std::unique_ptr<SkShaper> shaper = SkShaper::Make();
+ assert(shaper);
+ //SkString line("This is هذا هو الخط a line.");
+ //SkString line("This is a line هذا هو الخط.");
for (std::string line; std::getline(std::cin, line);) {
- placement.WriteLine(shaper, line.c_str(), line.size());
+ placement.WriteLine(*shaper, line.c_str(), line.size());
}
doc->close();
+ wStream.flush();
return 0;
}
diff --git a/src/third_party/skia/tools/valgrind.supp b/src/third_party/skia/tools/valgrind.supp
index 064f8ef..20f1a7d 100644
--- a/src/third_party/skia/tools/valgrind.supp
+++ b/src/third_party/skia/tools/valgrind.supp
@@ -6,7 +6,7 @@
Memcheck:Leak
match-leak-kinds: possible,definite
...
- fun:_ZN8SkThreadC1EPFvPvES0_
+ fun:start_keepalive
...
fun:main
...
@@ -101,6 +101,12 @@
obj:*/libGLX_nvidia.so*
}
{
+ nv_driver_bug_5
+ Memcheck:Leak
+ fun:malloc
+ obj:*/libGLX_nvidia.so*
+}
+{
#Fixed by FontConfig 2.9.0
#http://cgit.freedesktop.org/fontconfig/commit/?id=1c475d5c8cb265ac939d6b9e097666e300162511
font_config_bug_1
@@ -276,3 +282,22 @@
fun:_ZN12_GLOBAL__N_120ConvolveHorizontallyILb0EEEvPKhRK21SkConvolutionFilter1DPh
fun:_Z14BGRAConvolve2DPKhibRK21SkConvolutionFilter1DS3_iPhRK18SkConvolutionProcsb
}
+#Something odd happening in with SkRasterPipeline in GrConvertPixels. Seems bogus after
+#investigation. MSAN/ASAN have no complaints. Complaining about conditional jump or use
+#of var that is "uninitialized" but it definitely is.
+{
+ grconvertpixels_rasterpipeline
+ Memcheck:Cond
+ ...
+ fun:_ZNK16SkRasterPipeline3runEmmmm
+ fun:_Z15GrConvertPixelsRK11GrImageInfoPvmS1_PKvmb
+ ...
+}
+{
+ grconvertpixels_rasterpipeline
+ Memcheck:Value8
+ ...
+ fun:_ZNK16SkRasterPipeline3runEmmmm
+ fun:_Z15GrConvertPixelsRK11GrImageInfoPvmS1_PKvmb
+ ...
+}
diff --git a/src/third_party/skia/tools/viewer/AnimTimer.h b/src/third_party/skia/tools/viewer/AnimTimer.h
new file mode 100644
index 0000000..93d0077
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/AnimTimer.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkScalar.h"
+#include "include/core/SkTime.h"
+
+#ifndef AnimTimer_DEFINED
+#define AnimTimer_DEFINED
+
+/**
+ * Class to track a "timer". It supports 3 states: stopped, paused, and running.
+ * Playback speed is variable.
+ *
+ * The caller must call updateTime() to resync with the clock (typically just before
+ * using the timer). Forcing the caller to do this ensures that the timer's return values
+ * are consistent if called repeatedly, as they only reflect the time since the last
+ * calle to updateTimer().
+ */
+class AnimTimer {
+public:
+ /**
+ * Class begins in the "stopped" state.
+ */
+ AnimTimer() {}
+
+ enum State { kStopped_State, kPaused_State, kRunning_State };
+
+ State state() const { return fState; }
+
+ double nanos() const { return fElapsedNanos; }
+
+ /**
+ * Control the rate at which time advances.
+ */
+ float getSpeed() const { return fSpeed; }
+ void setSpeed(float speed) { fSpeed = speed; }
+
+ /**
+ * If the timer is paused or stopped, it will resume (or start if it was stopped).
+ */
+ void run() {
+ switch (this->state()) {
+ case kStopped_State:
+ fPreviousNanos = SkTime::GetNSecs();
+ fElapsedNanos = 0;
+ break;
+ case kPaused_State: // they want "resume"
+ fPreviousNanos = SkTime::GetNSecs();
+ break;
+ case kRunning_State: break;
+ }
+ fState = kRunning_State;
+ }
+
+ void pause() {
+ if (kRunning_State == this->state()) {
+ fState = kPaused_State;
+ } // else stay stopped or paused
+ }
+
+ /**
+ * If the timer is stopped, start running, else it toggles between paused and running.
+ */
+ void togglePauseResume() {
+ if (kRunning_State == this->state()) {
+ this->pause();
+ } else {
+ this->run();
+ }
+ }
+
+ /**
+ * Call this each time you want to sample the clock for the timer. This is NOT done
+ * automatically, so that repeated calls to msec() or secs() will always return the
+ * same value.
+ *
+ * This may safely be called with the timer in any state.
+ */
+ void updateTime() {
+ if (kRunning_State == this->state()) {
+ double now = SkTime::GetNSecs();
+ fElapsedNanos += (now - fPreviousNanos) * fSpeed;
+ fPreviousNanos = now;
+ }
+ }
+
+private:
+ double fPreviousNanos = 0;
+ double fElapsedNanos = 0;
+ float fSpeed = 1;
+ State fState = kStopped_State;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/BisectSlide.cpp b/src/third_party/skia/tools/viewer/BisectSlide.cpp
new file mode 100644
index 0000000..fa2bed9
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/BisectSlide.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/viewer/BisectSlide.h"
+
+#include "include/core/SkPicture.h"
+#include "include/core/SkStream.h"
+#include "src/utils/SkOSPath.h"
+
+#include <utility>
+
+#ifdef SK_XML
+#include "experimental/svg/model/SkSVGDOM.h"
+#include "src/xml/SkDOM.h"
+#endif
+
+sk_sp<BisectSlide> BisectSlide::Create(const char filepath[]) {
+ SkFILEStream stream(filepath);
+ if (!stream.isValid()) {
+ SkDebugf("BISECT: invalid input file at \"%s\"\n", filepath);
+ return nullptr;
+ }
+
+ sk_sp<BisectSlide> bisect(new BisectSlide(filepath));
+ if (bisect->fFilePath.endsWith(".svg")) {
+#ifdef SK_XML
+ SkDOM xml;
+ if (!xml.build(stream)) {
+ SkDebugf("BISECT: XML parsing failed: \"%s\"\n", filepath);
+ return nullptr;
+ }
+ sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromDOM(xml);
+ if (!svg) {
+ SkDebugf("BISECT: couldn't load svg at \"%s\"\n", filepath);
+ return nullptr;
+ }
+ svg->setContainerSize(SkSize::Make(bisect->getDimensions()));
+ svg->render(bisect.get());
+#else
+ return nullptr;
+#endif
+ } else {
+ sk_sp<SkPicture> skp = SkPicture::MakeFromStream(&stream);
+ if (!skp) {
+ SkDebugf("BISECT: couldn't load skp at \"%s\"\n", filepath);
+ return nullptr;
+ }
+ skp->playback(bisect.get());
+ }
+
+ return bisect;
+}
+
+BisectSlide::BisectSlide(const char filepath[])
+ : SkCanvas(4096, 4096, nullptr)
+ , fFilePath(filepath) {
+ const char* basename = strrchr(fFilePath.c_str(), SkOSPath::SEPARATOR);
+ fName.printf("BISECT_%s", basename ? basename + 1 : fFilePath.c_str());
+}
+
+// Called through SkPicture::playback only during creation.
+void BisectSlide::onDrawPath(const SkPath& path, const SkPaint& paint) {
+ SkRect bounds;
+ SkIRect ibounds;
+ this->getTotalMatrix().mapRect(&bounds, path.getBounds());
+ bounds.roundOut(&ibounds);
+ fDrawBounds.join(ibounds);
+ fFoundPaths.push_back() = {path, paint, this->getTotalMatrix()};
+}
+
+bool BisectSlide::onChar(SkUnichar c) {
+ switch (c) {
+ case 'X':
+ if (!fTossedPaths.empty()) {
+ using std::swap;
+ swap(fFoundPaths, fTossedPaths);
+ if ('X' == fTrail.back()) {
+ fTrail.pop_back();
+ } else {
+ fTrail.push_back('X');
+ }
+ }
+ return true;
+
+ case 'x':
+ if (fFoundPaths.count() > 1) {
+ int midpt = (fFoundPaths.count() + 1) / 2;
+ fPathHistory.emplace(fFoundPaths, fTossedPaths);
+ fTossedPaths.reset(fFoundPaths.begin() + midpt, fFoundPaths.count() - midpt);
+ fFoundPaths.resize_back(midpt);
+ fTrail.push_back('x');
+ }
+ return true;
+
+ case 'Z': {
+ if (!fPathHistory.empty()) {
+ fFoundPaths = fPathHistory.top().first;
+ fTossedPaths = fPathHistory.top().second;
+ fPathHistory.pop();
+ char ch;
+ do {
+ ch = fTrail.back();
+ fTrail.pop_back();
+ } while (ch != 'x');
+ }
+ return true;
+ }
+
+ case 'D':
+ SkDebugf("viewer --bisect %s", fFilePath.c_str());
+ if (!fTrail.empty()) {
+ SkDebugf(" ");
+ for (char ch : fTrail) {
+ SkDebugf("%c", ch);
+ }
+ }
+ SkDebugf("\n");
+ for (const FoundPath& foundPath : fFoundPaths) {
+ foundPath.fPath.dump();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void BisectSlide::draw(SkCanvas* canvas) {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(-fDrawBounds.left(), -fDrawBounds.top());
+
+ for (const FoundPath& path : fFoundPaths) {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(path.fViewMatrix);
+ canvas->drawPath(path.fPath, path.fPaint);
+ }
+}
diff --git a/src/third_party/skia/tools/viewer/BisectSlide.h b/src/third_party/skia/tools/viewer/BisectSlide.h
new file mode 100644
index 0000000..142209c
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/BisectSlide.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef BisectSlide_DEFINED
+#define BisectSlide_DEFINED
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkPath.h"
+#include "tools/viewer/Slide.h"
+
+#include <stack>
+
+/**
+ * This is a simple utility designed to extract the paths from an SKP file and then isolate a single
+ * one of them via bisect. Use the 'x' and 'X' keys to guide a binary search:
+ *
+ * 'x': Throw out half the paths.
+ * 'X': Toggle which half gets tossed and which half is kept.
+ * 'Z': Back up one level.
+ * 'D': Dump the path.
+ */
+class BisectSlide : public Slide, public SkCanvas {
+public:
+ static sk_sp<BisectSlide> Create(const char filepath[]);
+
+ // Slide overrides.
+ SkISize getDimensions() const override { return fDrawBounds.size(); }
+ bool onChar(SkUnichar c) override;
+ void draw(SkCanvas* canvas) override;
+
+private:
+ BisectSlide(const char filepath[]);
+
+ // SkCanvas override called only during creation.
+ void onDrawPath(const SkPath& path, const SkPaint& paint) override;
+
+ struct FoundPath {
+ SkPath fPath;
+ SkPaint fPaint;
+ SkMatrix fViewMatrix;
+ };
+
+ SkString fFilePath;
+ SkIRect fDrawBounds = SkIRect::MakeEmpty();
+ SkTArray<FoundPath> fFoundPaths;
+ SkTArray<FoundPath> fTossedPaths;
+ SkTArray<char> fTrail;
+ std::stack<std::pair<SkTArray<FoundPath>, SkTArray<FoundPath>>> fPathHistory;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/GMSlide.cpp b/src/third_party/skia/tools/viewer/GMSlide.cpp
index 40a9c99..24d8421 100644
--- a/src/third_party/skia/tools/viewer/GMSlide.cpp
+++ b/src/third_party/skia/tools/viewer/GMSlide.cpp
@@ -11,14 +11,14 @@
* found in the LICENSE file.
*/
-#include "GMSlide.h"
-#include "SkCanvas.h"
+#include "include/core/SkCanvas.h"
+#include "tools/viewer/GMSlide.h"
-GMSlide::GMSlide(skiagm::GM* gm) : fGM(gm) {
- fName.printf("GM_%s", gm->getName());
+GMSlide::GMSlide(std::unique_ptr<skiagm::GM> gm) : fGM(std::move(gm)) {
+ fName.printf("GM_%s", fGM->getName());
}
-GMSlide::~GMSlide() { delete fGM; }
+GMSlide::~GMSlide() = default;
void GMSlide::draw(SkCanvas* canvas) {
// Do we care about timing the draw of the background (once)?
@@ -27,10 +27,15 @@
fGM->drawContent(canvas);
}
-bool GMSlide::animate(const SkAnimTimer& timer) {
- return fGM->animate(timer);
+bool GMSlide::animate(double nanos) { return fGM->animate(nanos); }
+
+bool GMSlide::onChar(SkUnichar c) { return fGM->onChar(c); }
+
+bool GMSlide::onGetControls(SkMetaData* controls) {
+ return fGM->getControls(controls);
}
-bool GMSlide::onChar(SkUnichar c) {
- return fGM->handleKey(c);
+void GMSlide::onSetControls(const SkMetaData& controls) {
+ fGM->setControls(controls);
}
+
diff --git a/src/third_party/skia/tools/viewer/GMSlide.h b/src/third_party/skia/tools/viewer/GMSlide.h
index 2a3faa9..96d7af9 100644
--- a/src/third_party/skia/tools/viewer/GMSlide.h
+++ b/src/third_party/skia/tools/viewer/GMSlide.h
@@ -8,23 +8,26 @@
#ifndef GMSlide_DEFINED
#define GMSlide_DEFINED
-#include "Slide.h"
-#include "gm.h"
+#include "gm/gm.h"
+#include "tools/viewer/Slide.h"
class GMSlide : public Slide {
public:
- GMSlide(skiagm::GM* gm);
+ GMSlide(std::unique_ptr<skiagm::GM> gm);
~GMSlide() override;
SkISize getDimensions() const override { return fGM->getISize(); }
void draw(SkCanvas* canvas) override;
- bool animate(const SkAnimTimer&) override;
+ bool animate(double nanos) override;
bool onChar(SkUnichar c) override;
+ bool onGetControls(SkMetaData*) override;
+ void onSetControls(const SkMetaData&) override;
+
private:
- skiagm::GM* fGM;
+ std::unique_ptr<skiagm::GM> fGM;
};
diff --git a/src/third_party/skia/tools/viewer/ImGuiLayer.cpp b/src/third_party/skia/tools/viewer/ImGuiLayer.cpp
new file mode 100644
index 0000000..31b3a54
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/ImGuiLayer.cpp
@@ -0,0 +1,202 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "tools/viewer/ImGuiLayer.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkSwizzle.h"
+#include "include/core/SkTime.h"
+#include "include/core/SkVertices.h"
+
+#include "imgui.h"
+
+#include <stdlib.h>
+#include <map>
+
+using namespace sk_app;
+
+ImGuiLayer::ImGuiLayer() {
+ // ImGui initialization:
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Keymap...
+ io.KeyMap[ImGuiKey_Tab] = (int)skui::Key::kTab;
+ io.KeyMap[ImGuiKey_LeftArrow] = (int)skui::Key::kLeft;
+ io.KeyMap[ImGuiKey_RightArrow] = (int)skui::Key::kRight;
+ io.KeyMap[ImGuiKey_UpArrow] = (int)skui::Key::kUp;
+ io.KeyMap[ImGuiKey_DownArrow] = (int)skui::Key::kDown;
+ io.KeyMap[ImGuiKey_PageUp] = (int)skui::Key::kPageUp;
+ io.KeyMap[ImGuiKey_PageDown] = (int)skui::Key::kPageDown;
+ io.KeyMap[ImGuiKey_Home] = (int)skui::Key::kHome;
+ io.KeyMap[ImGuiKey_End] = (int)skui::Key::kEnd;
+ io.KeyMap[ImGuiKey_Delete] = (int)skui::Key::kDelete;
+ io.KeyMap[ImGuiKey_Backspace] = (int)skui::Key::kBack;
+ io.KeyMap[ImGuiKey_Enter] = (int)skui::Key::kOK;
+ io.KeyMap[ImGuiKey_Escape] = (int)skui::Key::kEscape;
+ io.KeyMap[ImGuiKey_A] = (int)skui::Key::kA;
+ io.KeyMap[ImGuiKey_C] = (int)skui::Key::kC;
+ io.KeyMap[ImGuiKey_V] = (int)skui::Key::kV;
+ io.KeyMap[ImGuiKey_X] = (int)skui::Key::kX;
+ io.KeyMap[ImGuiKey_Y] = (int)skui::Key::kY;
+ io.KeyMap[ImGuiKey_Z] = (int)skui::Key::kZ;
+
+ int w, h;
+ unsigned char* pixels;
+ io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
+ SkImageInfo info = SkImageInfo::MakeA8(w, h);
+ SkPixmap pmap(info, pixels, info.minRowBytes());
+ SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
+ auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
+ auto fontShader = fontImage->makeShader(&localMatrix);
+ fFontPaint.setShader(fontShader);
+ fFontPaint.setColor(SK_ColorWHITE);
+ fFontPaint.setFilterQuality(kLow_SkFilterQuality);
+ io.Fonts->TexID = &fFontPaint;
+}
+
+ImGuiLayer::~ImGuiLayer() {
+ ImGui::DestroyContext();
+}
+
+void ImGuiLayer::onAttach(Window* window) {
+ fWindow = window;
+}
+
+bool ImGuiLayer::onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos.x = static_cast<float>(x);
+ io.MousePos.y = static_cast<float>(y);
+ if (skui::InputState::kDown == state) {
+ io.MouseDown[0] = true;
+ } else if (skui::InputState::kUp == state) {
+ io.MouseDown[0] = false;
+ }
+ return io.WantCaptureMouse;
+}
+
+bool ImGuiLayer::onMouseWheel(float delta, skui::ModifierKey modifiers) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseWheel += delta;
+ return true;
+}
+
+void ImGuiLayer::skiaWidget(const ImVec2& size, SkiaWidgetFunc func) {
+ intptr_t funcIndex = fSkiaWidgetFuncs.count();
+ fSkiaWidgetFuncs.push_back(func);
+ ImGui::Image((ImTextureID)funcIndex, size);
+}
+
+void ImGuiLayer::onPrePaint() {
+ // Update ImGui input
+ ImGuiIO& io = ImGui::GetIO();
+
+ static double previousTime = 0.0;
+ double currentTime = SkTime::GetSecs();
+ io.DeltaTime = static_cast<float>(currentTime - previousTime);
+ previousTime = currentTime;
+
+ io.DisplaySize.x = static_cast<float>(fWindow->width());
+ io.DisplaySize.y = static_cast<float>(fWindow->height());
+
+ io.KeyAlt = io.KeysDown[static_cast<int>(skui::Key::kOption)];
+ io.KeyCtrl = io.KeysDown[static_cast<int>(skui::Key::kCtrl)];
+ io.KeyShift = io.KeysDown[static_cast<int>(skui::Key::kShift)];
+
+ ImGui::NewFrame();
+}
+
+void ImGuiLayer::onPaint(SkSurface* surface) {
+ // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
+ // (widgets, etc...) that have been issued
+ ImGui::Render();
+
+ // Then we fetch the most recent data, and convert it so we can render with Skia
+ const ImDrawData* drawData = ImGui::GetDrawData();
+ SkTDArray<SkPoint> pos;
+ SkTDArray<SkPoint> uv;
+ SkTDArray<SkColor> color;
+
+ auto canvas = surface->getCanvas();
+
+ for (int i = 0; i < drawData->CmdListsCount; ++i) {
+ const ImDrawList* drawList = drawData->CmdLists[i];
+
+ // De-interleave all vertex data (sigh), convert to Skia types
+ pos.rewind(); uv.rewind(); color.rewind();
+ for (int j = 0; j < drawList->VtxBuffer.size(); ++j) {
+ const ImDrawVert& vert = drawList->VtxBuffer[j];
+ pos.push_back(SkPoint::Make(vert.pos.x, vert.pos.y));
+ uv.push_back(SkPoint::Make(vert.uv.x, vert.uv.y));
+ color.push_back(vert.col);
+ }
+ // ImGui colors are RGBA
+ SkSwapRB(color.begin(), color.begin(), color.count());
+
+ int indexOffset = 0;
+
+ // Draw everything with canvas.drawVertices...
+ for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
+ const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
+
+ SkAutoCanvasRestore acr(canvas, true);
+
+ // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
+ if (drawCmd->UserCallback) {
+ drawCmd->UserCallback(drawList, drawCmd);
+ } else {
+ intptr_t idIndex = (intptr_t)drawCmd->TextureId;
+ if (idIndex < fSkiaWidgetFuncs.count()) {
+ // Small image IDs are actually indices into a list of callbacks. We directly
+ // examing the vertex data to deduce the image rectangle, then reconfigure the
+ // canvas to be clipped and translated so that the callback code gets to use
+ // Skia to render a widget in the middle of an ImGui panel.
+ ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset];
+ SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2];
+ canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY));
+ canvas->translate(tl.fX, tl.fY);
+ fSkiaWidgetFuncs[idIndex](canvas);
+ } else {
+ SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
+ SkASSERT(paint);
+
+ canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
+ drawCmd->ClipRect.z, drawCmd->ClipRect.w));
+ auto vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
+ drawList->VtxBuffer.size(),
+ pos.begin(), uv.begin(), color.begin(),
+ drawCmd->ElemCount,
+ drawList->IdxBuffer.begin() + indexOffset);
+ canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint);
+ }
+ indexOffset += drawCmd->ElemCount;
+ }
+ }
+ }
+
+ fSkiaWidgetFuncs.reset();
+}
+
+bool ImGuiLayer::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.KeysDown[static_cast<int>(key)] = (skui::InputState::kDown == state);
+ return io.WantCaptureKeyboard;
+}
+
+bool ImGuiLayer::onChar(SkUnichar c, skui::ModifierKey modifiers) {
+ ImGuiIO& io = ImGui::GetIO();
+ if (io.WantTextInput) {
+ if (c > 0 && c < 0x10000) {
+ io.AddInputCharacter(c);
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/src/third_party/skia/tools/viewer/ImGuiLayer.h b/src/third_party/skia/tools/viewer/ImGuiLayer.h
new file mode 100644
index 0000000..827eec0
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/ImGuiLayer.h
@@ -0,0 +1,137 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef ImGuiLayer_DEFINED
+#define ImGuiLayer_DEFINED
+
+#include "include/core/SkPaint.h"
+#include "include/private/SkTArray.h"
+#include "tools/sk_app/Window.h"
+
+#include "imgui.h"
+
+namespace ImGui {
+
+// Helper object for drawing in a widget region, with draggable points
+struct DragCanvas {
+ DragCanvas(const void* id, SkPoint tl = { 0.0f, 0.0f }, SkPoint br = { 1.0f, 1.0f },
+ float aspect = -1.0f)
+ : fID(0), fDragging(false) {
+ ImGui::PushID(id);
+ fDrawList = ImGui::GetWindowDrawList();
+
+ // Logical size
+ SkScalar w = SkTAbs(br.fX - tl.fX),
+ h = SkTAbs(br.fY - tl.fY);
+
+ // Determine aspect ratio automatically by default
+ if (aspect < 0) {
+ aspect = h / w;
+ }
+
+ float availWidth = SkTMax(ImGui::GetContentRegionAvailWidth(), 1.0f);
+ fPos = ImGui::GetCursorScreenPos();
+ fSize = ImVec2(availWidth, availWidth * aspect);
+
+ SkPoint local[4] = {
+ { tl.fX, tl.fY },
+ { br.fX, tl.fY },
+ { tl.fX, br.fY },
+ { br.fX, br.fY },
+ };
+ SkPoint screen[4] = {
+ { fPos.x , fPos.y },
+ { fPos.x + fSize.x, fPos.y },
+ { fPos.x , fPos.y + fSize.y },
+ { fPos.x + fSize.x, fPos.y + fSize.y },
+ };
+ fLocalToScreen.setPolyToPoly(local, screen, 4);
+ fScreenToLocal.setPolyToPoly(screen, local, 4);
+ }
+
+ ~DragCanvas() {
+ ImGui::SetCursorScreenPos(ImVec2(fPos.x, fPos.y + fSize.y));
+ ImGui::Spacing();
+ ImGui::PopID();
+ }
+
+ void fillColor(ImU32 color) {
+ fDrawList->AddRectFilled(fPos, ImVec2(fPos.x + fSize.x, fPos.y + fSize.y), color);
+ }
+
+ void dragPoint(SkPoint* p, bool tooltip = false, ImU32 color = 0xFFFFFFFF) {
+ // Transform points from logical coordinates to screen coordinates
+ SkPoint center = fLocalToScreen.mapXY(p->fX, p->fY);
+
+ // Invisible 10x10 button
+ ImGui::PushID(fID++);
+ ImGui::SetCursorScreenPos(ImVec2(center.fX - 5, center.fY - 5));
+ ImGui::InvisibleButton("", ImVec2(10, 10));
+
+ if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) {
+ // Update screen position to track mouse, clamped to our area
+ ImGuiIO& io = ImGui::GetIO();
+ center.set(SkTPin(io.MousePos.x, fPos.x, fPos.x + fSize.x),
+ SkTPin(io.MousePos.y, fPos.y, fPos.y + fSize.y));
+
+ // Update local coordinates for the caller
+ *p = fScreenToLocal.mapXY(center.fX, center.fY);
+ fDragging = true;
+ }
+
+ if (tooltip && ImGui::IsItemHovered()) {
+ ImGui::SetTooltip("x: %.3f\ny: %.3f", p->fX, p->fY);
+ }
+
+ ImGui::PopID();
+
+ fScreenPoints.push_back(ImVec2(center.fX, center.fY));
+ fDrawList->AddCircle(fScreenPoints.back(), 5.0f, color);
+ }
+
+ ImDrawList* fDrawList;
+
+ // Location and dimensions (in screen coordinates)
+ ImVec2 fPos;
+ ImVec2 fSize;
+
+ // Screen coordinates of points (for additional user drawing)
+ SkSTArray<4, ImVec2, true> fScreenPoints;
+
+ // To simplify dragPoint
+ SkMatrix fLocalToScreen;
+ SkMatrix fScreenToLocal;
+
+ int fID;
+ bool fDragging;
+};
+
+}
+
+class ImGuiLayer : public sk_app::Window::Layer {
+public:
+ ImGuiLayer();
+ ~ImGuiLayer() override;
+
+ typedef std::function<void(SkCanvas*)> SkiaWidgetFunc;
+ void skiaWidget(const ImVec2& size, SkiaWidgetFunc func);
+
+ void onAttach(sk_app::Window* window) override;
+ void onPrePaint() override;
+ void onPaint(SkSurface*) override;
+ bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override;
+ bool onMouseWheel(float delta, skui::ModifierKey modifiers) override;
+ bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override;
+ bool onChar(SkUnichar c, skui::ModifierKey modifiers) override;
+
+private:
+ sk_app::Window* fWindow;
+ SkPaint fFontPaint;
+ SkTArray<SkiaWidgetFunc> fSkiaWidgetFuncs;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/ImageSlide.cpp b/src/third_party/skia/tools/viewer/ImageSlide.cpp
index 8ff7d18..52e5d84 100644
--- a/src/third_party/skia/tools/viewer/ImageSlide.cpp
+++ b/src/third_party/skia/tools/viewer/ImageSlide.cpp
@@ -5,11 +5,11 @@
* found in the LICENSE file.
*/
-#include "ImageSlide.h"
+#include "tools/viewer/ImageSlide.h"
-#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkImage.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkData.h"
+#include "include/core/SkImage.h"
ImageSlide::ImageSlide(const SkString& name, const SkString& path) : fPath(path) {
fName = name;
diff --git a/src/third_party/skia/tools/viewer/ImageSlide.h b/src/third_party/skia/tools/viewer/ImageSlide.h
index d9e3f2d..2246408 100644
--- a/src/third_party/skia/tools/viewer/ImageSlide.h
+++ b/src/third_party/skia/tools/viewer/ImageSlide.h
@@ -8,9 +8,9 @@
#ifndef ImageSlide_DEFINED
#define ImageSlide_DEFINED
-#include "Slide.h"
-#include "SkPicture.h"
-#include "SkImage.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkPicture.h"
+#include "tools/viewer/Slide.h"
class ImageSlide : public Slide {
public:
diff --git a/src/third_party/skia/tools/viewer/ParticlesSlide.cpp b/src/third_party/skia/tools/viewer/ParticlesSlide.cpp
new file mode 100644
index 0000000..4ea33d1
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/ParticlesSlide.cpp
@@ -0,0 +1,438 @@
+/*
+* Copyright 2019 Google LLC
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "tools/viewer/ParticlesSlide.h"
+
+#include "modules/particles/include/SkParticleEffect.h"
+#include "modules/particles/include/SkParticleSerialization.h"
+#include "modules/particles/include/SkReflected.h"
+#include "src/core/SkOSFile.h"
+#include "src/sksl/SkSLByteCode.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/Resources.h"
+#include "tools/viewer/ImGuiLayer.h"
+
+#include "imgui.h"
+
+using namespace sk_app;
+
+namespace {
+
+static SkScalar kDragSize = 8.0f;
+static SkTArray<SkPoint*> gDragPoints;
+int gDragIndex = -1;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int InputTextCallback(ImGuiInputTextCallbackData* data) {
+ if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
+ SkString* s = (SkString*)data->UserData;
+ SkASSERT(data->Buf == s->writable_str());
+ SkString tmp(data->Buf, data->BufTextLen);
+ s->swap(tmp);
+ data->Buf = s->writable_str();
+ }
+ return 0;
+}
+
+static int count_lines(const SkString& s) {
+ int lines = 1;
+ for (size_t i = 0; i < s.size(); ++i) {
+ if (s[i] == '\n') {
+ ++lines;
+ }
+ }
+ return lines;
+}
+
+class SkGuiVisitor : public SkFieldVisitor {
+public:
+ SkGuiVisitor() {
+ fTreeStack.push_back(true);
+ }
+
+#define IF_OPEN(WIDGET) if (fTreeStack.back()) { WIDGET; }
+
+ void visit(const char* name, float& f) override {
+ IF_OPEN(ImGui::DragFloat(item(name), &f))
+ }
+ void visit(const char* name, int& i) override {
+ IF_OPEN(ImGui::DragInt(item(name), &i))
+ }
+ void visit(const char* name, bool& b) override {
+ IF_OPEN(ImGui::Checkbox(item(name), &b))
+ }
+ void visit(const char* name, SkString& s) override {
+ if (fTreeStack.back()) {
+ int lines = count_lines(s);
+ ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
+ if (lines > 1) {
+ ImGui::LabelText("##Label", "%s", name);
+ ImVec2 boxSize(-1.0f, ImGui::GetTextLineHeight() * (lines + 1));
+ ImGui::InputTextMultiline(item(name), s.writable_str(), s.size() + 1, boxSize,
+ flags, InputTextCallback, &s);
+ } else {
+ ImGui::InputText(item(name), s.writable_str(), s.size() + 1, flags,
+ InputTextCallback, &s);
+ }
+ }
+ }
+ void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
+ if (fTreeStack.back()) {
+ const char* curStr = EnumToString(i, map, count);
+ if (ImGui::BeginCombo(item(name), curStr ? curStr : "Unknown")) {
+ for (int j = 0; j < count; ++j) {
+ if (ImGui::Selectable(map[j].fName, i == map[j].fValue)) {
+ i = map[j].fValue;
+ }
+ }
+ ImGui::EndCombo();
+ }
+ }
+ }
+
+ void visit(const char* name, SkPoint& p) override {
+ if (fTreeStack.back()) {
+ ImGui::DragFloat2(item(name), &p.fX);
+ gDragPoints.push_back(&p);
+ }
+ }
+ void visit(const char* name, SkColor4f& c) override {
+ IF_OPEN(ImGui::ColorEdit4(item(name), c.vec()))
+ }
+
+#undef IF_OPEN
+
+ void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
+ if (fTreeStack.back()) {
+ const SkReflected::Type* curType = e ? e->getType() : nullptr;
+ if (ImGui::BeginCombo("Type", curType ? curType->fName : "Null")) {
+ auto visitType = [baseType, curType, &e](const SkReflected::Type* t) {
+ if (t->fFactory && (t == baseType || t->isDerivedFrom(baseType)) &&
+ ImGui::Selectable(t->fName, curType == t)) {
+ e = t->fFactory();
+ }
+ };
+ SkReflected::VisitTypes(visitType);
+ ImGui::EndCombo();
+ }
+ }
+ }
+
+ void enterObject(const char* name) override {
+ if (fTreeStack.back()) {
+ fTreeStack.push_back(ImGui::TreeNodeEx(item(name),
+ ImGuiTreeNodeFlags_AllowItemOverlap));
+ } else {
+ fTreeStack.push_back(false);
+ }
+ }
+ void exitObject() override {
+ if (fTreeStack.back()) {
+ ImGui::TreePop();
+ }
+ fTreeStack.pop_back();
+ }
+
+ int enterArray(const char* name, int oldCount) override {
+ this->enterObject(item(name));
+ fArrayCounterStack.push_back(0);
+ fArrayEditStack.push_back();
+
+ int count = oldCount;
+ if (fTreeStack.back()) {
+ ImGui::SameLine();
+ if (ImGui::Button("+")) {
+ ++count;
+ }
+ }
+ return count;
+ }
+ ArrayEdit exitArray() override {
+ fArrayCounterStack.pop_back();
+ auto edit = fArrayEditStack.back();
+ fArrayEditStack.pop_back();
+ this->exitObject();
+ return edit;
+ }
+
+private:
+ const char* item(const char* name) {
+ if (name) {
+ return name;
+ }
+
+ // We're in an array. Add extra controls and a dynamic label.
+ int index = fArrayCounterStack.back()++;
+ ArrayEdit& edit(fArrayEditStack.back());
+ fScratchLabel = SkStringPrintf("[%d]", index);
+
+ ImGui::PushID(index);
+
+ if (ImGui::Button("X")) {
+ edit.fVerb = ArrayEdit::Verb::kRemove;
+ edit.fIndex = index;
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("^")) {
+ edit.fVerb = ArrayEdit::Verb::kMoveForward;
+ edit.fIndex = index;
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("v")) {
+ edit.fVerb = ArrayEdit::Verb::kMoveForward;
+ edit.fIndex = index + 1;
+ }
+ ImGui::SameLine();
+
+ ImGui::PopID();
+
+ return fScratchLabel.c_str();
+ }
+
+ SkSTArray<16, bool, true> fTreeStack;
+ SkSTArray<16, int, true> fArrayCounterStack;
+ SkSTArray<16, ArrayEdit, true> fArrayEditStack;
+ SkString fScratchLabel;
+};
+
+ParticlesSlide::ParticlesSlide() {
+ // Register types for serialization
+ SkParticleEffect::RegisterParticleTypes();
+ fName = "Particles";
+ fPlayPosition.set(200.0f, 200.0f);
+}
+
+void ParticlesSlide::loadEffects(const char* dirname) {
+ fLoaded.reset();
+ fRunning.reset();
+ SkOSFile::Iter iter(dirname, ".json");
+ for (SkString file; iter.next(&file); ) {
+ LoadedEffect effect;
+ effect.fName = SkOSPath::Join(dirname, file.c_str());
+ effect.fParams.reset(new SkParticleEffectParams());
+ if (auto fileData = SkData::MakeFromFileName(effect.fName.c_str())) {
+ skjson::DOM dom(static_cast<const char*>(fileData->data()), fileData->size());
+ SkFromJsonVisitor fromJson(dom.root());
+ effect.fParams->visitFields(&fromJson);
+ fLoaded.push_back(effect);
+ }
+ }
+}
+
+void ParticlesSlide::load(SkScalar winWidth, SkScalar winHeight) {
+ this->loadEffects(GetResourcePath("particles").c_str());
+}
+
+void ParticlesSlide::draw(SkCanvas* canvas) {
+ canvas->clear(SK_ColorGRAY);
+
+ gDragPoints.reset();
+ gDragPoints.push_back(&fPlayPosition);
+
+ // Window to show all loaded effects, and allow playing them
+ if (ImGui::Begin("Library", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
+ static bool looped = true;
+ ImGui::Checkbox("Looped", &looped);
+
+ static SkString dirname = GetResourcePath("particles");
+ ImGuiInputTextFlags textFlags = ImGuiInputTextFlags_CallbackResize;
+ ImGui::InputText("Directory", dirname.writable_str(), dirname.size() + 1, textFlags,
+ InputTextCallback, &dirname);
+
+ if (ImGui::Button("New")) {
+ LoadedEffect effect;
+ effect.fName = SkOSPath::Join(dirname.c_str(), "new.json");
+ effect.fParams.reset(new SkParticleEffectParams());
+ fLoaded.push_back(effect);
+ }
+ ImGui::SameLine();
+
+ if (ImGui::Button("Load")) {
+ this->loadEffects(dirname.c_str());
+ }
+ ImGui::SameLine();
+
+ if (ImGui::Button("Save")) {
+ for (const auto& effect : fLoaded) {
+ SkFILEWStream fileStream(effect.fName.c_str());
+ if (fileStream.isValid()) {
+ SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kPretty);
+ SkToJsonVisitor toJson(writer);
+ writer.beginObject();
+ effect.fParams->visitFields(&toJson);
+ writer.endObject();
+ writer.flush();
+ fileStream.flush();
+ } else {
+ SkDebugf("Failed to open %s\n", effect.fName.c_str());
+ }
+ }
+ }
+
+ SkGuiVisitor gui;
+ for (int i = 0; i < fLoaded.count(); ++i) {
+ ImGui::PushID(i);
+ if (fAnimated && ImGui::Button("Play")) {
+ sk_sp<SkParticleEffect> effect(new SkParticleEffect(fLoaded[i].fParams, fRandom));
+ effect->start(fAnimationTime, looped);
+ fRunning.push_back({ fPlayPosition, fLoaded[i].fName, effect, false });
+ fRandom.nextU();
+ }
+ ImGui::SameLine();
+
+ ImGui::InputText("##Name", fLoaded[i].fName.writable_str(), fLoaded[i].fName.size() + 1,
+ textFlags, InputTextCallback, &fLoaded[i].fName);
+
+ if (ImGui::TreeNode("##Details")) {
+ fLoaded[i].fParams->visitFields(&gui);
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+ }
+ }
+ ImGui::End();
+
+ // Another window to show all the running effects
+ if (ImGui::Begin("Running")) {
+ for (int i = 0; i < fRunning.count(); ++i) {
+ SkParticleEffect* effect = fRunning[i].fEffect.get();
+ ImGui::PushID(effect);
+
+ ImGui::Checkbox("##Track", &fRunning[i].fTrackMouse);
+ ImGui::SameLine();
+ bool remove = ImGui::Button("X") || !effect->isAlive();
+ ImGui::SameLine();
+ ImGui::Text("%4g, %4g %5d %s", fRunning[i].fPosition.fX, fRunning[i].fPosition.fY,
+ effect->getCount(), fRunning[i].fName.c_str());
+ if (fRunning[i].fTrackMouse) {
+ effect->setPosition({ ImGui::GetMousePos().x, ImGui::GetMousePos().y });
+ fRunning[i].fPosition.set(0, 0);
+ }
+
+ auto uniformsGui = [](const SkSL::ByteCode* code, float* data, SkPoint spawnPos) {
+ if (!code || !data) {
+ return;
+ }
+ for (int i = 0; i < code->getUniformCount(); ++i) {
+ const auto& uni = code->getUniform(i);
+ float* vals = data + uni.fSlot;
+
+ // Skip over builtin uniforms, to reduce clutter
+ if (uni.fName == "dt" || uni.fName.startsWith("effect.")) {
+ continue;
+ }
+
+ // Special case for 'uniform float2 mouse_pos' - an example of likely app logic
+ if (uni.fName == "mouse_pos" &&
+ uni.fType == SkSL::TypeCategory::kFloat &&
+ uni.fRows == 2 && uni.fColumns == 1) {
+ ImVec2 mousePos = ImGui::GetMousePos();
+ vals[0] = mousePos.x - spawnPos.fX;
+ vals[1] = mousePos.y - spawnPos.fY;
+ continue;
+ }
+
+ if (uni.fType == SkSL::TypeCategory::kBool) {
+ for (int c = 0; c < uni.fColumns; ++c, vals += uni.fRows) {
+ for (int r = 0; r < uni.fRows; ++r, ++vals) {
+ ImGui::PushID(c*uni.fRows + r);
+ if (r > 0) {
+ ImGui::SameLine();
+ }
+ ImGui::CheckboxFlags(r == uni.fRows - 1 ? uni.fName.c_str()
+ : "##Hidden",
+ (unsigned int*)vals, ~0);
+ ImGui::PopID();
+ }
+ }
+ continue;
+ }
+
+ ImGuiDataType dataType = ImGuiDataType_COUNT;
+ switch (uni.fType) {
+ case SkSL::TypeCategory::kSigned: dataType = ImGuiDataType_S32; break;
+ case SkSL::TypeCategory::kUnsigned: dataType = ImGuiDataType_U32; break;
+ case SkSL::TypeCategory::kFloat: dataType = ImGuiDataType_Float; break;
+ default: break;
+ }
+ SkASSERT(dataType != ImGuiDataType_COUNT);
+ for (int c = 0; c < uni.fColumns; ++c, vals += uni.fRows) {
+ ImGui::PushID(c);
+ ImGui::DragScalarN(uni.fName.c_str(), dataType, vals, uni.fRows, 1.0f);
+ ImGui::PopID();
+ }
+ }
+ };
+ uniformsGui(effect->effectCode(), effect->effectUniforms(), fRunning[i].fPosition);
+ uniformsGui(effect->particleCode(), effect->particleUniforms(), fRunning[i].fPosition);
+ if (remove) {
+ fRunning.removeShuffle(i);
+ }
+ ImGui::PopID();
+ }
+ }
+ ImGui::End();
+
+ SkPaint dragPaint;
+ dragPaint.setColor(SK_ColorLTGRAY);
+ dragPaint.setAntiAlias(true);
+ SkPaint dragHighlight;
+ dragHighlight.setStyle(SkPaint::kStroke_Style);
+ dragHighlight.setColor(SK_ColorGREEN);
+ dragHighlight.setStrokeWidth(2);
+ dragHighlight.setAntiAlias(true);
+ for (int i = 0; i < gDragPoints.count(); ++i) {
+ canvas->drawCircle(*gDragPoints[i], kDragSize, dragPaint);
+ if (gDragIndex == i) {
+ canvas->drawCircle(*gDragPoints[i], kDragSize, dragHighlight);
+ }
+ }
+ for (const auto& effect : fRunning) {
+ canvas->save();
+ canvas->translate(effect.fPosition.fX, effect.fPosition.fY);
+ effect.fEffect->draw(canvas);
+ canvas->restore();
+ }
+}
+
+bool ParticlesSlide::animate(double nanos) {
+ fAnimated = true;
+ fAnimationTime = 1e-9 * nanos;
+ for (const auto& effect : fRunning) {
+ effect.fEffect->update(fAnimationTime);
+ }
+ return true;
+}
+
+bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, skui::InputState state, skui::ModifierKey modifiers) {
+ if (gDragIndex == -1) {
+ if (state == skui::InputState::kDown) {
+ float bestDistance = kDragSize;
+ SkPoint mousePt = { x, y };
+ for (int i = 0; i < gDragPoints.count(); ++i) {
+ float distance = SkPoint::Distance(*gDragPoints[i], mousePt);
+ if (distance < bestDistance) {
+ gDragIndex = i;
+ bestDistance = distance;
+ }
+ }
+ return gDragIndex != -1;
+ }
+ } else {
+ // Currently dragging
+ SkASSERT(gDragIndex < gDragPoints.count());
+ gDragPoints[gDragIndex]->set(x, y);
+ if (state == skui::InputState::kUp) {
+ gDragIndex = -1;
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/src/third_party/skia/tools/viewer/ParticlesSlide.h b/src/third_party/skia/tools/viewer/ParticlesSlide.h
new file mode 100644
index 0000000..9d98d41
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/ParticlesSlide.h
@@ -0,0 +1,57 @@
+/*
+* Copyright 2019 Google LLC
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef ParticlesSlide_DEFINED
+#define ParticlesSlide_DEFINED
+
+#include "tools/viewer/Slide.h"
+
+#include "include/core/SkPath.h"
+#include "include/private/SkTArray.h"
+#include "include/utils/SkRandom.h"
+
+class SkParticleEffect;
+class SkParticleEffectParams;
+
+class ParticlesSlide : public Slide {
+public:
+ ParticlesSlide();
+
+ // TODO: We need a way for primarily interactive slides to always be as large as the window
+ SkISize getDimensions() const override { return SkISize::MakeEmpty(); }
+
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void draw(SkCanvas* canvas) override;
+ bool animate(double) override;
+
+ bool onMouse(SkScalar x, SkScalar y, skui::InputState state,
+ skui::ModifierKey modifiers) override;
+
+private:
+ void loadEffects(const char* dirname);
+
+ SkRandom fRandom;
+ bool fAnimated = false;
+ double fAnimationTime = 0;
+ SkPoint fPlayPosition;
+
+ struct LoadedEffect {
+ SkString fName;
+ sk_sp<SkParticleEffectParams> fParams;
+ };
+ SkTArray<LoadedEffect> fLoaded;
+
+ struct RunningEffect {
+ SkPoint fPosition;
+ SkString fName;
+ sk_sp<SkParticleEffect> fEffect;
+ bool fTrackMouse;
+ };
+ SkTArray<RunningEffect> fRunning;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/SKPSlide.cpp b/src/third_party/skia/tools/viewer/SKPSlide.cpp
index e24e1fd..1c03a5e 100644
--- a/src/third_party/skia/tools/viewer/SKPSlide.cpp
+++ b/src/third_party/skia/tools/viewer/SKPSlide.cpp
@@ -5,12 +5,11 @@
* found in the LICENSE file.
*/
-#include "SKPSlide.h"
+#include "tools/viewer/SKPSlide.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkOSFile.h"
-#include "SkStream.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStream.h"
+#include "src/core/SkOSFile.h"
SKPSlide::SKPSlide(const SkString& name, const SkString& path) : fPath(path) {
fName = name;
@@ -50,7 +49,9 @@
void SKPSlide::load(SkScalar, SkScalar) {
fPic = read_picture(fPath.c_str());
- fCullRect = fPic->cullRect().roundOut();
+ if (fPic) {
+ fCullRect = fPic->cullRect().roundOut();
+ }
}
void SKPSlide::unload() {
diff --git a/src/third_party/skia/tools/viewer/SKPSlide.h b/src/third_party/skia/tools/viewer/SKPSlide.h
index ff92ed1..e202250 100644
--- a/src/third_party/skia/tools/viewer/SKPSlide.h
+++ b/src/third_party/skia/tools/viewer/SKPSlide.h
@@ -8,8 +8,8 @@
#ifndef SKPSlide_DEFINED
#define SKPSlide_DEFINED
-#include "Slide.h"
-#include "SkPicture.h"
+#include "include/core/SkPicture.h"
+#include "tools/viewer/Slide.h"
class SKPSlide : public Slide {
public:
diff --git a/src/third_party/skia/tools/viewer/SampleSlide.cpp b/src/third_party/skia/tools/viewer/SampleSlide.cpp
index 93a495e..662cb40 100644
--- a/src/third_party/skia/tools/viewer/SampleSlide.cpp
+++ b/src/third_party/skia/tools/viewer/SampleSlide.cpp
@@ -5,50 +5,45 @@
* found in the LICENSE file.
*/
-#include "SampleSlide.h"
+#include "tools/viewer/SampleSlide.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkOSFile.h"
-#include "SkStream.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStream.h"
+#include "src/core/SkOSFile.h"
-SampleSlide::SampleSlide(const SkViewFactory* factory) : fViewFactory(factory) {
- SkView* view = (*factory)();
- SampleCode::RequestTitle(view, &fName);
- view->unref();
+using namespace sk_app;
+
+SampleSlide::SampleSlide(const SampleFactory factory) : fSampleFactory(factory) {
+ std::unique_ptr<Sample> sample(factory());
+ fName = sample->name();
}
SampleSlide::~SampleSlide() {}
+SkISize SampleSlide::getDimensions() const {
+ return SkISize::Make(SkScalarCeilToInt(fSample->width()), SkScalarCeilToInt(fSample->height()));
+}
+
+bool SampleSlide::animate(double nanos) { return fSample->animate(nanos); }
+
void SampleSlide::draw(SkCanvas* canvas) {
- SkASSERT(fView);
- fView->draw(canvas);
+ SkASSERT(fSample);
+ fSample->draw(canvas);
}
void SampleSlide::load(SkScalar winWidth, SkScalar winHeight) {
- fView.reset((*fViewFactory)());
- fView->setVisibleP(true);
- fView->setClipToBounds(false);
- fView->setSize(winWidth, winHeight);
+ fSample.reset(fSampleFactory());
+ fSample->setSize(winWidth, winHeight);
}
void SampleSlide::unload() {
- fView.reset();
+ fSample.reset();
}
bool SampleSlide::onChar(SkUnichar c) {
- if (!fView) {
- return false;
- }
- SkEvent evt(gCharEvtName);
- evt.setFast32(c);
- return fView->doQuery(&evt);
+ return fSample && fSample->onChar(c);
}
-#if defined(SK_BUILD_FOR_ANDROID)
-// these are normally defined in SkOSWindow_unix, but we don't
-// want to include that
-void SkEvent::SignalNonEmptyQueue() {}
-
-void SkEvent::SignalQueueTimer(SkMSec delay) {}
-#endif
+bool SampleSlide::onMouse(SkScalar x, SkScalar y, skui::InputState state, skui::ModifierKey modifierKeys) {
+ return fSample && fSample->mouse({x, y}, state, modifierKeys);
+}
diff --git a/src/third_party/skia/tools/viewer/SampleSlide.h b/src/third_party/skia/tools/viewer/SampleSlide.h
index 24325c9..fcb5542 100644
--- a/src/third_party/skia/tools/viewer/SampleSlide.h
+++ b/src/third_party/skia/tools/viewer/SampleSlide.h
@@ -8,29 +8,31 @@
#ifndef SampleSlide_DEFINED
#define SampleSlide_DEFINED
-#include "Slide.h"
-#include "SampleCode.h"
+#include "samplecode/Sample.h"
+#include "tools/viewer/Slide.h"
class SampleSlide : public Slide {
public:
- SampleSlide(const SkViewFactory* factory);
+ SampleSlide(const SampleFactory factory);
~SampleSlide() override;
+ SkISize getDimensions() const override;
+
void draw(SkCanvas* canvas) override;
void load(SkScalar winWidth, SkScalar winHeight) override;
- void unload() override;
- bool animate(const SkAnimTimer& timer) override {
- if (fView && SampleView::IsSampleView(fView.get())) {
- return ((SampleView*)fView.get())->animate(timer);
- }
- return false;
+ void resize(SkScalar winWidth, SkScalar winHeight) override {
+ fSample->setSize(winWidth, winHeight);
}
+ void unload() override;
+ bool animate(double) override;
bool onChar(SkUnichar c) override;
+ bool onMouse(SkScalar x, SkScalar y, skui::InputState state,
+ skui::ModifierKey modifiers) override;
private:
- const SkViewFactory* fViewFactory;
- sk_sp<SkView> fView;
+ const SampleFactory fSampleFactory;
+ std::unique_ptr<Sample> fSample;
};
#endif
diff --git a/src/third_party/skia/tools/viewer/SkottieSlide.cpp b/src/third_party/skia/tools/viewer/SkottieSlide.cpp
new file mode 100644
index 0000000..65ec645
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SkottieSlide.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/viewer/SkottieSlide.h"
+
+#if defined(SK_ENABLE_SKOTTIE)
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFont.h"
+#include "modules/skottie/include/Skottie.h"
+#include "modules/skottie/utils/SkottieUtils.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/timer/TimeUtils.h"
+
+#include <cmath>
+
+static void draw_stats_box(SkCanvas* canvas, const skottie::Animation::Builder::Stats& stats) {
+ static constexpr SkRect kR = { 10, 10, 280, 120 };
+ static constexpr SkScalar kTextSize = 20;
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(0xffeeeeee);
+
+ SkFont font(nullptr, kTextSize);
+
+ canvas->drawRect(kR, paint);
+
+ paint.setColor(SK_ColorBLACK);
+
+ const auto json_size = SkStringPrintf("Json size: %lu bytes",
+ stats.fJsonSize);
+ canvas->drawString(json_size, kR.x() + 10, kR.y() + kTextSize * 1, font, paint);
+ const auto animator_count = SkStringPrintf("Animator count: %lu",
+ stats.fAnimatorCount);
+ canvas->drawString(animator_count, kR.x() + 10, kR.y() + kTextSize * 2, font, paint);
+ const auto json_parse_time = SkStringPrintf("Json parse time: %.3f ms",
+ stats.fJsonParseTimeMS);
+ canvas->drawString(json_parse_time, kR.x() + 10, kR.y() + kTextSize * 3, font, paint);
+ const auto scene_parse_time = SkStringPrintf("Scene build time: %.3f ms",
+ stats.fSceneParseTimeMS);
+ canvas->drawString(scene_parse_time, kR.x() + 10, kR.y() + kTextSize * 4, font, paint);
+ const auto total_load_time = SkStringPrintf("Total load time: %.3f ms",
+ stats.fTotalLoadTimeMS);
+ canvas->drawString(total_load_time, kR.x() + 10, kR.y() + kTextSize * 5, font, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(kR, paint);
+}
+
+SkottieSlide::SkottieSlide(const SkString& name, const SkString& path)
+ : fPath(path) {
+ fName = name;
+}
+
+void SkottieSlide::load(SkScalar w, SkScalar h) {
+ class Logger final : public skottie::Logger {
+ public:
+ struct LogEntry {
+ SkString fMessage,
+ fJSON;
+ };
+
+ void log(skottie::Logger::Level lvl, const char message[], const char json[]) override {
+ auto& log = lvl == skottie::Logger::Level::kError ? fErrors : fWarnings;
+ log.push_back({ SkString(message), json ? SkString(json) : SkString() });
+ }
+
+ void report() const {
+ SkDebugf("Animation loaded with %lu error%s, %lu warning%s.\n",
+ fErrors.size(), fErrors.size() == 1 ? "" : "s",
+ fWarnings.size(), fWarnings.size() == 1 ? "" : "s");
+
+ const auto& show = [](const LogEntry& log, const char prefix[]) {
+ SkDebugf("%s%s", prefix, log.fMessage.c_str());
+ if (!log.fJSON.isEmpty())
+ SkDebugf(" : %s", log.fJSON.c_str());
+ SkDebugf("\n");
+ };
+
+ for (const auto& err : fErrors) show(err, " !! ");
+ for (const auto& wrn : fWarnings) show(wrn, " ?? ");
+ }
+
+ private:
+ std::vector<LogEntry> fErrors,
+ fWarnings;
+ };
+
+ auto logger = sk_make_sp<Logger>();
+ skottie::Animation::Builder builder;
+
+ fAnimation = builder
+ .setLogger(logger)
+ .setResourceProvider(
+ skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str())))
+ .makeFromFile(fPath.c_str());
+ fAnimationStats = builder.getStats();
+ fWinSize = SkSize::Make(w, h);
+ fTimeBase = 0; // force a time reset
+
+ if (fAnimation) {
+ SkDebugf("Loaded Bodymovin animation v: %s, size: [%f %f]\n",
+ fAnimation->version().c_str(),
+ fAnimation->size().width(),
+ fAnimation->size().height());
+ logger->report();
+ } else {
+ SkDebugf("failed to load Bodymovin animation: %s\n", fPath.c_str());
+ }
+}
+
+void SkottieSlide::unload() {
+ fAnimation.reset();
+}
+
+SkISize SkottieSlide::getDimensions() const {
+ // We always scale to fill the window.
+ return fWinSize.toCeil();
+}
+
+void SkottieSlide::draw(SkCanvas* canvas) {
+ if (fAnimation) {
+ SkAutoCanvasRestore acr(canvas, true);
+ const auto dstR = SkRect::MakeSize(fWinSize);
+ fAnimation->render(canvas, &dstR);
+
+ if (fShowAnimationStats) {
+ draw_stats_box(canvas, fAnimationStats);
+ }
+ if (fShowAnimationInval) {
+ const auto t = SkMatrix::MakeRectToRect(SkRect::MakeSize(fAnimation->size()),
+ dstR,
+ SkMatrix::kCenter_ScaleToFit);
+ SkPaint fill, stroke;
+ fill.setAntiAlias(true);
+ fill.setColor(0x40ff0000);
+ stroke.setAntiAlias(true);
+ stroke.setColor(0xffff0000);
+ stroke.setStyle(SkPaint::kStroke_Style);
+
+ for (const auto& r : fInvalController) {
+ SkRect bounds;
+ t.mapRect(&bounds, r);
+ canvas->drawRect(bounds, fill);
+ canvas->drawRect(bounds, stroke);
+ }
+ }
+ }
+}
+
+bool SkottieSlide::animate(double nanos) {
+ SkMSec msec = TimeUtils::NanosToMSec(nanos);
+ if (fTimeBase == 0) {
+ // Reset the animation time.
+ fTimeBase = msec;
+ }
+
+ if (fAnimation) {
+ fInvalController.reset();
+ const auto t = msec - fTimeBase;
+ const auto d = fAnimation->duration() * 1000;
+ fAnimation->seek(std::fmod(t, d) / d, &fInvalController);
+ }
+ return true;
+}
+
+bool SkottieSlide::onChar(SkUnichar c) {
+ switch (c) {
+ case 'I':
+ fShowAnimationStats = !fShowAnimationStats;
+ break;
+ default:
+ break;
+ }
+
+ return INHERITED::onChar(c);
+}
+
+bool SkottieSlide::onMouse(SkScalar x, SkScalar y, skui::InputState state, skui::ModifierKey) {
+ switch (state) {
+ case skui::InputState::kUp:
+ fShowAnimationInval = !fShowAnimationInval;
+ fShowAnimationStats = !fShowAnimationStats;
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+#endif // SK_ENABLE_SKOTTIE
diff --git a/src/third_party/skia/tools/viewer/SkottieSlide.h b/src/third_party/skia/tools/viewer/SkottieSlide.h
new file mode 100644
index 0000000..843922b
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SkottieSlide.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkottieSlide_DEFINED
+#define SkottieSlide_DEFINED
+
+#include "tools/viewer/Slide.h"
+
+#if defined(SK_ENABLE_SKOTTIE)
+#include "modules/skottie/include/Skottie.h"
+#include "modules/sksg/include/SkSGInvalidationController.h"
+
+namespace sksg { class Scene; }
+
+class SkottieSlide : public Slide {
+public:
+ SkottieSlide(const SkString& name, const SkString& path);
+ ~SkottieSlide() override = default;
+
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void unload() override;
+
+ SkISize getDimensions() const override;
+
+ void draw(SkCanvas*) override;
+ bool animate(double) override;
+
+ bool onChar(SkUnichar) override;
+ bool onMouse(SkScalar x, SkScalar y, skui::InputState, skui::ModifierKey modifiers) override;
+
+private:
+ SkString fPath;
+ sk_sp<skottie::Animation> fAnimation;
+ skottie::Animation::Builder::Stats fAnimationStats;
+ sksg::InvalidationController fInvalController;
+ SkSize fWinSize = SkSize::MakeEmpty();
+ SkMSec fTimeBase = 0;
+ bool fShowAnimationInval = false,
+ fShowAnimationStats = false;
+
+ typedef Slide INHERITED;
+};
+
+#endif // SK_ENABLE_SKOTTIE
+
+#endif // SkottieSlide_DEFINED
diff --git a/src/third_party/skia/tools/viewer/Slide.h b/src/third_party/skia/tools/viewer/Slide.h
index 9ec7a3d..e81f860 100644
--- a/src/third_party/skia/tools/viewer/Slide.h
+++ b/src/third_party/skia/tools/viewer/Slide.h
@@ -8,30 +8,36 @@
#ifndef Slide_DEFINED
#define Slide_DEFINED
-#include "SkRefCnt.h"
-#include "SkSize.h"
-#include "SkString.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "tools/sk_app/Window.h"
class SkCanvas;
-class SkAnimTimer;
+class SkMetaData;
class Slide : public SkRefCnt {
public:
virtual ~Slide() {}
- virtual SkISize getDimensions() const {
- return SkISize::Make(0, 0);
- }
+ virtual SkISize getDimensions() const = 0;
virtual void draw(SkCanvas* canvas) = 0;
- virtual bool animate(const SkAnimTimer&) { return false; }
+ virtual bool animate(double nanos) { return false; }
virtual void load(SkScalar winWidth, SkScalar winHeight) {}
+ virtual void resize(SkScalar winWidth, SkScalar winHeight) {}
virtual void unload() {}
virtual bool onChar(SkUnichar c) { return false; }
+ virtual bool onMouse(SkScalar x, SkScalar y, skui::InputState state,
+ skui::ModifierKey modifiers) { return false; }
+
+ virtual bool onGetControls(SkMetaData*) { return false; }
+ virtual void onSetControls(const SkMetaData&) {}
SkString getName() { return fName; }
+
protected:
SkString fName;
};
diff --git a/src/third_party/skia/tools/viewer/SlideDir.cpp b/src/third_party/skia/tools/viewer/SlideDir.cpp
new file mode 100644
index 0000000..27eed20
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SlideDir.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/viewer/SlideDir.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkCubicMap.h"
+#include "include/core/SkTypeface.h"
+#include "modules/sksg/include/SkSGDraw.h"
+#include "modules/sksg/include/SkSGGroup.h"
+#include "modules/sksg/include/SkSGPaint.h"
+#include "modules/sksg/include/SkSGPlane.h"
+#include "modules/sksg/include/SkSGRect.h"
+#include "modules/sksg/include/SkSGRenderNode.h"
+#include "modules/sksg/include/SkSGScene.h"
+#include "modules/sksg/include/SkSGText.h"
+#include "modules/sksg/include/SkSGTransform.h"
+#include "src/core/SkMakeUnique.h"
+#include "tools/timer/TimeUtils.h"
+
+#include <cmath>
+#include <utility>
+
+namespace {
+
+static constexpr float kAspectRatio = 1.5f;
+static constexpr float kLabelSize = 12.0f;
+static constexpr SkSize kPadding = { 12.0f , 24.0f };
+
+static constexpr float kFocusDuration = 500;
+static constexpr SkSize kFocusInset = { 100.0f, 100.0f };
+static constexpr SkPoint kFocusCtrl0 = { 0.3f, 1.0f };
+static constexpr SkPoint kFocusCtrl1 = { 0.0f, 1.0f };
+static constexpr SkColor kFocusShade = 0xa0000000;
+
+// TODO: better unfocus binding?
+static constexpr SkUnichar kUnfocusKey = ' ';
+
+class SlideAdapter final : public sksg::RenderNode {
+public:
+ explicit SlideAdapter(sk_sp<Slide> slide)
+ : fSlide(std::move(slide)) {
+ SkASSERT(fSlide);
+ }
+
+ sk_sp<sksg::Animator> makeForwardingAnimator() {
+ // Trivial sksg::Animator -> skottie::Animation tick adapter
+ class ForwardingAnimator final : public sksg::Animator {
+ public:
+ explicit ForwardingAnimator(sk_sp<SlideAdapter> adapter)
+ : fAdapter(std::move(adapter)) {}
+
+ protected:
+ void onTick(float t) override {
+ fAdapter->tick(SkScalarRoundToInt(t));
+ }
+
+ private:
+ sk_sp<SlideAdapter> fAdapter;
+ };
+
+ return sk_make_sp<ForwardingAnimator>(sk_ref_sp(this));
+ }
+
+protected:
+ SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
+ const auto isize = fSlide->getDimensions();
+ return SkRect::MakeIWH(isize.width(), isize.height());
+ }
+
+ void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clipRect(SkRect::Make(fSlide->getDimensions()), true);
+
+ // TODO: commit the context?
+ fSlide->draw(canvas);
+ }
+
+ const RenderNode* onNodeAt(const SkPoint&) const override { return nullptr; }
+
+private:
+ void tick(SkMSec t) {
+ fSlide->animate(t * 1e6);
+ this->invalidate();
+ }
+
+ const sk_sp<Slide> fSlide;
+
+ using INHERITED = sksg::RenderNode;
+};
+
+SkMatrix SlideMatrix(const sk_sp<Slide>& slide, const SkRect& dst) {
+ const auto slideSize = slide->getDimensions();
+ return SkMatrix::MakeRectToRect(SkRect::MakeIWH(slideSize.width(), slideSize.height()),
+ dst,
+ SkMatrix::kCenter_ScaleToFit);
+}
+
+} // namespace
+
+struct SlideDir::Rec {
+ sk_sp<Slide> fSlide;
+ sk_sp<sksg::RenderNode> fSlideRoot;
+ sk_sp<sksg::Matrix<SkMatrix>> fMatrix;
+ SkRect fRect;
+};
+
+class SlideDir::FocusController final : public sksg::Animator {
+public:
+ FocusController(const SlideDir* dir, const SkRect& focusRect)
+ : fDir(dir)
+ , fRect(focusRect)
+ , fTarget(nullptr)
+ , fMap(kFocusCtrl1, kFocusCtrl0)
+ , fState(State::kIdle) {
+ fShadePaint = sksg::Color::Make(kFocusShade);
+ fShade = sksg::Draw::Make(sksg::Plane::Make(), fShadePaint);
+ }
+
+ bool hasFocus() const { return fState == State::kFocused; }
+
+ void startFocus(const Rec* target) {
+ if (fState != State::kIdle)
+ return;
+
+ fTarget = target;
+
+ // Move the shade & slide to front.
+ fDir->fRoot->removeChild(fTarget->fSlideRoot);
+ fDir->fRoot->addChild(fShade);
+ fDir->fRoot->addChild(fTarget->fSlideRoot);
+
+ fM0 = SlideMatrix(fTarget->fSlide, fTarget->fRect);
+ fM1 = SlideMatrix(fTarget->fSlide, fRect);
+
+ fOpacity0 = 0;
+ fOpacity1 = 1;
+
+ fTimeBase = 0;
+ fState = State::kFocusing;
+
+ // Push initial state to the scene graph.
+ this->onTick(fTimeBase);
+ }
+
+ void startUnfocus() {
+ SkASSERT(fTarget);
+
+ using std::swap;
+ swap(fM0, fM1);
+ swap(fOpacity0, fOpacity1);
+
+ fTimeBase = 0;
+ fState = State::kUnfocusing;
+ }
+
+ bool onMouse(SkScalar x, SkScalar y, skui::InputState state, skui::ModifierKey modifiers) {
+ SkASSERT(fTarget);
+
+ if (!fRect.contains(x, y)) {
+ this->startUnfocus();
+ return true;
+ }
+
+ // Map coords to slide space.
+ const auto xform = SkMatrix::MakeRectToRect(fRect,
+ SkRect::MakeSize(fDir->fWinSize),
+ SkMatrix::kCenter_ScaleToFit);
+ const auto pt = xform.mapXY(x, y);
+
+ return fTarget->fSlide->onMouse(pt.x(), pt.y(), state, modifiers);
+ }
+
+ bool onChar(SkUnichar c) {
+ SkASSERT(fTarget);
+
+ return fTarget->fSlide->onChar(c);
+ }
+
+protected:
+ void onTick(float t) {
+ if (!this->isAnimating())
+ return;
+
+ if (!fTimeBase) {
+ fTimeBase = t;
+ }
+
+ const auto rel_t = (t - fTimeBase) / kFocusDuration,
+ map_t = SkTPin(fMap.computeYFromX(rel_t), 0.0f, 1.0f);
+
+ SkMatrix m;
+ for (int i = 0; i < 9; ++i) {
+ m[i] = fM0[i] + map_t * (fM1[i] - fM0[i]);
+ }
+
+ SkASSERT(fTarget);
+ fTarget->fMatrix->setMatrix(m);
+
+ const auto shadeOpacity = fOpacity0 + map_t * (fOpacity1 - fOpacity0);
+ fShadePaint->setOpacity(shadeOpacity);
+
+ if (rel_t < 1)
+ return;
+
+ switch (fState) {
+ case State::kFocusing:
+ fState = State::kFocused;
+ break;
+ case State::kUnfocusing:
+ fState = State::kIdle;
+ fDir->fRoot->removeChild(fShade);
+ break;
+
+ case State::kIdle:
+ case State::kFocused:
+ SkASSERT(false);
+ break;
+ }
+ }
+
+private:
+ enum class State {
+ kIdle,
+ kFocusing,
+ kUnfocusing,
+ kFocused,
+ };
+
+ bool isAnimating() const { return fState == State::kFocusing || fState == State::kUnfocusing; }
+
+ const SlideDir* fDir;
+ const SkRect fRect;
+ const Rec* fTarget;
+
+ SkCubicMap fMap;
+ sk_sp<sksg::RenderNode> fShade;
+ sk_sp<sksg::PaintNode> fShadePaint;
+
+ SkMatrix fM0 = SkMatrix::I(),
+ fM1 = SkMatrix::I();
+ float fOpacity0 = 0,
+ fOpacity1 = 1,
+ fTimeBase = 0;
+ State fState = State::kIdle;
+
+ using INHERITED = sksg::Animator;
+};
+
+SlideDir::SlideDir(const SkString& name, SkTArray<sk_sp<Slide>>&& slides, int columns)
+ : fSlides(std::move(slides))
+ , fColumns(columns) {
+ fName = name;
+}
+
+static sk_sp<sksg::RenderNode> MakeLabel(const SkString& txt,
+ const SkPoint& pos,
+ const SkMatrix& dstXform) {
+ const auto size = kLabelSize / std::sqrt(dstXform.getScaleX() * dstXform.getScaleY());
+ auto text = sksg::Text::Make(nullptr, txt);
+ text->setEdging(SkFont::Edging::kAntiAlias);
+ text->setSize(size);
+ text->setAlign(SkTextUtils::kCenter_Align);
+ text->setPosition(pos + SkPoint::Make(0, size));
+
+ return sksg::Draw::Make(std::move(text), sksg::Color::Make(SK_ColorBLACK));
+}
+
+void SlideDir::load(SkScalar winWidth, SkScalar winHeight) {
+ // Build a global scene using transformed animation fragments:
+ //
+ // [Group(root)]
+ // [Transform]
+ // [Group]
+ // [AnimationWrapper]
+ // [Draw]
+ // [Text]
+ // [Color]
+ // [Transform]
+ // [Group]
+ // [AnimationWrapper]
+ // [Draw]
+ // [Text]
+ // [Color]
+ // ...
+ //
+
+ fWinSize = SkSize::Make(winWidth, winHeight);
+ const auto cellWidth = winWidth / fColumns;
+ fCellSize = SkSize::Make(cellWidth, cellWidth / kAspectRatio);
+
+ sksg::AnimatorList sceneAnimators;
+ fRoot = sksg::Group::Make();
+
+ for (int i = 0; i < fSlides.count(); ++i) {
+ const auto& slide = fSlides[i];
+ slide->load(winWidth, winHeight);
+
+ const auto slideSize = slide->getDimensions();
+ const auto cell = SkRect::MakeXYWH(fCellSize.width() * (i % fColumns),
+ fCellSize.height() * (i / fColumns),
+ fCellSize.width(),
+ fCellSize.height()),
+ slideRect = cell.makeInset(kPadding.width(), kPadding.height());
+
+ auto slideMatrix = sksg::Matrix<SkMatrix>::Make(SlideMatrix(slide, slideRect));
+ auto adapter = sk_make_sp<SlideAdapter>(slide);
+ auto slideGrp = sksg::Group::Make();
+ slideGrp->addChild(sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeIWH(slideSize.width(),
+ slideSize.height())),
+ sksg::Color::Make(0xfff0f0f0)));
+ slideGrp->addChild(adapter);
+ slideGrp->addChild(MakeLabel(slide->getName(),
+ SkPoint::Make(slideSize.width() / 2, slideSize.height()),
+ slideMatrix->getMatrix()));
+ auto slideRoot = sksg::TransformEffect::Make(std::move(slideGrp), slideMatrix);
+
+ sceneAnimators.push_back(adapter->makeForwardingAnimator());
+
+ fRoot->addChild(slideRoot);
+ fRecs.push_back({ slide, slideRoot, slideMatrix, slideRect });
+ }
+
+ fScene = sksg::Scene::Make(fRoot, std::move(sceneAnimators));
+
+ const auto focusRect = SkRect::MakeSize(fWinSize).makeInset(kFocusInset.width(),
+ kFocusInset.height());
+ fFocusController = skstd::make_unique<FocusController>(this, focusRect);
+}
+
+void SlideDir::unload() {
+ for (const auto& slide : fSlides) {
+ slide->unload();
+ }
+
+ fRecs.reset();
+ fScene.reset();
+ fFocusController.reset();
+ fRoot.reset();
+ fTimeBase = 0;
+}
+
+SkISize SlideDir::getDimensions() const {
+ return SkSize::Make(fWinSize.width(),
+ fCellSize.height() * (1 + (fSlides.count() - 1) / fColumns)).toCeil();
+}
+
+void SlideDir::draw(SkCanvas* canvas) {
+ fScene->render(canvas);
+}
+
+bool SlideDir::animate(double nanos) {
+ SkMSec msec = TimeUtils::NanosToMSec(nanos);
+ if (fTimeBase == 0) {
+ // Reset the animation time.
+ fTimeBase = msec;
+ }
+
+ const auto t = msec - fTimeBase;
+ fScene->animate(t);
+ fFocusController->tick(t);
+
+ return true;
+}
+
+bool SlideDir::onChar(SkUnichar c) {
+ if (fFocusController->hasFocus()) {
+ if (c == kUnfocusKey) {
+ fFocusController->startUnfocus();
+ return true;
+ }
+ return fFocusController->onChar(c);
+ }
+
+ return false;
+}
+
+bool SlideDir::onMouse(SkScalar x, SkScalar y, skui::InputState state,
+ skui::ModifierKey modifiers) {
+ modifiers &= ~skui::ModifierKey::kFirstPress;
+ if (state == skui::InputState::kMove || skstd::Any(modifiers))
+ return false;
+
+ if (fFocusController->hasFocus()) {
+ return fFocusController->onMouse(x, y, state, modifiers);
+ }
+
+ const auto* cell = this->findCell(x, y);
+ if (!cell)
+ return false;
+
+ static constexpr SkScalar kClickMoveTolerance = 4;
+
+ switch (state) {
+ case skui::InputState::kDown:
+ fTrackingCell = cell;
+ fTrackingPos = SkPoint::Make(x, y);
+ break;
+ case skui::InputState::kUp:
+ if (cell == fTrackingCell &&
+ SkPoint::Distance(fTrackingPos, SkPoint::Make(x, y)) < kClickMoveTolerance) {
+ fFocusController->startFocus(cell);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+const SlideDir::Rec* SlideDir::findCell(float x, float y) const {
+ // TODO: use SG hit testing instead of layout info?
+ const auto size = this->getDimensions();
+ if (x < 0 || y < 0 || x >= size.width() || y >= size.height()) {
+ return nullptr;
+ }
+
+ const int col = static_cast<int>(x / fCellSize.width()),
+ row = static_cast<int>(y / fCellSize.height()),
+ idx = row * fColumns + col;
+
+ return idx < fRecs.count() ? &fRecs[idx] : nullptr;
+}
diff --git a/src/third_party/skia/tools/viewer/SlideDir.h b/src/third_party/skia/tools/viewer/SlideDir.h
new file mode 100644
index 0000000..3a57340
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SlideDir.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SlideDir_DEFINED
+#define SlideDir_DEFINED
+
+#include "tools/viewer/Slide.h"
+
+#include "include/private/SkTArray.h"
+
+class SkString;
+
+namespace sksg {
+
+class Group;
+class Scene;
+
+}
+
+class SlideDir final : public Slide {
+public:
+ SlideDir(const SkString& name, SkTArray<sk_sp<Slide>>&&,
+ int columns = kDefaultColumnCount);
+
+protected:
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void unload() override;
+
+ SkISize getDimensions() const override;
+
+ void draw(SkCanvas*) override;
+ bool animate(double) override;
+
+ bool onChar(SkUnichar) override;
+ bool onMouse(SkScalar x, SkScalar y, skui::InputState, skui::ModifierKey modifiers) override;
+
+private:
+ struct Rec;
+ class FocusController;
+
+ static constexpr int kDefaultColumnCount = 4;
+
+ const Rec* findCell(float x, float y) const;
+
+ const SkTArray<sk_sp<Slide>> fSlides;
+ std::unique_ptr<FocusController> fFocusController;
+ const int fColumns;
+
+ SkTArray<Rec, true> fRecs;
+ std::unique_ptr<sksg::Scene> fScene;
+ sk_sp<sksg::Group> fRoot;
+
+ SkSize fWinSize = SkSize::MakeEmpty();
+ SkSize fCellSize = SkSize::MakeEmpty();
+ SkMSec fTimeBase = 0;
+
+ const Rec* fTrackingCell = nullptr;
+ SkPoint fTrackingPos = SkPoint::Make(0, 0);
+
+ using INHERITED = Slide;
+};
+
+#endif // SlideDir_DEFINED
diff --git a/src/third_party/skia/tools/viewer/StatsLayer.cpp b/src/third_party/skia/tools/viewer/StatsLayer.cpp
new file mode 100644
index 0000000..a047b31
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/StatsLayer.cpp
@@ -0,0 +1,177 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "tools/viewer/StatsLayer.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFont.h"
+#include "include/core/SkString.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTime.h"
+
+StatsLayer::StatsLayer()
+ : fCurrentMeasurement(-1)
+ , fLastTotalBegin(0)
+ , fCumulativeMeasurementTime(0)
+ , fCumulativeMeasurementCount(0)
+ , fDisplayScale(1.0f) {
+ memset(fTotalTimes, 0, sizeof(fTotalTimes));
+}
+
+void StatsLayer::resetMeasurements() {
+ for (int i = 0; i < fTimers.count(); ++i) {
+ memset(fTimers[i].fTimes, 0, sizeof(fTimers[i].fTimes));
+ }
+ memset(fTotalTimes, 0, sizeof(fTotalTimes));
+ fCurrentMeasurement = -1;
+ fLastTotalBegin = 0;
+ fCumulativeMeasurementTime = 0;
+ fCumulativeMeasurementCount = 0;
+}
+
+StatsLayer::Timer StatsLayer::addTimer(const char* label, SkColor color, SkColor labelColor) {
+ Timer newTimer = fTimers.count();
+ TimerData& newData = fTimers.push_back();
+ memset(newData.fTimes, 0, sizeof(newData.fTimes));
+ newData.fLabel = label;
+ newData.fColor = color;
+ newData.fLabelColor = labelColor ? labelColor : color;
+ return newTimer;
+}
+
+void StatsLayer::beginTiming(Timer timer) {
+ if (fCurrentMeasurement >= 0) {
+ fTimers[timer].fTimes[fCurrentMeasurement] -= SkTime::GetMSecs();
+ }
+}
+
+void StatsLayer::endTiming(Timer timer) {
+ if (fCurrentMeasurement >= 0) {
+ fTimers[timer].fTimes[fCurrentMeasurement] += SkTime::GetMSecs();
+ }
+}
+
+void StatsLayer::onPrePaint() {
+ if (fCurrentMeasurement >= 0) {
+ fTotalTimes[fCurrentMeasurement] = SkTime::GetMSecs() - fLastTotalBegin;
+ fCumulativeMeasurementTime += fTotalTimes[fCurrentMeasurement];
+ fCumulativeMeasurementCount++;
+ }
+ fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
+ SkASSERT(fCurrentMeasurement >= 0 && fCurrentMeasurement < kMeasurementCount);
+ fLastTotalBegin = SkTime::GetMSecs();
+}
+
+void StatsLayer::onPaint(SkSurface* surface) {
+ int nextMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
+ for (int i = 0; i < fTimers.count(); ++i) {
+ fTimers[i].fTimes[nextMeasurement] = 0;
+ }
+
+#ifdef SK_BUILD_FOR_ANDROID
+ // Scale up the stats overlay on Android devices
+ static constexpr SkScalar kScale = 1.5;
+#else
+ SkScalar kScale = fDisplayScale;
+#endif
+
+ // Now draw everything
+ static const float kPixelPerMS = 2.0f;
+ static const int kDisplayWidth = 192;
+ static const int kGraphHeight = 100;
+ static const int kTextHeight = 60;
+ static const int kDisplayHeight = kGraphHeight + kTextHeight;
+ static const int kDisplayPadding = 10;
+ static const int kGraphPadding = 3;
+ static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
+
+ auto canvas = surface->getCanvas();
+ SkISize canvasSize = canvas->getBaseLayerSize();
+ SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
+ SkIntToScalar(kDisplayPadding),
+ SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
+ SkPaint paint;
+ canvas->save();
+
+ // Scale the canvas while keeping the right edge in place.
+ canvas->concat(SkMatrix::MakeRectToRect(SkRect::Make(canvasSize),
+ SkRect::MakeXYWH(canvasSize.width() * (1 - kScale),
+ 0,
+ canvasSize.width() * kScale,
+ canvasSize.height() * kScale),
+ SkMatrix::kFill_ScaleToFit));
+
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawRect(rect, paint);
+ // draw the 16ms line
+ paint.setColor(SK_ColorLTGRAY);
+ canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
+ rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
+ paint.setColor(SK_ColorRED);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(rect, paint);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
+ const int xStep = 3;
+ int i = nextMeasurement;
+ SkTDArray<double> sumTimes;
+ sumTimes.setCount(fTimers.count());
+ memset(sumTimes.begin(), 0, sumTimes.count() * sizeof(double));
+ int count = 0;
+ double totalTime = 0;
+ int totalCount = 0;
+ do {
+ int startY = SkScalarTruncToInt(rect.fBottom);
+ double inc = 0;
+ for (int timer = 0; timer < fTimers.count(); ++timer) {
+ int height = (int)(fTimers[timer].fTimes[i] * kPixelPerMS + 0.5);
+ int endY = SkTMax(startY - height, kDisplayPadding + kTextHeight);
+ paint.setColor(fTimers[timer].fColor);
+ canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
+ SkIntToScalar(x), SkIntToScalar(endY), paint);
+ startY = endY;
+ inc += fTimers[timer].fTimes[i];
+ sumTimes[timer] += fTimers[timer].fTimes[i];
+ }
+
+ int height = (int)(fTotalTimes[i] * kPixelPerMS + 0.5);
+ height = SkTMax(0, height - (SkScalarTruncToInt(rect.fBottom) - startY));
+ int endY = SkTMax(startY - height, kDisplayPadding + kTextHeight);
+ paint.setColor(SK_ColorWHITE);
+ canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
+ SkIntToScalar(x), SkIntToScalar(endY), paint);
+ totalTime += fTotalTimes[i];
+ if (fTotalTimes[i] > 0) {
+ ++totalCount;
+ }
+
+ if (inc > 0) {
+ ++count;
+ }
+
+ i++;
+ i &= (kMeasurementCount - 1); // fast mod
+ x += xStep;
+ } while (i != nextMeasurement);
+
+ SkFont font(nullptr, 16);
+ paint.setColor(SK_ColorWHITE);
+ double time = totalTime / SkTMax(1, totalCount);
+ double measure = fCumulativeMeasurementTime / SkTMax(1, fCumulativeMeasurementCount);
+ canvas->drawString(SkStringPrintf("%4.3f ms -> %4.3f ms", time, measure),
+ rect.fLeft + 3, rect.fTop + 14, font, paint);
+
+ for (int timer = 0; timer < fTimers.count(); ++timer) {
+ paint.setColor(fTimers[timer].fLabelColor);
+ canvas->drawString(SkStringPrintf("%s: %4.3f ms", fTimers[timer].fLabel.c_str(),
+ sumTimes[timer] / SkTMax(1, count)),
+ rect.fLeft + 3, rect.fTop + 28 + (14 * timer), font, paint);
+ }
+
+ canvas->restore();
+}
diff --git a/src/third_party/skia/tools/viewer/StatsLayer.h b/src/third_party/skia/tools/viewer/StatsLayer.h
new file mode 100644
index 0000000..79f4a78
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/StatsLayer.h
@@ -0,0 +1,48 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef StatsLayer_DEFINED
+#define StatsLayer_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkString.h"
+#include "tools/sk_app/Window.h"
+
+class StatsLayer : public sk_app::Window::Layer {
+public:
+ StatsLayer();
+ void resetMeasurements();
+
+ typedef int Timer;
+
+ Timer addTimer(const char* label, SkColor color, SkColor labelColor = 0);
+ void beginTiming(Timer);
+ void endTiming(Timer);
+
+ void onPrePaint() override;
+ void onPaint(SkSurface*) override;
+
+ void setDisplayScale(float scale) { fDisplayScale = scale; }
+
+private:
+ static const int kMeasurementCount = 1 << 6; // should be power of 2 for fast mod
+ struct TimerData {
+ double fTimes[kMeasurementCount];
+ SkString fLabel;
+ SkColor fColor;
+ SkColor fLabelColor;
+ };
+ SkTArray<TimerData> fTimers;
+ double fTotalTimes[kMeasurementCount];
+ int fCurrentMeasurement;
+ double fLastTotalBegin;
+ double fCumulativeMeasurementTime;
+ int fCumulativeMeasurementCount;
+ float fDisplayScale;
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/SvgSlide.cpp b/src/third_party/skia/tools/viewer/SvgSlide.cpp
new file mode 100644
index 0000000..512546b
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SvgSlide.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/viewer/SvgSlide.h"
+
+#if defined(SK_XML)
+
+#include "experimental/svg/model/SkSVGDOM.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStream.h"
+
+SvgSlide::SvgSlide(const SkString& name, const SkString& path)
+ : fPath(path) {
+ fName = name;
+}
+
+void SvgSlide::load(SkScalar w, SkScalar h) {
+ fWinSize = SkSize::Make(w, h);
+
+ if (const auto svgStream = SkStream::MakeFromFile(fPath.c_str())) {
+ fDom = SkSVGDOM::MakeFromStream(*svgStream);
+ if (fDom) {
+ fDom->setContainerSize(fWinSize);
+ }
+ }
+}
+
+void SvgSlide::unload() {
+ fDom.reset();
+}
+
+SkISize SvgSlide::getDimensions() const {
+ // We always scale to fill the window.
+ return fWinSize.toCeil();
+}
+
+void SvgSlide::draw(SkCanvas* canvas) {
+ if (fDom) {
+ fDom->render(canvas);
+ }
+}
+
+#endif // SK_XML
diff --git a/src/third_party/skia/tools/viewer/SvgSlide.h b/src/third_party/skia/tools/viewer/SvgSlide.h
new file mode 100644
index 0000000..1744d74
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/SvgSlide.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SvgSlide_DEFINED
+#define SvgSlide_DEFINED
+
+#include "tools/viewer/Slide.h"
+
+class SkSVGDOM;
+
+class SvgSlide final : public Slide {
+public:
+ SvgSlide(const SkString& name, const SkString& path);
+
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void unload() override;
+
+ SkISize getDimensions() const override;
+
+ void draw(SkCanvas*) override;
+private:
+ const SkString fPath;
+
+ SkSize fWinSize = SkSize::MakeEmpty();
+ sk_sp<SkSVGDOM> fDom;
+
+ typedef Slide INHERITED;
+};
+
+#endif // SvgSlide_DEFINED
diff --git a/src/third_party/skia/tools/viewer/TouchGesture.cpp b/src/third_party/skia/tools/viewer/TouchGesture.cpp
new file mode 100644
index 0000000..4bef1f2
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/TouchGesture.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <algorithm>
+
+#include "include/core/SkMatrix.h"
+#include "include/core/SkTime.h"
+#include "tools/viewer/TouchGesture.h"
+
+#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER true
+
+static const SkScalar MAX_FLING_SPEED = SkIntToScalar(1500);
+
+static SkScalar pin_max_fling(SkScalar speed) {
+ if (speed > MAX_FLING_SPEED) {
+ speed = MAX_FLING_SPEED;
+ }
+ return speed;
+}
+
+static double getseconds() {
+ return SkTime::GetMSecs() * 0.001;
+}
+
+// returns +1 or -1, depending on the sign of x
+// returns +1 if z is zero
+static SkScalar SkScalarSignNonZero(SkScalar x) {
+ SkScalar sign = SK_Scalar1;
+ if (x < 0) {
+ sign = -sign;
+ }
+ return sign;
+}
+
+static void unit_axis_align(SkVector* unit) {
+ const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
+ if (SkScalarAbs(unit->fX) < TOLERANCE) {
+ unit->fX = 0;
+ unit->fY = SkScalarSignNonZero(unit->fY);
+ } else if (SkScalarAbs(unit->fY) < TOLERANCE) {
+ unit->fX = SkScalarSignNonZero(unit->fX);
+ unit->fY = 0;
+ }
+}
+
+void TouchGesture::FlingState::reset(float sx, float sy) {
+ fActive = true;
+ fDirection.set(sx, sy);
+ fSpeed0 = SkPoint::Normalize(&fDirection);
+ fSpeed0 = pin_max_fling(fSpeed0);
+ fTime0 = getseconds();
+
+ unit_axis_align(&fDirection);
+// printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
+}
+
+bool TouchGesture::FlingState::evaluateMatrix(SkMatrix* matrix) {
+ if (!fActive) {
+ return false;
+ }
+
+ const float t = (float)(getseconds() - fTime0);
+ const float MIN_SPEED = 2;
+ const float K0 = 5;
+ const float K1 = 0.02f;
+ const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
+ if (speed <= MIN_SPEED) {
+ fActive = false;
+ return false;
+ }
+ float dist = (fSpeed0 - speed) / K0;
+
+// printf("---- time %g speed %g dist %g\n", t, speed, dist);
+ float tx = fDirection.fX * dist;
+ float ty = fDirection.fY * dist;
+ if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
+ tx = (float)sk_float_round2int(tx);
+ ty = (float)sk_float_round2int(ty);
+ }
+ matrix->setTranslate(tx, ty);
+// printf("---- evaluate (%g %g)\n", tx, ty);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const SkMSec MAX_DBL_TAP_INTERVAL = 300;
+static const float MAX_DBL_TAP_DISTANCE = 100;
+static const float MAX_JITTER_RADIUS = 2;
+
+// if true, then ignore the touch-move, 'cause its probably just jitter
+static bool close_enough_for_jitter(float x0, float y0, float x1, float y1) {
+ return sk_float_abs(x0 - x1) <= MAX_JITTER_RADIUS &&
+ sk_float_abs(y0 - y1) <= MAX_JITTER_RADIUS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+TouchGesture::TouchGesture() {
+ this->reset();
+}
+
+TouchGesture::~TouchGesture() {
+}
+
+void TouchGesture::resetTouchState() {
+ fIsTransLimited = false;
+ fTouches.reset();
+ fState = kEmpty_State;
+ fLocalM.reset();
+
+ fLastUpMillis = SkTime::GetMSecs() - 2*MAX_DBL_TAP_INTERVAL;
+ fLastUpP.set(0, 0);
+}
+
+void TouchGesture::reset() {
+ fGlobalM.reset();
+ this->resetTouchState();
+}
+
+void TouchGesture::flushLocalM() {
+ fGlobalM.postConcat(fLocalM);
+ fLocalM.reset();
+}
+
+const SkMatrix& TouchGesture::localM() {
+ if (fFlinger.isActive()) {
+ if (!fFlinger.evaluateMatrix(&fLocalM)) {
+ this->flushLocalM();
+ }
+ }
+ return fLocalM;
+}
+
+void TouchGesture::appendNewRec(void* owner, float x, float y) {
+ Rec* rec = fTouches.append();
+ rec->fOwner = owner;
+ rec->fStartX = rec->fPrevX = rec->fLastX = x;
+ rec->fStartY = rec->fPrevY = rec->fLastY = y;
+ rec->fLastT = rec->fPrevT = static_cast<float>(SkTime::GetSecs());
+}
+
+void TouchGesture::touchBegin(void* owner, float x, float y) {
+// SkDebugf("--- %d touchBegin %p %g %g\n", fTouches.count(), owner, x, y);
+
+ int index = this->findRec(owner);
+ if (index >= 0) {
+ this->flushLocalM();
+ fTouches.removeShuffle(index);
+ SkDebugf("---- already exists, removing\n");
+ }
+
+ if (fTouches.count() == 2) {
+ return;
+ }
+
+ this->flushLocalM();
+ fFlinger.stop();
+
+ this->appendNewRec(owner, x, y);
+
+ switch (fTouches.count()) {
+ case 1:
+ fState = kTranslate_State;
+ break;
+ case 2:
+ this->startZoom();
+ break;
+ default:
+ break;
+ }
+}
+
+int TouchGesture::findRec(void* owner) const {
+ for (int i = 0; i < fTouches.count(); i++) {
+ if (owner == fTouches[i].fOwner) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static SkScalar center(float pos0, float pos1) {
+ return (pos0 + pos1) * 0.5f;
+}
+
+static const float MAX_ZOOM_SCALE = 4;
+static const float MIN_ZOOM_SCALE = 0.25f;
+
+float TouchGesture::limitTotalZoom(float scale) const {
+ // this query works 'cause we know that we're square-scale w/ no skew/rotation
+ const float curr = SkScalarToFloat(fGlobalM[0]);
+
+ if (scale > 1 && curr * scale > MAX_ZOOM_SCALE) {
+ scale = MAX_ZOOM_SCALE / curr;
+ } else if (scale < 1 && curr * scale < MIN_ZOOM_SCALE) {
+ scale = MIN_ZOOM_SCALE / curr;
+ }
+ return scale;
+}
+
+void TouchGesture::startZoom() {
+ fState = kZoom_State;
+}
+
+void TouchGesture::updateZoom(float scale, float startX, float startY, float lastX, float lastY) {
+ scale = this->limitTotalZoom(scale);
+
+ fLocalM.setTranslate(-startX, -startY);
+ fLocalM.postScale(scale, scale);
+ fLocalM.postTranslate(lastX, lastY);
+}
+
+void TouchGesture::endZoom() {
+ this->flushLocalM();
+ SkASSERT(kZoom_State == fState);
+ fState = kEmpty_State;
+}
+
+void TouchGesture::touchMoved(void* owner, float x, float y) {
+// SkDebugf("--- %d touchMoved %p %g %g\n", fTouches.count(), owner, x, y);
+
+ if (kEmpty_State == fState) {
+ return;
+ }
+
+ int index = this->findRec(owner);
+ if (index < 0) {
+ SkDebugf("---- ignoring move without begin\n");
+ return;
+ }
+
+ Rec& rec = fTouches[index];
+
+ // not sure how valuable this is
+ if (fTouches.count() == 2) {
+ if (close_enough_for_jitter(rec.fLastX, rec.fLastY, x, y)) {
+// SkDebugf("--- drop touchMove, within jitter tolerance %g %g\n", rec.fLastX - x, rec.fLastY - y);
+ return;
+ }
+ }
+
+ rec.fPrevX = rec.fLastX; rec.fLastX = x;
+ rec.fPrevY = rec.fLastY; rec.fLastY = y;
+ rec.fPrevT = rec.fLastT;
+ rec.fLastT = static_cast<float>(SkTime::GetSecs());
+
+ switch (fTouches.count()) {
+ case 1: {
+ float dx = rec.fLastX - rec.fStartX;
+ float dy = rec.fLastY - rec.fStartY;
+ dx = (float)sk_float_round2int(dx);
+ dy = (float)sk_float_round2int(dy);
+ fLocalM.setTranslate(dx, dy);
+ } break;
+ case 2: {
+ SkASSERT(kZoom_State == fState);
+ const Rec& rec0 = fTouches[0];
+ const Rec& rec1 = fTouches[1];
+
+ float scale = this->computePinch(rec0, rec1);
+ this->updateZoom(scale,
+ center(rec0.fStartX, rec1.fStartX),
+ center(rec0.fStartY, rec1.fStartY),
+ center(rec0.fLastX, rec1.fLastX),
+ center(rec0.fLastY, rec1.fLastY));
+ } break;
+ default:
+ break;
+ }
+}
+
+void TouchGesture::touchEnd(void* owner) {
+// SkDebugf("--- %d touchEnd %p\n", fTouches.count(), owner);
+
+ int index = this->findRec(owner);
+ if (index < 0) {
+ SkDebugf("--- not found\n");
+ return;
+ }
+
+ const Rec& rec = fTouches[index];
+ if (this->handleDblTap(rec.fLastX, rec.fLastY)) {
+ return;
+ }
+
+ // count() reflects the number before we removed the owner
+ switch (fTouches.count()) {
+ case 1: {
+ this->flushLocalM();
+ float dx = rec.fLastX - rec.fPrevX;
+ float dy = rec.fLastY - rec.fPrevY;
+ float dur = rec.fLastT - rec.fPrevT;
+ if (dur > 0) {
+ fFlinger.reset(dx / dur, dy / dur);
+ }
+ fState = kEmpty_State;
+ } break;
+ case 2:
+ this->endZoom();
+ break;
+ default:
+ SkASSERT(kZoom_State == fState);
+ break;
+ }
+
+ fTouches.removeShuffle(index);
+
+ limitTrans();
+}
+
+bool TouchGesture::isFling(SkPoint* dir) {
+ if (fFlinger.isActive()) {
+ SkScalar speed;
+ fFlinger.get(dir, &speed);
+ if (speed > 1000) {
+ return true;
+ }
+ }
+ return false;
+}
+
+float TouchGesture::computePinch(const Rec& rec0, const Rec& rec1) {
+ double dx = rec0.fStartX - rec1.fStartX;
+ double dy = rec0.fStartY - rec1.fStartY;
+ double dist0 = sqrt(dx*dx + dy*dy);
+
+ dx = rec0.fLastX - rec1.fLastX;
+ dy = rec0.fLastY - rec1.fLastY;
+ double dist1 = sqrt(dx*dx + dy*dy);
+
+ double scale = dist1 / dist0;
+ return (float)scale;
+}
+
+bool TouchGesture::handleDblTap(float x, float y) {
+ bool found = false;
+ double now = SkTime::GetMSecs();
+ if (now - fLastUpMillis <= MAX_DBL_TAP_INTERVAL) {
+ if (SkPoint::Length(fLastUpP.fX - x,
+ fLastUpP.fY - y) <= MAX_DBL_TAP_DISTANCE) {
+ fFlinger.stop();
+ fLocalM.reset();
+ fGlobalM.reset();
+ fTouches.reset();
+ fState = kEmpty_State;
+ found = true;
+ }
+ }
+
+ fLastUpMillis = now;
+ fLastUpP.set(x, y);
+ return found;
+}
+
+void TouchGesture::setTransLimit(const SkRect& contentRect, const SkRect& windowRect,
+ const SkMatrix& preTouchMatrix) {
+ fIsTransLimited = true;
+ fContentRect = contentRect;
+ fWindowRect = windowRect;
+ fPreTouchM = preTouchMatrix;
+}
+
+void TouchGesture::limitTrans() {
+ if (!fIsTransLimited) {
+ return;
+ }
+
+ SkRect scaledContent = fContentRect;
+ fPreTouchM.mapRect(&scaledContent);
+ fGlobalM.mapRect(&scaledContent);
+ const SkScalar ZERO = 0;
+
+ fGlobalM.postTranslate(ZERO, std::min(ZERO, fWindowRect.fBottom - scaledContent.fTop));
+ fGlobalM.postTranslate(ZERO, std::max(ZERO, fWindowRect.fTop - scaledContent.fBottom));
+ fGlobalM.postTranslate(std::min(ZERO, fWindowRect.fRight - scaledContent.fLeft), ZERO);
+ fGlobalM.postTranslate(std::max(ZERO, fWindowRect.fLeft - scaledContent.fRight), ZERO);
+}
diff --git a/src/third_party/skia/tools/viewer/TouchGesture.h b/src/third_party/skia/tools/viewer/TouchGesture.h
new file mode 100644
index 0000000..475b438
--- /dev/null
+++ b/src/third_party/skia/tools/viewer/TouchGesture.h
@@ -0,0 +1,96 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef TouchGesture_DEFINED
+#define TouchGesture_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "include/private/SkTDArray.h"
+
+class TouchGesture {
+public:
+ TouchGesture();
+ ~TouchGesture();
+
+ void touchBegin(void* owner, float x, float y);
+ void touchMoved(void* owner, float x, float y);
+ void touchEnd(void* owner);
+ void reset();
+ void resetTouchState();
+
+ bool isActive() { return fFlinger.isActive(); }
+ void stop() { fFlinger.stop(); }
+ bool isBeingTouched() { return kEmpty_State != fState; }
+ bool isFling(SkPoint* dir);
+
+ void startZoom();
+ void updateZoom(float scale, float startX, float startY, float lastX, float lastY);
+ void endZoom();
+
+ const SkMatrix& localM();
+ const SkMatrix& globalM() const { return fGlobalM; }
+
+ void setTransLimit(const SkRect& contentRect, const SkRect& windowRect,
+ const SkMatrix& preTouchM);
+
+private:
+ enum State {
+ kEmpty_State,
+ kTranslate_State,
+ kZoom_State,
+ };
+
+ struct Rec {
+ void* fOwner;
+ float fStartX, fStartY;
+ float fPrevX, fPrevY;
+ float fLastX, fLastY;
+ float fPrevT, fLastT;
+ };
+ SkTDArray<Rec> fTouches;
+
+ State fState;
+ SkMatrix fLocalM, fGlobalM, fPreTouchM;
+
+ struct FlingState {
+ FlingState() : fActive(false) {}
+
+ bool isActive() const { return fActive; }
+ void stop() { fActive = false; }
+
+ void reset(float sx, float sy);
+ bool evaluateMatrix(SkMatrix* matrix);
+
+ void get(SkPoint* dir, SkScalar* speed) {
+ *dir = fDirection;
+ *speed = fSpeed0;
+ }
+
+ private:
+ SkPoint fDirection;
+ SkScalar fSpeed0;
+ double fTime0;
+ bool fActive;
+ };
+ FlingState fFlinger;
+ double fLastUpMillis;
+ SkPoint fLastUpP;
+
+ // The following rects are used to limit the translation so the content never leaves the window
+ SkRect fContentRect, fWindowRect;
+ bool fIsTransLimited = false;
+
+ void limitTrans(); // here we only limit the translation with respect to globalM
+ void flushLocalM();
+ int findRec(void* owner) const;
+ void appendNewRec(void* owner, float x, float y);
+ float computePinch(const Rec&, const Rec&);
+ float limitTotalZoom(float scale) const;
+ bool handleDblTap(float, float);
+};
+
+#endif
diff --git a/src/third_party/skia/tools/viewer/Viewer.cpp b/src/third_party/skia/tools/viewer/Viewer.cpp
index 6753b6b..f02f5b9 100644
--- a/src/third_party/skia/tools/viewer/Viewer.cpp
+++ b/src/third_party/skia/tools/viewer/Viewer.cpp
@@ -5,179 +5,169 @@
* found in the LICENSE file.
*/
-#include "Viewer.h"
-
-#include "GMSlide.h"
-#include "ImageSlide.h"
-#include "Resources.h"
-#include "SampleSlide.h"
-#include "SKPSlide.h"
-
-#include "GrContext.h"
-#include "SkATrace.h"
-#include "SkCanvas.h"
-#include "SkColorSpace_Base.h"
-#include "SkColorSpaceXformCanvas.h"
-#include "SkCommandLineFlags.h"
-#include "SkCommonFlagsPathRenderer.h"
-#include "SkDashPathEffect.h"
-#include "SkGraphics.h"
-#include "SkImagePriv.h"
-#include "SkMetaData.h"
-#include "SkOnce.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkRandom.h"
-#include "SkStream.h"
-#include "SkSurface.h"
-#include "SkSwizzle.h"
-#include "SkTaskGroup.h"
-#include "SkTime.h"
-#include "SkVertices.h"
-
-#include "imgui.h"
-
-#include "ccpr/GrCoverageCountingPathRenderer.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkData.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkPictureRecorder.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrContext.h"
+#include "include/private/SkTo.h"
+#include "include/utils/SkPaintFilterCanvas.h"
+#include "src/core/SkColorSpacePriv.h"
+#include "src/core/SkImagePriv.h"
+#include "src/core/SkMD5.h"
+#include "src/core/SkMakeUnique.h"
+#include "src/core/SkOSFile.h"
+#include "src/core/SkScan.h"
+#include "src/core/SkTaskGroup.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrPersistentCacheUtils.h"
+#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
+#include "src/utils/SkJSONWriter.h"
+#include "src/utils/SkOSPath.h"
+#include "tools/Resources.h"
+#include "tools/ToolUtils.h"
+#include "tools/flags/CommandLineFlags.h"
+#include "tools/flags/CommonFlags.h"
+#include "tools/trace/EventTracingPriv.h"
+#include "tools/viewer/BisectSlide.h"
+#include "tools/viewer/GMSlide.h"
+#include "tools/viewer/ImageSlide.h"
+#include "tools/viewer/ParticlesSlide.h"
+#include "tools/viewer/SKPSlide.h"
+#include "tools/viewer/SampleSlide.h"
+#include "tools/viewer/SlideDir.h"
+#include "tools/viewer/SvgSlide.h"
+#include "tools/viewer/Viewer.h"
#include <stdlib.h>
#include <map>
+#include "imgui.h"
+#include "misc/cpp/imgui_stdlib.h" // For ImGui support of std::string
+
+#if defined(SK_ENABLE_SKOTTIE)
+ #include "tools/viewer/SkottieSlide.h"
+#endif
+
+class CapturingShaderErrorHandler : public GrContextOptions::ShaderErrorHandler {
+public:
+ void compileError(const char* shader, const char* errors) override {
+ fShaders.push_back(SkString(shader));
+ fErrors.push_back(SkString(errors));
+ }
+
+ void reset() {
+ fShaders.reset();
+ fErrors.reset();
+ }
+
+ SkTArray<SkString> fShaders;
+ SkTArray<SkString> fErrors;
+};
+
+static CapturingShaderErrorHandler gShaderErrorHandler;
+
using namespace sk_app;
-using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
static std::map<GpuPathRenderers, std::string> gPathRendererNames;
Application* Application::Create(int argc, char** argv, void* platformData) {
return new Viewer(argc, argv, platformData);
}
-static void on_backend_created_func(void* userData) {
- Viewer* vv = reinterpret_cast<Viewer*>(userData);
+static DEFINE_string(slide, "", "Start on this sample.");
+static DEFINE_bool(list, false, "List samples?");
- return vv->onBackendCreated();
-}
-
-static void on_paint_handler(SkCanvas* canvas, void* userData) {
- Viewer* vv = reinterpret_cast<Viewer*>(userData);
-
- return vv->onPaint(canvas);
-}
-
-static bool on_touch_handler(intptr_t owner, Window::InputState state, float x, float y, void* userData)
-{
- Viewer* viewer = reinterpret_cast<Viewer*>(userData);
-
- return viewer->onTouch(owner, state, x, y);
-}
-
-static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) {
- Viewer* viewer = reinterpret_cast<Viewer*>(userData);
-
- return viewer->onUIStateChanged(stateName, stateValue);
-}
-
-static bool on_mouse_handler(int x, int y, Window::InputState state, uint32_t modifiers,
- void* userData) {
- ImGuiIO& io = ImGui::GetIO();
- io.MousePos.x = static_cast<float>(x);
- io.MousePos.y = static_cast<float>(y);
- if (Window::kDown_InputState == state) {
- io.MouseDown[0] = true;
- } else if (Window::kUp_InputState == state) {
- io.MouseDown[0] = false;
- }
- if (io.WantCaptureMouse) {
- return true;
- } else {
- Viewer* viewer = reinterpret_cast<Viewer*>(userData);
- return viewer->onMouse(x, y, state, modifiers);
- }
-}
-
-static bool on_mouse_wheel_handler(float delta, uint32_t modifiers, void* userData) {
- ImGuiIO& io = ImGui::GetIO();
- io.MouseWheel += delta;
- return true;
-}
-
-static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
- void* userData) {
- ImGuiIO& io = ImGui::GetIO();
- io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
-
- if (io.WantCaptureKeyboard) {
- return true;
- } else {
- Viewer* viewer = reinterpret_cast<Viewer*>(userData);
- return viewer->onKey(key, state, modifiers);
- }
-}
-
-static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
- ImGuiIO& io = ImGui::GetIO();
- if (io.WantTextInput) {
- if (c > 0 && c < 0x10000) {
- io.AddInputCharacter(c);
- }
- return true;
- } else {
- Viewer* viewer = reinterpret_cast<Viewer*>(userData);
- return viewer->onChar(c, modifiers);
- }
-}
-
-static DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
-
-static DEFINE_string2(match, m, nullptr,
- "[~][^]substring[$] [...] of bench name to run.\n"
- "Multiple matches may be separated by spaces.\n"
- "~ causes a matching bench to always be skipped\n"
- "^ requires the start of the bench to match\n"
- "$ requires the end of the bench to match\n"
- "^ and $ requires an exact match\n"
- "If a bench does not match any list entry,\n"
- "it is skipped unless some list entry starts with ~");
-
-DEFINE_string(slide, "", "Start on this sample.");
-DEFINE_bool(list, false, "List samples?");
-
-#ifdef SK_VULKAN
+#if defined(SK_VULKAN)
# define BACKENDS_STR "\"sw\", \"gl\", and \"vk\""
+#elif defined(SK_METAL) && defined(SK_BUILD_FOR_MAC)
+# define BACKENDS_STR "\"sw\", \"gl\", and \"mtl\""
+#elif defined(SK_DAWN)
+# define BACKENDS_STR "\"sw\", \"gl\", and \"dawn\""
#else
# define BACKENDS_STR "\"sw\" and \"gl\""
#endif
-#ifdef SK_BUILD_FOR_ANDROID
-static DEFINE_string(skps, "/data/local/tmp/skps", "Directory to read skps from.");
-static DEFINE_string(jpgs, "/data/local/tmp/resources", "Directory to read jpgs from.");
-#else
-static DEFINE_string(skps, "skps", "Directory to read skps from.");
-static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
-#endif
-
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
-static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android.");
+static DEFINE_int(msaa, 1, "Number of subpixel samples. 0 for no HW antialiasing.");
-DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
-DEFINE_pathrenderer_flag;
+static DEFINE_int(internalSamples, 4,
+ "Number of samples for internal draws that use MSAA or mixed samples.");
-DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");
+static DEFINE_string(bisect, "", "Path to a .skp or .svg file to bisect.");
-const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
+static DEFINE_string2(file, f, "", "Open a single file for viewing.");
+
+static DEFINE_string2(match, m, nullptr,
+ "[~][^]substring[$] [...] of name to run.\n"
+ "Multiple matches may be separated by spaces.\n"
+ "~ causes a matching name to always be skipped\n"
+ "^ requires the start of the name to match\n"
+ "$ requires the end of the name to match\n"
+ "^ and $ requires an exact match\n"
+ "If a name does not match any list entry,\n"
+ "it is skipped unless some list entry starts with ~");
+
+#if defined(SK_BUILD_FOR_ANDROID)
+ static DEFINE_string(jpgs, "/data/local/tmp/resources", "Directory to read jpgs from.");
+ static DEFINE_string(skps, "/data/local/tmp/skps", "Directory to read skps from.");
+ static DEFINE_string(lotties, "/data/local/tmp/lotties",
+ "Directory to read (Bodymovin) jsons from.");
+#else
+ static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
+ static DEFINE_string(skps, "skps", "Directory to read skps from.");
+ static DEFINE_string(lotties, "lotties", "Directory to read (Bodymovin) jsons from.");
+#endif
+
+static DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
+
+static DEFINE_int_2(threads, j, -1,
+ "Run threadsafe tests on a threadpool with this many extra threads, "
+ "defaulting to one extra thread per core.");
+
+
+const char* kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
"OpenGL",
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ "ANGLE",
+#endif
+#ifdef SK_DAWN
+ "Dawn",
+#endif
#ifdef SK_VULKAN
"Vulkan",
#endif
+#ifdef SK_METAL
+ "Metal",
+#endif
"Raster"
};
static sk_app::Window::BackendType get_backend_type(const char* str) {
+#ifdef SK_DAWN
+ if (0 == strcmp(str, "dawn")) {
+ return sk_app::Window::kDawn_BackendType;
+ } else
+#endif
#ifdef SK_VULKAN
if (0 == strcmp(str, "vk")) {
return sk_app::Window::kVulkan_BackendType;
} else
#endif
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ if (0 == strcmp(str, "angle")) {
+ return sk_app::Window::kANGLE_BackendType;
+ } else
+#endif
+#ifdef SK_METAL
+ if (0 == strcmp(str, "mtl")) {
+ return sk_app::Window::kMetal_BackendType;
+ } else
+#endif
if (0 == strcmp(str, "gl")) {
return sk_app::Window::kNativeGL_BackendType;
} else if (0 == strcmp(str, "sw")) {
@@ -226,6 +216,22 @@
return memcmp(&a, &b, sizeof(SkColorSpacePrimaries)) == 0;
}
+static Window::BackendType backend_type_for_window(Window::BackendType backendType) {
+ // In raster mode, we still use GL for the window.
+ // This lets us render the GUI faster (and correct).
+ return Window::kRaster_BackendType == backendType ? Window::kNativeGL_BackendType : backendType;
+}
+
+class NullSlide : public Slide {
+ SkISize getDimensions() const override {
+ return SkISize::Make(640, 480);
+ }
+
+ void draw(SkCanvas* canvas) override {
+ canvas->clear(0xffff11ff);
+ }
+};
+
const char* kName = "name";
const char* kValue = "value";
const char* kOptions = "options";
@@ -233,7 +239,6 @@
const char* kBackendStateName = "Backend";
const char* kMSAAStateName = "MSAA";
const char* kPathRendererStateName = "Path renderer";
-const char* kInstancedRenderingStateName = "Instanced rendering";
const char* kSoftkeyStateName = "Softkey";
const char* kSoftkeyHint = "Please select a softkey";
const char* kFpsStateName = "FPS";
@@ -242,37 +247,40 @@
const char* kRefreshStateName = "Refresh";
Viewer::Viewer(int argc, char** argv, void* platformData)
- : fCurrentMeasurement(0)
- , fDisplayStats(false)
+ : fCurrentSlide(-1)
, fRefresh(false)
+ , fSaveToSKP(false)
+ , fShowSlideDimensions(false)
, fShowImGuiDebugWindow(false)
+ , fShowSlidePicker(false)
, fShowImGuiTestWindow(false)
, fShowZoomWindow(false)
+ , fZoomWindowFixed(false)
+ , fZoomWindowLocation{0.0f, 0.0f}
, fLastImage(nullptr)
+ , fZoomUI(false)
, fBackendType(sk_app::Window::kNativeGL_BackendType)
, fColorMode(ColorMode::kLegacy)
, fColorSpacePrimaries(gSrgbPrimaries)
+ // Our UI can only tweak gamma (currently), so start out gamma-only
+ , fColorSpaceTransferFn(SkNamedTransferFn::k2Dot2)
, fZoomLevel(0.0f)
+ , fRotation(0.0f)
+ , fOffset{0.5f, 0.5f}
, fGestureDevice(GestureDevice::kNone)
+ , fTiled(false)
+ , fDrawTileBoundaries(false)
+ , fTileScale{0.25f, 0.25f}
+ , fPerspectiveMode(kPerspective_Off)
{
- static SkTaskGroup::Enabler kTaskGroupEnabler;
SkGraphics::Init();
- static SkOnce initPathRendererNames;
- initPathRendererNames([]() {
- gPathRendererNames[GpuPathRenderers::kAll] = "Default Ganesh Behavior (best path renderer)";
- gPathRendererNames[GpuPathRenderers::kStencilAndCover] = "NV_path_rendering";
- gPathRendererNames[GpuPathRenderers::kMSAA] = "Sample shading";
- gPathRendererNames[GpuPathRenderers::kSmall] = "Small paths (cached sdf or alpha masks)";
- gPathRendererNames[GpuPathRenderers::kCoverageCounting] = "Coverage counting";
- gPathRendererNames[GpuPathRenderers::kTessellating] = "Tessellating";
- gPathRendererNames[GpuPathRenderers::kDefault] = "Original Ganesh path renderer";
- gPathRendererNames[GpuPathRenderers::kNone] = "Software masks";
- });
-
- memset(fPaintTimes, 0, sizeof(fPaintTimes));
- memset(fFlushTimes, 0, sizeof(fFlushTimes));
- memset(fAnimateTimes, 0, sizeof(fAnimateTimes));
+ gPathRendererNames[GpuPathRenderers::kAll] = "All Path Renderers";
+ gPathRendererNames[GpuPathRenderers::kStencilAndCover] = "NV_path_rendering";
+ gPathRendererNames[GpuPathRenderers::kSmall] = "Small paths (cached sdf or alpha masks)";
+ gPathRendererNames[GpuPathRenderers::kCoverageCounting] = "CCPR";
+ gPathRendererNames[GpuPathRenderers::kTessellating] = "Tessellating";
+ gPathRendererNames[GpuPathRenderers::kNone] = "Software masks";
SkDebugf("Command line arguments: ");
for (int i = 1; i < argc; ++i) {
@@ -280,40 +288,59 @@
}
SkDebugf("\n");
- SkCommandLineFlags::Parse(argc, argv);
+ CommandLineFlags::Parse(argc, argv);
#ifdef SK_BUILD_FOR_ANDROID
SetResourcePath("/data/local/tmp/resources");
#endif
- if (FLAGS_atrace) {
- SkAssertResult(SkEventTracer::SetInstance(new SkATrace()));
- }
+ ToolUtils::SetDefaultFontMgr();
+
+ initializeEventTracingForTools();
+ static SkTaskGroup::Enabler kTaskGroupEnabler(FLAGS_threads);
fBackendType = get_backend_type(FLAGS_backend[0]);
fWindow = Window::CreateNativeWindow(platformData);
DisplayParams displayParams;
displayParams.fMSAASampleCount = FLAGS_msaa;
- displayParams.fGrContextOptions.fEnableInstancedRendering = FLAGS_instancedRendering;
- displayParams.fGrContextOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+ SetCtxOptionsFromCommonFlags(&displayParams.fGrContextOptions);
+ displayParams.fGrContextOptions.fPersistentCache = &fPersistentCache;
+ displayParams.fGrContextOptions.fShaderCacheStrategy =
+ GrContextOptions::ShaderCacheStrategy::kBackendSource;
+ displayParams.fGrContextOptions.fShaderErrorHandler = &gShaderErrorHandler;
+ displayParams.fGrContextOptions.fSuppressPrints = true;
+ displayParams.fGrContextOptions.fInternalMultisampleCount = FLAGS_internalSamples;
fWindow->setRequestedDisplayParams(displayParams);
+ // Configure timers
+ fStatsLayer.setActive(false);
+ fAnimateTimer = fStatsLayer.addTimer("Animate", SK_ColorMAGENTA, 0xffff66ff);
+ fPaintTimer = fStatsLayer.addTimer("Paint", SK_ColorGREEN);
+ fFlushTimer = fStatsLayer.addTimer("Flush", SK_ColorRED, 0xffff6666);
+
// register callbacks
fCommands.attach(fWindow);
- fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
- fWindow->registerPaintFunc(on_paint_handler, this);
- fWindow->registerTouchFunc(on_touch_handler, this);
- fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
- fWindow->registerMouseFunc(on_mouse_handler, this);
- fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
- fWindow->registerKeyFunc(on_key_handler, this);
- fWindow->registerCharFunc(on_char_handler, this);
+ fWindow->pushLayer(this);
+ fWindow->pushLayer(&fStatsLayer);
+ fWindow->pushLayer(&fImGuiLayer);
// add key-bindings
fCommands.addCommand(' ', "GUI", "Toggle Debug GUI", [this]() {
this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
fWindow->inval();
});
+ // Command to jump directly to the slide picker and give it focus
+ fCommands.addCommand('/', "GUI", "Jump to slide picker", [this]() {
+ this->fShowImGuiDebugWindow = true;
+ this->fShowSlidePicker = true;
+ fWindow->inval();
+ });
+ // Alias that to Backspace, to match SampleApp
+ fCommands.addCommand(skui::Key::kBack, "Backspace", "GUI", "Jump to slide picker", [this]() {
+ this->fShowImGuiDebugWindow = true;
+ this->fShowSlidePicker = true;
+ fWindow->inval();
+ });
fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() {
this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
fWindow->inval();
@@ -322,208 +349,405 @@
this->fShowZoomWindow = !this->fShowZoomWindow;
fWindow->inval();
});
+ fCommands.addCommand('Z', "GUI", "Toggle zoom window state", [this]() {
+ this->fZoomWindowFixed = !this->fZoomWindowFixed;
+ fWindow->inval();
+ });
+ fCommands.addCommand('v', "VSync", "Toggle vsync on/off", [this]() {
+ DisplayParams params = fWindow->getRequestedDisplayParams();
+ params.fDisableVsync = !params.fDisableVsync;
+ fWindow->setRequestedDisplayParams(params);
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('r', "Redraw", "Toggle redraw", [this]() {
+ fRefresh = !fRefresh;
+ fWindow->inval();
+ });
fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
- this->fDisplayStats = !this->fDisplayStats;
+ fStatsLayer.setActive(!fStatsLayer.getActive());
+ fWindow->inval();
+ });
+ fCommands.addCommand('0', "Overlays", "Reset stats", [this]() {
+ fStatsLayer.resetMeasurements();
+ this->updateTitle();
fWindow->inval();
});
fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() {
switch (fColorMode) {
case ColorMode::kLegacy:
- this->setColorMode(ColorMode::kColorManagedSRGB8888_NonLinearBlending);
+ this->setColorMode(ColorMode::kColorManaged8888);
break;
- case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
- this->setColorMode(ColorMode::kColorManagedSRGB8888);
+ case ColorMode::kColorManaged8888:
+ this->setColorMode(ColorMode::kColorManagedF16);
break;
- case ColorMode::kColorManagedSRGB8888:
- this->setColorMode(ColorMode::kColorManagedLinearF16);
+ case ColorMode::kColorManagedF16:
+ this->setColorMode(ColorMode::kColorManagedF16Norm);
break;
- case ColorMode::kColorManagedLinearF16:
+ case ColorMode::kColorManagedF16Norm:
this->setColorMode(ColorMode::kLegacy);
break;
}
});
- fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() {
- int previousSlide = fCurrentSlide;
- fCurrentSlide++;
- if (fCurrentSlide >= fSlides.count()) {
- fCurrentSlide = 0;
- }
- this->setupCurrentSlide(previousSlide);
+ fCommands.addCommand(skui::Key::kRight, "Right", "Navigation", "Next slide", [this]() {
+ this->setCurrentSlide(fCurrentSlide < fSlides.count() - 1 ? fCurrentSlide + 1 : 0);
});
- fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() {
- int previousSlide = fCurrentSlide;
- fCurrentSlide--;
- if (fCurrentSlide < 0) {
- fCurrentSlide = fSlides.count() - 1;
- }
- this->setupCurrentSlide(previousSlide);
+ fCommands.addCommand(skui::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() {
+ this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.count() - 1);
});
- fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() {
+ fCommands.addCommand(skui::Key::kUp, "Up", "Transform", "Zoom in", [this]() {
this->changeZoomLevel(1.f / 32.f);
fWindow->inval();
});
- fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() {
+ fCommands.addCommand(skui::Key::kDown, "Down", "Transform", "Zoom out", [this]() {
this->changeZoomLevel(-1.f / 32.f);
fWindow->inval();
});
fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() {
- sk_app::Window::BackendType newBackend = fBackendType;
-#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
- if (sk_app::Window::kRaster_BackendType == fBackendType) {
- newBackend = sk_app::Window::kNativeGL_BackendType;
-#ifdef SK_VULKAN
- } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
- newBackend = sk_app::Window::kVulkan_BackendType;
-#endif
- } else {
- newBackend = sk_app::Window::kRaster_BackendType;
- }
-#elif defined(SK_BUILD_FOR_UNIX)
+ sk_app::Window::BackendType newBackend = (sk_app::Window::BackendType)(
+ (fBackendType + 1) % sk_app::Window::kBackendTypeCount);
// Switching to and from Vulkan is problematic on Linux so disabled for now
- if (sk_app::Window::kRaster_BackendType == fBackendType) {
- newBackend = sk_app::Window::kNativeGL_BackendType;
- } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
- newBackend = sk_app::Window::kRaster_BackendType;
+#if defined(SK_BUILD_FOR_UNIX) && defined(SK_VULKAN)
+ if (newBackend == sk_app::Window::kVulkan_BackendType) {
+ newBackend = (sk_app::Window::BackendType)((newBackend + 1) %
+ sk_app::Window::kBackendTypeCount);
+ } else if (fBackendType == sk_app::Window::kVulkan_BackendType) {
+ newBackend = sk_app::Window::kVulkan_BackendType;
}
#endif
-
this->setBackend(newBackend);
});
+ fCommands.addCommand('K', "IO", "Save slide to SKP", [this]() {
+ fSaveToSKP = true;
+ fWindow->inval();
+ });
+ fCommands.addCommand('&', "Overlays", "Show slide dimensios", [this]() {
+ fShowSlideDimensions = !fShowSlideDimensions;
+ fWindow->inval();
+ });
+ fCommands.addCommand('G', "Modes", "Geometry", [this]() {
+ DisplayParams params = fWindow->getRequestedDisplayParams();
+ uint32_t flags = params.fSurfaceProps.flags();
+ if (!fPixelGeometryOverrides) {
+ fPixelGeometryOverrides = true;
+ params.fSurfaceProps = SkSurfaceProps(flags, kUnknown_SkPixelGeometry);
+ } else {
+ switch (params.fSurfaceProps.pixelGeometry()) {
+ case kUnknown_SkPixelGeometry:
+ params.fSurfaceProps = SkSurfaceProps(flags, kRGB_H_SkPixelGeometry);
+ break;
+ case kRGB_H_SkPixelGeometry:
+ params.fSurfaceProps = SkSurfaceProps(flags, kBGR_H_SkPixelGeometry);
+ break;
+ case kBGR_H_SkPixelGeometry:
+ params.fSurfaceProps = SkSurfaceProps(flags, kRGB_V_SkPixelGeometry);
+ break;
+ case kRGB_V_SkPixelGeometry:
+ params.fSurfaceProps = SkSurfaceProps(flags, kBGR_V_SkPixelGeometry);
+ break;
+ case kBGR_V_SkPixelGeometry:
+ params.fSurfaceProps = SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+ fPixelGeometryOverrides = false;
+ break;
+ }
+ }
+ fWindow->setRequestedDisplayParams(params);
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('H', "Font", "Hinting mode", [this]() {
+ if (!fFontOverrides.fHinting) {
+ fFontOverrides.fHinting = true;
+ fFont.setHinting(SkFontHinting::kNone);
+ } else {
+ switch (fFont.getHinting()) {
+ case SkFontHinting::kNone:
+ fFont.setHinting(SkFontHinting::kSlight);
+ break;
+ case SkFontHinting::kSlight:
+ fFont.setHinting(SkFontHinting::kNormal);
+ break;
+ case SkFontHinting::kNormal:
+ fFont.setHinting(SkFontHinting::kFull);
+ break;
+ case SkFontHinting::kFull:
+ fFont.setHinting(SkFontHinting::kNone);
+ fFontOverrides.fHinting = false;
+ break;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('A', "Paint", "Antialias Mode", [this]() {
+ if (!fPaintOverrides.fAntiAlias) {
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::Alias;
+ fPaintOverrides.fAntiAlias = true;
+ fPaint.setAntiAlias(false);
+ gSkUseAnalyticAA = gSkForceAnalyticAA = false;
+ } else {
+ fPaint.setAntiAlias(true);
+ switch (fPaintOverrides.fAntiAliasState) {
+ case SkPaintFields::AntiAliasState::Alias:
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::Normal;
+ gSkUseAnalyticAA = gSkForceAnalyticAA = false;
+ break;
+ case SkPaintFields::AntiAliasState::Normal:
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::AnalyticAAEnabled;
+ gSkUseAnalyticAA = true;
+ gSkForceAnalyticAA = false;
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAEnabled:
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::AnalyticAAForced;
+ gSkUseAnalyticAA = gSkForceAnalyticAA = true;
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAForced:
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::Alias;
+ fPaintOverrides.fAntiAlias = false;
+ gSkUseAnalyticAA = fPaintOverrides.fOriginalSkUseAnalyticAA;
+ gSkForceAnalyticAA = fPaintOverrides.fOriginalSkForceAnalyticAA;
+ break;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('D', "Modes", "DFT", [this]() {
+ DisplayParams params = fWindow->getRequestedDisplayParams();
+ uint32_t flags = params.fSurfaceProps.flags();
+ flags ^= SkSurfaceProps::kUseDeviceIndependentFonts_Flag;
+ params.fSurfaceProps = SkSurfaceProps(flags, params.fSurfaceProps.pixelGeometry());
+ fWindow->setRequestedDisplayParams(params);
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('L', "Font", "Subpixel Antialias Mode", [this]() {
+ if (!fFontOverrides.fEdging) {
+ fFontOverrides.fEdging = true;
+ fFont.setEdging(SkFont::Edging::kAlias);
+ } else {
+ switch (fFont.getEdging()) {
+ case SkFont::Edging::kAlias:
+ fFont.setEdging(SkFont::Edging::kAntiAlias);
+ break;
+ case SkFont::Edging::kAntiAlias:
+ fFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ break;
+ case SkFont::Edging::kSubpixelAntiAlias:
+ fFont.setEdging(SkFont::Edging::kAlias);
+ fFontOverrides.fEdging = false;
+ break;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('S', "Font", "Subpixel Position Mode", [this]() {
+ if (!fFontOverrides.fSubpixel) {
+ fFontOverrides.fSubpixel = true;
+ fFont.setSubpixel(false);
+ } else {
+ if (!fFont.isSubpixel()) {
+ fFont.setSubpixel(true);
+ } else {
+ fFontOverrides.fSubpixel = false;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('B', "Font", "Baseline Snapping", [this]() {
+ if (!fFontOverrides.fBaselineSnap) {
+ fFontOverrides.fBaselineSnap = true;
+ fFont.setBaselineSnap(false);
+ } else {
+ if (!fFont.isBaselineSnap()) {
+ fFont.setBaselineSnap(true);
+ } else {
+ fFontOverrides.fBaselineSnap = false;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('p', "Transform", "Toggle Perspective Mode", [this]() {
+ fPerspectiveMode = (kPerspective_Real == fPerspectiveMode) ? kPerspective_Fake
+ : kPerspective_Real;
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('P', "Transform", "Toggle Perspective", [this]() {
+ fPerspectiveMode = (kPerspective_Off == fPerspectiveMode) ? kPerspective_Real
+ : kPerspective_Off;
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('a', "Transform", "Toggle Animation", [this]() {
+ fAnimTimer.togglePauseResume();
+ });
+ fCommands.addCommand('u', "GUI", "Zoom UI", [this]() {
+ fZoomUI = !fZoomUI;
+ fStatsLayer.setDisplayScale(fZoomUI ? 2.0f : 1.0f);
+ fWindow->inval();
+ });
// set up slides
this->initSlides();
- this->setStartupSlide();
if (FLAGS_list) {
this->listNames();
}
+ fPerspectivePoints[0].set(0, 0);
+ fPerspectivePoints[1].set(1, 0);
+ fPerspectivePoints[2].set(0, 1);
+ fPerspectivePoints[3].set(1, 1);
fAnimTimer.run();
- // ImGui initialization:
- ImGuiIO& io = ImGui::GetIO();
- io.DisplaySize.x = static_cast<float>(fWindow->width());
- io.DisplaySize.y = static_cast<float>(fWindow->height());
-
- // Keymap...
- io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
- io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
- io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
- io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
- io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
- io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
- io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
- io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
- io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
- io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
- io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
- io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
- io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
- io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
- io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
- io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
- io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
- io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
- io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;
-
- int w, h;
- unsigned char* pixels;
- io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
- SkImageInfo info = SkImageInfo::MakeA8(w, h);
- SkPixmap pmap(info, pixels, info.minRowBytes());
- SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
- auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
- auto fontShader = fontImage->makeShader(&localMatrix);
- fImGuiFontPaint.setShader(fontShader);
- fImGuiFontPaint.setColor(SK_ColorWHITE);
- fImGuiFontPaint.setFilterQuality(kLow_SkFilterQuality);
- io.Fonts->TexID = &fImGuiFontPaint;
-
- auto gamutImage = GetResourceAsImage("gamut.png");
+ auto gamutImage = GetResourceAsImage("images/gamut.png");
if (gamutImage) {
fImGuiGamutPaint.setShader(gamutImage->makeShader());
}
fImGuiGamutPaint.setColor(SK_ColorWHITE);
fImGuiGamutPaint.setFilterQuality(kLow_SkFilterQuality);
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
+ this->setCurrentSlide(this->startupSlide());
}
void Viewer::initSlides() {
- fAllSlideNames = Json::Value(Json::arrayValue);
+ using SlideFactory = sk_sp<Slide>(*)(const SkString& name, const SkString& path);
+ static const struct {
+ const char* fExtension;
+ const char* fDirName;
+ const CommandLineFlags::StringArray& fFlags;
+ const SlideFactory fFactory;
+ } gExternalSlidesInfo[] = {
+ { ".skp", "skp-dir", FLAGS_skps,
+ [](const SkString& name, const SkString& path) -> sk_sp<Slide> {
+ return sk_make_sp<SKPSlide>(name, path);}
+ },
+ { ".jpg", "jpg-dir", FLAGS_jpgs,
+ [](const SkString& name, const SkString& path) -> sk_sp<Slide> {
+ return sk_make_sp<ImageSlide>(name, path);}
+ },
+#if defined(SK_ENABLE_SKOTTIE)
+ { ".json", "skottie-dir", FLAGS_lotties,
+ [](const SkString& name, const SkString& path) -> sk_sp<Slide> {
+ return sk_make_sp<SkottieSlide>(name, path);}
+ },
+#endif
+#if defined(SK_XML)
+ { ".svg", "svg-dir", FLAGS_svgs,
+ [](const SkString& name, const SkString& path) -> sk_sp<Slide> {
+ return sk_make_sp<SvgSlide>(name, path);}
+ },
+#endif
+ };
- const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
- while (gms) {
- std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr));
+ SkTArray<sk_sp<Slide>> dirSlides;
- if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
- sk_sp<Slide> slide(new GMSlide(gm.release()));
- fSlides.push_back(slide);
+ const auto addSlide =
+ [&](const SkString& name, const SkString& path, const SlideFactory& fact) {
+ if (CommandLineFlags::ShouldSkip(FLAGS_match, name.c_str())) {
+ return;
+ }
+
+ if (auto slide = fact(name, path)) {
+ dirSlides.push_back(slide);
+ fSlides.push_back(std::move(slide));
+ }
+ };
+
+ if (!FLAGS_file.isEmpty()) {
+ // single file mode
+ const SkString file(FLAGS_file[0]);
+
+ if (sk_exists(file.c_str(), kRead_SkFILE_Flag)) {
+ for (const auto& sinfo : gExternalSlidesInfo) {
+ if (file.endsWith(sinfo.fExtension)) {
+ addSlide(SkOSPath::Basename(file.c_str()), file, sinfo.fFactory);
+ return;
+ }
+ }
+
+ fprintf(stderr, "Unsupported file type \"%s\"\n", file.c_str());
+ } else {
+ fprintf(stderr, "Cannot read \"%s\"\n", file.c_str());
}
- gms = gms->next();
+ return;
}
- // reverse array
- for (int i = 0; i < fSlides.count()/2; ++i) {
- sk_sp<Slide> temp = fSlides[i];
- fSlides[i] = fSlides[fSlides.count() - i - 1];
- fSlides[fSlides.count() - i - 1] = temp;
+ // Bisect slide.
+ if (!FLAGS_bisect.isEmpty()) {
+ sk_sp<BisectSlide> bisect = BisectSlide::Create(FLAGS_bisect[0]);
+ if (bisect && !CommandLineFlags::ShouldSkip(FLAGS_match, bisect->getName().c_str())) {
+ if (FLAGS_bisect.count() >= 2) {
+ for (const char* ch = FLAGS_bisect[1]; *ch; ++ch) {
+ bisect->onChar(*ch);
+ }
+ }
+ fSlides.push_back(std::move(bisect));
+ }
+ }
+
+ // GMs
+ int firstGM = fSlides.count();
+ for (skiagm::GMFactory gmFactory : skiagm::GMRegistry::Range()) {
+ std::unique_ptr<skiagm::GM> gm = gmFactory();
+ if (!CommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
+ sk_sp<Slide> slide(new GMSlide(std::move(gm)));
+ fSlides.push_back(std::move(slide));
+ }
+ }
+ // reverse gms
+ int numGMs = fSlides.count() - firstGM;
+ for (int i = 0; i < numGMs/2; ++i) {
+ std::swap(fSlides[firstGM + i], fSlides[fSlides.count() - i - 1]);
}
// samples
- const SkViewRegister* reg = SkViewRegister::Head();
- while (reg) {
- sk_sp<Slide> slide(new SampleSlide(reg->factory()));
- if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) {
+ for (const SampleFactory factory : SampleRegistry::Range()) {
+ sk_sp<Slide> slide(new SampleSlide(factory));
+ if (!CommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) {
fSlides.push_back(slide);
}
- reg = reg->next();
}
- // SKPs
- for (int i = 0; i < FLAGS_skps.count(); i++) {
- if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
- continue;
- }
+ // Particle demo
+ {
+ // TODO: Convert this to a sample
+ sk_sp<Slide> slide(new ParticlesSlide());
+ if (!CommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) {
+ fSlides.push_back(std::move(slide));
+ }
+ }
- SkString path(FLAGS_skps[i]);
- sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
- if (slide) {
- fSlides.push_back(slide);
+ for (const auto& info : gExternalSlidesInfo) {
+ for (const auto& flag : info.fFlags) {
+ if (SkStrEndsWith(flag.c_str(), info.fExtension)) {
+ // single file
+ addSlide(SkOSPath::Basename(flag.c_str()), flag, info.fFactory);
+ } else {
+ // directory
+ SkOSFile::Iter it(flag.c_str(), info.fExtension);
+ SkString name;
+ while (it.next(&name)) {
+ addSlide(name, SkOSPath::Join(flag.c_str(), name.c_str()), info.fFactory);
+ }
}
- } else {
- SkOSFile::Iter it(FLAGS_skps[i], ".skp");
- SkString skpName;
- while (it.next(&skpName)) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
- continue;
- }
-
- SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
- sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
- if (slide) {
- fSlides.push_back(slide);
- }
+ if (!dirSlides.empty()) {
+ fSlides.push_back(
+ sk_make_sp<SlideDir>(SkStringPrintf("%s[%s]", info.fDirName, flag.c_str()),
+ std::move(dirSlides)));
+ dirSlides.reset(); // NOLINT(bugprone-use-after-move)
}
}
}
- // JPGs
- for (int i = 0; i < FLAGS_jpgs.count(); i++) {
- SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg");
- SkString jpgName;
- while (it.next(&jpgName)) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jpgName.c_str())) {
- continue;
- }
-
- SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str());
- sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path));
- if (slide) {
- fSlides.push_back(slide);
- }
- }
+ if (!fSlides.count()) {
+ sk_sp<Slide> slide(new NullSlide());
+ fSlides.push_back(std::move(slide));
}
}
@@ -533,30 +757,137 @@
delete fWindow;
}
+struct SkPaintTitleUpdater {
+ SkPaintTitleUpdater(SkString* title) : fTitle(title), fCount(0) {}
+ void append(const char* s) {
+ if (fCount == 0) {
+ fTitle->append(" {");
+ } else {
+ fTitle->append(", ");
+ }
+ fTitle->append(s);
+ ++fCount;
+ }
+ void done() {
+ if (fCount > 0) {
+ fTitle->append("}");
+ }
+ }
+ SkString* fTitle;
+ int fCount;
+};
+
void Viewer::updateTitle() {
if (!fWindow) {
return;
}
- if (fWindow->sampleCount() < 0) {
+ if (fWindow->sampleCount() < 1) {
return; // Surface hasn't been created yet.
}
SkString title("Viewer: ");
title.append(fSlides[fCurrentSlide]->getName());
+ if (gSkUseAnalyticAA) {
+ if (gSkForceAnalyticAA) {
+ title.append(" <FAAA>");
+ } else {
+ title.append(" <AAA>");
+ }
+ }
+
+ SkPaintTitleUpdater paintTitle(&title);
+ auto paintFlag = [this, &paintTitle](bool SkPaintFields::* flag,
+ bool (SkPaint::* isFlag)() const,
+ const char* on, const char* off)
+ {
+ if (fPaintOverrides.*flag) {
+ paintTitle.append((fPaint.*isFlag)() ? on : off);
+ }
+ };
+
+ auto fontFlag = [this, &paintTitle](bool SkFontFields::* flag, bool (SkFont::* isFlag)() const,
+ const char* on, const char* off)
+ {
+ if (fFontOverrides.*flag) {
+ paintTitle.append((fFont.*isFlag)() ? on : off);
+ }
+ };
+
+ paintFlag(&SkPaintFields::fAntiAlias, &SkPaint::isAntiAlias, "Antialias", "Alias");
+ paintFlag(&SkPaintFields::fDither, &SkPaint::isDither, "DITHER", "No Dither");
+ if (fPaintOverrides.fFilterQuality) {
+ switch (fPaint.getFilterQuality()) {
+ case kNone_SkFilterQuality:
+ paintTitle.append("NoFilter");
+ break;
+ case kLow_SkFilterQuality:
+ paintTitle.append("LowFilter");
+ break;
+ case kMedium_SkFilterQuality:
+ paintTitle.append("MediumFilter");
+ break;
+ case kHigh_SkFilterQuality:
+ paintTitle.append("HighFilter");
+ break;
+ }
+ }
+
+ fontFlag(&SkFontFields::fForceAutoHinting, &SkFont::isForceAutoHinting,
+ "Force Autohint", "No Force Autohint");
+ fontFlag(&SkFontFields::fEmbolden, &SkFont::isEmbolden, "Fake Bold", "No Fake Bold");
+ fontFlag(&SkFontFields::fBaselineSnap, &SkFont::isBaselineSnap, "BaseSnap", "No BaseSnap");
+ fontFlag(&SkFontFields::fLinearMetrics, &SkFont::isLinearMetrics,
+ "Linear Metrics", "Non-Linear Metrics");
+ fontFlag(&SkFontFields::fEmbeddedBitmaps, &SkFont::isEmbeddedBitmaps,
+ "Bitmap Text", "No Bitmap Text");
+ fontFlag(&SkFontFields::fSubpixel, &SkFont::isSubpixel, "Subpixel Text", "Pixel Text");
+
+ if (fFontOverrides.fEdging) {
+ switch (fFont.getEdging()) {
+ case SkFont::Edging::kAlias:
+ paintTitle.append("Alias Text");
+ break;
+ case SkFont::Edging::kAntiAlias:
+ paintTitle.append("Antialias Text");
+ break;
+ case SkFont::Edging::kSubpixelAntiAlias:
+ paintTitle.append("Subpixel Antialias Text");
+ break;
+ }
+ }
+
+ if (fFontOverrides.fHinting) {
+ switch (fFont.getHinting()) {
+ case SkFontHinting::kNone:
+ paintTitle.append("No Hinting");
+ break;
+ case SkFontHinting::kSlight:
+ paintTitle.append("Slight Hinting");
+ break;
+ case SkFontHinting::kNormal:
+ paintTitle.append("Normal Hinting");
+ break;
+ case SkFontHinting::kFull:
+ paintTitle.append("Full Hinting");
+ break;
+ }
+ }
+ paintTitle.done();
+
switch (fColorMode) {
case ColorMode::kLegacy:
title.append(" Legacy 8888");
break;
- case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
- title.append(" ColorManaged 8888 (Nonlinear blending)");
- break;
- case ColorMode::kColorManagedSRGB8888:
+ case ColorMode::kColorManaged8888:
title.append(" ColorManaged 8888");
break;
- case ColorMode::kColorManagedLinearF16:
+ case ColorMode::kColorManagedF16:
title.append(" ColorManaged F16");
break;
+ case ColorMode::kColorManagedF16Norm:
+ title.append(" ColorManaged F16 Norm");
+ break;
}
if (ColorMode::kLegacy != fColorMode) {
@@ -567,12 +898,40 @@
break;
}
}
- title.appendf(" %s", curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom");
+ title.appendf(" %s Gamma %f",
+ curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom",
+ fColorSpaceTransferFn.g);
+ }
+
+ const DisplayParams& params = fWindow->getRequestedDisplayParams();
+ if (fPixelGeometryOverrides) {
+ switch (params.fSurfaceProps.pixelGeometry()) {
+ case kUnknown_SkPixelGeometry:
+ title.append( " Flat");
+ break;
+ case kRGB_H_SkPixelGeometry:
+ title.append( " RGB");
+ break;
+ case kBGR_H_SkPixelGeometry:
+ title.append( " BGR");
+ break;
+ case kRGB_V_SkPixelGeometry:
+ title.append( " RGBV");
+ break;
+ case kBGR_V_SkPixelGeometry:
+ title.append( " BGRV");
+ break;
+ }
+ }
+
+ if (params.fSurfaceProps.isUseDeviceIndependentFonts()) {
+ title.append(" DFT");
}
title.append(" [");
title.append(kBackendTypeStrings[fBackendType]);
- if (int msaa = fWindow->sampleCount()) {
+ int msaa = fWindow->sampleCount();
+ if (msaa > 1) {
title.appendf(" MSAA: %i", msaa);
}
title.append("]");
@@ -582,17 +941,22 @@
title.appendf(" [Path renderer: %s]", gPathRendererNames[pr].c_str());
}
+ if (kPerspective_Real == fPerspectiveMode) {
+ title.append(" Perpsective (Real)");
+ } else if (kPerspective_Fake == fPerspectiveMode) {
+ title.append(" Perspective (Fake)");
+ }
+
fWindow->setTitle(title.c_str());
}
-void Viewer::setStartupSlide() {
+int Viewer::startupSlide() const {
if (!FLAGS_slide.isEmpty()) {
int count = fSlides.count();
for (int i = 0; i < count; i++) {
if (fSlides[i]->getName().equals(FLAGS_slide[0])) {
- fCurrentSlide = i;
- return;
+ return i;
}
}
@@ -600,47 +964,60 @@
this->listNames();
}
- fCurrentSlide = 0;
+ return 0;
}
-void Viewer::listNames() {
- int count = fSlides.count();
+void Viewer::listNames() const {
SkDebugf("All Slides:\n");
- for (int i = 0; i < count; i++) {
- SkDebugf(" %s\n", fSlides[i]->getName().c_str());
+ for (const auto& slide : fSlides) {
+ SkDebugf(" %s\n", slide->getName().c_str());
}
}
-void Viewer::setupCurrentSlide(int previousSlide) {
- if (fCurrentSlide == previousSlide) {
- return; // no change; do nothing
+void Viewer::setCurrentSlide(int slide) {
+ SkASSERT(slide >= 0 && slide < fSlides.count());
+
+ if (slide == fCurrentSlide) {
+ return;
}
- // prepare dimensions for image slides
- fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height()));
- fGesture.reset();
- fDefaultMatrix.reset();
+ if (fCurrentSlide >= 0) {
+ fSlides[fCurrentSlide]->unload();
+ }
- const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
- const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
- const SkRect windowRect = SkRect::MakeIWH(fWindow->width(), fWindow->height());
+ fSlides[slide]->load(SkIntToScalar(fWindow->width()),
+ SkIntToScalar(fWindow->height()));
+ fCurrentSlide = slide;
+ this->setupCurrentSlide();
+}
- // Start with a matrix that scales the slide to the available screen space
- if (fWindow->scaleContentToFit()) {
- if (windowRect.width() > 0 && windowRect.height() > 0) {
- fDefaultMatrix.setRectToRect(slideBounds, windowRect, SkMatrix::kStart_ScaleToFit);
+void Viewer::setupCurrentSlide() {
+ if (fCurrentSlide >= 0) {
+ // prepare dimensions for image slides
+ fGesture.resetTouchState();
+ fDefaultMatrix.reset();
+
+ const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
+ const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
+ const SkRect windowRect = SkRect::MakeIWH(fWindow->width(), fWindow->height());
+
+ // Start with a matrix that scales the slide to the available screen space
+ if (fWindow->scaleContentToFit()) {
+ if (windowRect.width() > 0 && windowRect.height() > 0) {
+ fDefaultMatrix.setRectToRect(slideBounds, windowRect, SkMatrix::kStart_ScaleToFit);
+ }
}
- }
- // Prevent the user from dragging content so far outside the window they can't find it again
- fGesture.setTransLimit(slideBounds, windowRect, fDefaultMatrix);
+ // Prevent the user from dragging content so far outside the window they can't find it again
+ fGesture.setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
- this->updateTitle();
- this->updateUIState();
- if (previousSlide >= 0) {
- fSlides[previousSlide]->unload();
+ this->updateTitle();
+ this->updateUIState();
+
+ fStatsLayer.resetMeasurements();
+
+ fWindow->inval();
}
- fWindow->inval();
}
#define MAX_ZOOM_LEVEL 8
@@ -649,362 +1026,577 @@
void Viewer::changeZoomLevel(float delta) {
fZoomLevel += delta;
fZoomLevel = SkScalarPin(fZoomLevel, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
+ this->preTouchMatrixChanged();
}
-SkMatrix Viewer::computeMatrix() {
- SkMatrix m;
+void Viewer::preTouchMatrixChanged() {
+ // Update the trans limit as the transform changes.
+ const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
+ const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
+ const SkRect windowRect = SkRect::MakeIWH(fWindow->width(), fWindow->height());
+ fGesture.setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
+}
- SkScalar zoomScale = (fZoomLevel < 0) ? SK_Scalar1 / (SK_Scalar1 - fZoomLevel)
- : SK_Scalar1 + fZoomLevel;
- m = fGesture.localM();
- m.preConcat(fGesture.globalM());
- m.preConcat(fDefaultMatrix);
+SkMatrix Viewer::computePerspectiveMatrix() {
+ SkScalar w = fWindow->width(), h = fWindow->height();
+ SkPoint orthoPts[4] = { { 0, 0 }, { w, 0 }, { 0, h }, { w, h } };
+ SkPoint perspPts[4] = {
+ { fPerspectivePoints[0].fX * w, fPerspectivePoints[0].fY * h },
+ { fPerspectivePoints[1].fX * w, fPerspectivePoints[1].fY * h },
+ { fPerspectivePoints[2].fX * w, fPerspectivePoints[2].fY * h },
+ { fPerspectivePoints[3].fX * w, fPerspectivePoints[3].fY * h }
+ };
+ SkMatrix m;
+ m.setPolyToPoly(orthoPts, perspPts, 4);
+ return m;
+}
+
+SkMatrix Viewer::computePreTouchMatrix() {
+ SkMatrix m = fDefaultMatrix;
+
+ SkScalar zoomScale = exp(fZoomLevel);
+ m.preTranslate((fOffset.x() - 0.5f) * 2.0f, (fOffset.y() - 0.5f) * 2.0f);
m.preScale(zoomScale, zoomScale);
+ const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
+ m.preRotate(fRotation, slideSize.width() * 0.5f, slideSize.height() * 0.5f);
+
+ if (kPerspective_Real == fPerspectiveMode) {
+ SkMatrix persp = this->computePerspectiveMatrix();
+ m.postConcat(persp);
+ }
+
return m;
}
+SkMatrix Viewer::computeMatrix() {
+ SkMatrix m = fGesture.localM();
+ m.preConcat(fGesture.globalM());
+ m.preConcat(this->computePreTouchMatrix());
+ return m;
+}
+
void Viewer::setBackend(sk_app::Window::BackendType backendType) {
+ fPersistentCache.reset();
+ fCachedGLSL.reset();
fBackendType = backendType;
fWindow->detach();
-#if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN)
- // Switching from OpenGL to Vulkan (or vice-versa on some systems) in the same window is
- // problematic at this point on Windows, so we just delete the window and recreate it.
- if (sk_app::Window::kVulkan_BackendType == fBackendType ||
- sk_app::Window::kNativeGL_BackendType == fBackendType) {
- DisplayParams params = fWindow->getRequestedDisplayParams();
- delete fWindow;
- fWindow = Window::CreateNativeWindow(nullptr);
+#if defined(SK_BUILD_FOR_WIN)
+ // Switching between OpenGL, Vulkan, and ANGLE in the same window is problematic at this point
+ // on Windows, so we just delete the window and recreate it.
+ DisplayParams params = fWindow->getRequestedDisplayParams();
+ delete fWindow;
+ fWindow = Window::CreateNativeWindow(nullptr);
- // re-register callbacks
- fCommands.attach(fWindow);
- fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
- fWindow->registerPaintFunc(on_paint_handler, this);
- fWindow->registerTouchFunc(on_touch_handler, this);
- fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
- fWindow->registerMouseFunc(on_mouse_handler, this);
- fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
- fWindow->registerKeyFunc(on_key_handler, this);
- fWindow->registerCharFunc(on_char_handler, this);
- // Don't allow the window to re-attach. If we're in MSAA mode, the params we grabbed above
- // will still include our correct sample count. But the re-created fWindow will lose that
- // information. On Windows, we need to re-create the window when changing sample count,
- // so we'll incorrectly detect that situation, then re-initialize the window in GL mode,
- // rendering this tear-down step pointless (and causing the Vulkan window context to fail
- // as if we had never changed windows at all).
- fWindow->setRequestedDisplayParams(params, false);
- }
+ // re-register callbacks
+ fCommands.attach(fWindow);
+ fWindow->pushLayer(this);
+ fWindow->pushLayer(&fStatsLayer);
+ fWindow->pushLayer(&fImGuiLayer);
+
+ // Don't allow the window to re-attach. If we're in MSAA mode, the params we grabbed above
+ // will still include our correct sample count. But the re-created fWindow will lose that
+ // information. On Windows, we need to re-create the window when changing sample count,
+ // so we'll incorrectly detect that situation, then re-initialize the window in GL mode,
+ // rendering this tear-down step pointless (and causing the Vulkan window context to fail
+ // as if we had never changed windows at all).
+ fWindow->setRequestedDisplayParams(params, false);
#endif
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
}
void Viewer::setColorMode(ColorMode colorMode) {
fColorMode = colorMode;
-
- // When we're in color managed mode, we tag our window surface as sRGB. If we've switched into
- // or out of legacy/nonlinear mode, we need to update our window configuration.
- DisplayParams params = fWindow->getRequestedDisplayParams();
- bool wasInLegacy = !SkToBool(params.fColorSpace);
- bool wantLegacy = (ColorMode::kLegacy == fColorMode) ||
- (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode);
- if (wasInLegacy != wantLegacy) {
- params.fColorSpace = wantLegacy ? nullptr : SkColorSpace::MakeSRGB();
- fWindow->setRequestedDisplayParams(params);
- }
-
this->updateTitle();
fWindow->inval();
}
-void Viewer::drawSlide(SkCanvas* canvas) {
- SkAutoCanvasRestore autorestore(canvas, false);
+class OveridePaintFilterCanvas : public SkPaintFilterCanvas {
+public:
+ OveridePaintFilterCanvas(SkCanvas* canvas, SkPaint* paint, Viewer::SkPaintFields* pfields,
+ SkFont* font, Viewer::SkFontFields* ffields)
+ : SkPaintFilterCanvas(canvas), fPaint(paint), fPaintOverrides(pfields), fFont(font), fFontOverrides(ffields)
+ { }
+ const SkTextBlob* filterTextBlob(const SkPaint& paint, const SkTextBlob* blob,
+ sk_sp<SkTextBlob>* cache) {
+ bool blobWillChange = false;
+ for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
+ SkTCopyOnFirstWrite<SkFont> filteredFont(it.font());
+ bool shouldDraw = this->filterFont(&filteredFont);
+ if (it.font() != *filteredFont || !shouldDraw) {
+ blobWillChange = true;
+ break;
+ }
+ }
+ if (!blobWillChange) {
+ return blob;
+ }
+
+ SkTextBlobBuilder builder;
+ for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
+ SkTCopyOnFirstWrite<SkFont> filteredFont(it.font());
+ bool shouldDraw = this->filterFont(&filteredFont);
+ if (!shouldDraw) {
+ continue;
+ }
+
+ SkFont font = *filteredFont;
+
+ const SkTextBlobBuilder::RunBuffer& runBuffer
+ = it.positioning() == SkTextBlobRunIterator::kDefault_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunText(&builder, font,
+ it.glyphCount(), it.offset().x(),it.offset().y(), it.textSize(), SkString())
+ : it.positioning() == SkTextBlobRunIterator::kHorizontal_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunTextPosH(&builder, font,
+ it.glyphCount(), it.offset().y(), it.textSize(), SkString())
+ : it.positioning() == SkTextBlobRunIterator::kFull_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunTextPos(&builder, font,
+ it.glyphCount(), it.textSize(), SkString())
+ : (SkASSERT_RELEASE(false), SkTextBlobBuilder::RunBuffer());
+ uint32_t glyphCount = it.glyphCount();
+ if (it.glyphs()) {
+ size_t glyphSize = sizeof(decltype(*it.glyphs()));
+ memcpy(runBuffer.glyphs, it.glyphs(), glyphCount * glyphSize);
+ }
+ if (it.pos()) {
+ size_t posSize = sizeof(decltype(*it.pos()));
+ uint8_t positioning = it.positioning();
+ memcpy(runBuffer.pos, it.pos(), glyphCount * positioning * posSize);
+ }
+ if (it.text()) {
+ size_t textSize = sizeof(decltype(*it.text()));
+ uint32_t textCount = it.textSize();
+ memcpy(runBuffer.utf8text, it.text(), textCount * textSize);
+ }
+ if (it.clusters()) {
+ size_t clusterSize = sizeof(decltype(*it.clusters()));
+ memcpy(runBuffer.clusters, it.clusters(), glyphCount * clusterSize);
+ }
+ }
+ *cache = builder.make();
+ return cache->get();
+ }
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) override {
+ sk_sp<SkTextBlob> cache;
+ this->SkPaintFilterCanvas::onDrawTextBlob(
+ this->filterTextBlob(paint, blob, &cache), x, y, paint);
+ }
+ bool filterFont(SkTCopyOnFirstWrite<SkFont>* font) const {
+ if (fFontOverrides->fSize) {
+ font->writable()->setSize(fFont->getSize());
+ }
+ if (fFontOverrides->fScaleX) {
+ font->writable()->setScaleX(fFont->getScaleX());
+ }
+ if (fFontOverrides->fSkewX) {
+ font->writable()->setSkewX(fFont->getSkewX());
+ }
+ if (fFontOverrides->fHinting) {
+ font->writable()->setHinting(fFont->getHinting());
+ }
+ if (fFontOverrides->fEdging) {
+ font->writable()->setEdging(fFont->getEdging());
+ }
+ if (fFontOverrides->fEmbolden) {
+ font->writable()->setEmbolden(fFont->isEmbolden());
+ }
+ if (fFontOverrides->fBaselineSnap) {
+ font->writable()->setBaselineSnap(fFont->isBaselineSnap());
+ }
+ if (fFontOverrides->fLinearMetrics) {
+ font->writable()->setLinearMetrics(fFont->isLinearMetrics());
+ }
+ if (fFontOverrides->fSubpixel) {
+ font->writable()->setSubpixel(fFont->isSubpixel());
+ }
+ if (fFontOverrides->fEmbeddedBitmaps) {
+ font->writable()->setEmbeddedBitmaps(fFont->isEmbeddedBitmaps());
+ }
+ if (fFontOverrides->fForceAutoHinting) {
+ font->writable()->setForceAutoHinting(fFont->isForceAutoHinting());
+ }
+
+ return true;
+ }
+ bool onFilter(SkPaint& paint) const override {
+ if (fPaintOverrides->fAntiAlias) {
+ paint.setAntiAlias(fPaint->isAntiAlias());
+ }
+ if (fPaintOverrides->fDither) {
+ paint.setDither(fPaint->isDither());
+ }
+ if (fPaintOverrides->fFilterQuality) {
+ paint.setFilterQuality(fPaint->getFilterQuality());
+ }
+ return true;
+ }
+ SkPaint* fPaint;
+ Viewer::SkPaintFields* fPaintOverrides;
+ SkFont* fFont;
+ Viewer::SkFontFields* fFontOverrides;
+};
+
+void Viewer::drawSlide(SkSurface* surface) {
+ if (fCurrentSlide < 0) {
+ return;
+ }
+
+ SkAutoCanvasRestore autorestore(surface->getCanvas(), false);
// By default, we render directly into the window's surface/canvas
- SkCanvas* slideCanvas = canvas;
+ SkSurface* slideSurface = surface;
+ SkCanvas* slideCanvas = surface->getCanvas();
fLastImage.reset();
// If we're in any of the color managed modes, construct the color space we're going to use
- sk_sp<SkColorSpace> cs = nullptr;
+ sk_sp<SkColorSpace> colorSpace = nullptr;
if (ColorMode::kLegacy != fColorMode) {
- auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
- ? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
- SkMatrix44 toXYZ;
+ skcms_Matrix3x3 toXYZ;
SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
- cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
+ colorSpace = SkColorSpace::MakeRGB(fColorSpaceTransferFn, toXYZ);
}
- // If we're in F16, or we're zooming, or we're in color correct 8888 and the gamut isn't sRGB,
- // we need to render offscreen
+ if (fSaveToSKP) {
+ SkPictureRecorder recorder;
+ SkCanvas* recorderCanvas = recorder.beginRecording(
+ SkRect::Make(fSlides[fCurrentSlide]->getDimensions()));
+ fSlides[fCurrentSlide]->draw(recorderCanvas);
+ sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
+ SkFILEWStream stream("sample_app.skp");
+ picture->serialize(&stream);
+ fSaveToSKP = false;
+ }
+
+ // Grab some things we'll need to make surfaces (for tiling or general offscreen rendering)
+ SkColorType colorType;
+ switch (fColorMode) {
+ case ColorMode::kLegacy:
+ case ColorMode::kColorManaged8888:
+ colorType = kN32_SkColorType;
+ break;
+ case ColorMode::kColorManagedF16:
+ colorType = kRGBA_F16_SkColorType;
+ break;
+ case ColorMode::kColorManagedF16Norm:
+ colorType = kRGBA_F16Norm_SkColorType;
+ break;
+ }
+
+ auto make_surface = [=](int w, int h) {
+ SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
+ slideCanvas->getProps(&props);
+
+ SkImageInfo info = SkImageInfo::Make(w, h, colorType, kPremul_SkAlphaType, colorSpace);
+ return Window::kRaster_BackendType == this->fBackendType
+ ? SkSurface::MakeRaster(info, &props)
+ : slideCanvas->makeSurface(info, &props);
+ };
+
+ // We need to render offscreen if we're...
+ // ... in fake perspective or zooming (so we have a snapped copy of the results)
+ // ... in any raster mode, because the window surface is actually GL
+ // ... in any color managed mode, because we always make the window surface with no color space
sk_sp<SkSurface> offscreenSurface = nullptr;
- if (ColorMode::kColorManagedLinearF16 == fColorMode ||
+ if (kPerspective_Fake == fPerspectiveMode ||
fShowZoomWindow ||
- (ColorMode::kColorManagedSRGB8888 == fColorMode &&
- !primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {
+ Window::kRaster_BackendType == fBackendType ||
+ colorSpace != nullptr) {
- SkColorType colorType = (ColorMode::kColorManagedLinearF16 == fColorMode)
- ? kRGBA_F16_SkColorType : kN32_SkColorType;
- // In nonlinear blending mode, we actually use a legacy off-screen canvas, and wrap it
- // with a special canvas (below) that has the color space attached
- sk_sp<SkColorSpace> offscreenColorSpace =
- (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) ? nullptr : cs;
- SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), colorType,
- kPremul_SkAlphaType, std::move(offscreenColorSpace));
- offscreenSurface = canvas->makeSurface(info);
+ offscreenSurface = make_surface(fWindow->width(), fWindow->height());
+ slideSurface = offscreenSurface.get();
slideCanvas = offscreenSurface->getCanvas();
}
- std::unique_ptr<SkCanvas> xformCanvas = nullptr;
- if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
- xformCanvas = SkCreateColorSpaceXformCanvas(slideCanvas, cs);
- slideCanvas = xformCanvas.get();
- }
-
int count = slideCanvas->save();
slideCanvas->clear(SK_ColorWHITE);
- slideCanvas->concat(computeMatrix());
// Time the painting logic of the slide
- double startTime = SkTime::GetMSecs();
- fSlides[fCurrentSlide]->draw(slideCanvas);
- fPaintTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
+ fStatsLayer.beginTiming(fPaintTimer);
+ if (fTiled) {
+ int tileW = SkScalarCeilToInt(fWindow->width() * fTileScale.width());
+ int tileH = SkScalarCeilToInt(fWindow->height() * fTileScale.height());
+ sk_sp<SkSurface> tileSurface = make_surface(tileW, tileH);
+ SkCanvas* tileCanvas = tileSurface->getCanvas();
+ SkMatrix m = this->computeMatrix();
+ for (int y = 0; y < fWindow->height(); y += tileH) {
+ for (int x = 0; x < fWindow->width(); x += tileW) {
+ SkAutoCanvasRestore acr(tileCanvas, true);
+ tileCanvas->translate(-x, -y);
+ tileCanvas->clear(SK_ColorTRANSPARENT);
+ tileCanvas->concat(m);
+ OveridePaintFilterCanvas filterCanvas(tileCanvas, &fPaint, &fPaintOverrides,
+ &fFont, &fFontOverrides);
+ fSlides[fCurrentSlide]->draw(&filterCanvas);
+ tileSurface->draw(slideCanvas, x, y, nullptr);
+ }
+ }
+
+ // Draw borders between tiles
+ if (fDrawTileBoundaries) {
+ SkPaint border;
+ border.setColor(0x60FF00FF);
+ border.setStyle(SkPaint::kStroke_Style);
+ for (int y = 0; y < fWindow->height(); y += tileH) {
+ for (int x = 0; x < fWindow->width(); x += tileW) {
+ slideCanvas->drawRect(SkRect::MakeXYWH(x, y, tileW, tileH), border);
+ }
+ }
+ }
+ } else {
+ slideCanvas->concat(this->computeMatrix());
+ if (kPerspective_Real == fPerspectiveMode) {
+ slideCanvas->clipRect(SkRect::MakeWH(fWindow->width(), fWindow->height()));
+ }
+ OveridePaintFilterCanvas filterCanvas(slideCanvas, &fPaint, &fPaintOverrides, &fFont, &fFontOverrides);
+ fSlides[fCurrentSlide]->draw(&filterCanvas);
+ }
+ fStatsLayer.endTiming(fPaintTimer);
slideCanvas->restoreToCount(count);
// Force a flush so we can time that, too
- startTime = SkTime::GetMSecs();
- slideCanvas->flush();
- fFlushTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
+ fStatsLayer.beginTiming(fFlushTimer);
+ slideSurface->flush();
+ fStatsLayer.endTiming(fFlushTimer);
// If we rendered offscreen, snap an image and push the results to the window's canvas
if (offscreenSurface) {
fLastImage = offscreenSurface->makeImageSnapshot();
- // Tag the image with the sRGB gamut, so no further color space conversion happens
- sk_sp<SkColorSpace> srgb = (ColorMode::kColorManagedLinearF16 == fColorMode)
- ? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB();
- auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), srgb.get());
+ SkCanvas* canvas = surface->getCanvas();
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawImage(retaggedImage, 0, 0, &paint);
+ int prePerspectiveCount = canvas->save();
+ if (kPerspective_Fake == fPerspectiveMode) {
+ paint.setFilterQuality(kHigh_SkFilterQuality);
+ canvas->clear(SK_ColorWHITE);
+ canvas->concat(this->computePerspectiveMatrix());
+ }
+ canvas->drawImage(fLastImage, 0, 0, &paint);
+ canvas->restoreToCount(prePerspectiveCount);
+ }
+
+ if (fShowSlideDimensions) {
+ SkRect r = SkRect::Make(fSlides[fCurrentSlide]->getDimensions());
+ SkPaint paint;
+ paint.setColor(0x40FFFF00);
+ surface->getCanvas()->drawRect(r, paint);
}
}
void Viewer::onBackendCreated() {
- this->updateTitle();
- this->updateUIState();
- this->setupCurrentSlide(-1);
+ this->setupCurrentSlide();
fWindow->show();
- fWindow->inval();
}
-void Viewer::onPaint(SkCanvas* canvas) {
- // Update ImGui input
- ImGuiIO& io = ImGui::GetIO();
- io.DeltaTime = 1.0f / 60.0f;
- io.DisplaySize.x = static_cast<float>(fWindow->width());
- io.DisplaySize.y = static_cast<float>(fWindow->height());
+void Viewer::onPaint(SkSurface* surface) {
+ this->drawSlide(surface);
- io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
- io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
- io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];
+ fCommands.drawHelp(surface->getCanvas());
- ImGui::NewFrame();
+ this->drawImGui();
- drawSlide(canvas);
-
- // Advance our timing bookkeeping
- fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
- SkASSERT(fCurrentMeasurement < kMeasurementCount);
-
- // Draw any overlays or UI that we don't want timed
- if (fDisplayStats) {
- drawStats(canvas);
+ if (GrContext* ctx = fWindow->getGrContext()) {
+ // Clean out cache items that haven't been used in more than 10 seconds.
+ ctx->performDeferredCleanup(std::chrono::seconds(10));
}
- fCommands.drawHelp(canvas);
-
- drawImGui(canvas);
-
- // Update the FPS
- updateUIState();
}
-bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
+void Viewer::onResize(int width, int height) {
+ if (fCurrentSlide >= 0) {
+ fSlides[fCurrentSlide]->resize(width, height);
+ }
+}
+
+SkPoint Viewer::mapEvent(float x, float y) {
+ const auto m = this->computeMatrix();
+ SkMatrix inv;
+
+ SkAssertResult(m.invert(&inv));
+
+ return inv.mapXY(x, y);
+}
+
+bool Viewer::onTouch(intptr_t owner, skui::InputState state, float x, float y) {
if (GestureDevice::kMouse == fGestureDevice) {
return false;
}
+
+ const auto slidePt = this->mapEvent(x, y);
+ if (fSlides[fCurrentSlide]->onMouse(slidePt.x(), slidePt.y(), state, skui::ModifierKey::kNone)) {
+ fWindow->inval();
+ return true;
+ }
+
void* castedOwner = reinterpret_cast<void*>(owner);
switch (state) {
- case Window::kUp_InputState: {
+ case skui::InputState::kUp: {
fGesture.touchEnd(castedOwner);
+#if defined(SK_BUILD_FOR_IOS)
+ // TODO: move IOS swipe detection higher up into the platform code
+ SkPoint dir;
+ if (fGesture.isFling(&dir)) {
+ // swiping left or right
+ if (SkTAbs(dir.fX) > SkTAbs(dir.fY)) {
+ if (dir.fX < 0) {
+ this->setCurrentSlide(fCurrentSlide < fSlides.count() - 1 ?
+ fCurrentSlide + 1 : 0);
+ } else {
+ this->setCurrentSlide(fCurrentSlide > 0 ?
+ fCurrentSlide - 1 : fSlides.count() - 1);
+ }
+ }
+ fGesture.reset();
+ }
+#endif
break;
}
- case Window::kDown_InputState: {
+ case skui::InputState::kDown: {
fGesture.touchBegin(castedOwner, x, y);
break;
}
- case Window::kMove_InputState: {
+ case skui::InputState::kMove: {
fGesture.touchMoved(castedOwner, x, y);
break;
}
+ default: {
+ // kLeft and kRight are only for swipes
+ SkASSERT(false);
+ break;
+ }
}
fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kTouch : GestureDevice::kNone;
fWindow->inval();
return true;
}
-bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {
+bool Viewer::onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) {
if (GestureDevice::kTouch == fGestureDevice) {
return false;
}
+
+ const auto slidePt = this->mapEvent(x, y);
+ if (fSlides[fCurrentSlide]->onMouse(slidePt.x(), slidePt.y(), state, modifiers)) {
+ fWindow->inval();
+ return true;
+ }
+
switch (state) {
- case Window::kUp_InputState: {
+ case skui::InputState::kUp: {
fGesture.touchEnd(nullptr);
break;
}
- case Window::kDown_InputState: {
+ case skui::InputState::kDown: {
fGesture.touchBegin(nullptr, x, y);
break;
}
- case Window::kMove_InputState: {
+ case skui::InputState::kMove: {
fGesture.touchMoved(nullptr, x, y);
break;
}
+ default: {
+ SkASSERT(false); // shouldn't see kRight or kLeft here
+ break;
+ }
}
fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
- fWindow->inval();
+
+ if (state != skui::InputState::kMove || fGesture.isBeingTouched()) {
+ fWindow->inval();
+ }
return true;
}
-void Viewer::drawStats(SkCanvas* canvas) {
- static const float kPixelPerMS = 2.0f;
- static const int kDisplayWidth = 130;
- static const int kDisplayHeight = 100;
- static const int kDisplayPadding = 10;
- static const int kGraphPadding = 3;
- static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
-
- SkISize canvasSize = canvas->getBaseLayerSize();
- SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
- SkIntToScalar(kDisplayPadding),
- SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
- SkPaint paint;
- canvas->save();
-
- canvas->clipRect(rect);
- paint.setColor(SK_ColorBLACK);
- canvas->drawRect(rect, paint);
- // draw the 16ms line
- paint.setColor(SK_ColorLTGRAY);
- canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
- rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
- paint.setColor(SK_ColorRED);
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawRect(rect, paint);
-
- int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
- const int xStep = 2;
- int i = fCurrentMeasurement;
- do {
- // Round to nearest values
- int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5);
- int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5);
- int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5);
- int startY = SkScalarTruncToInt(rect.fBottom);
- int endY = startY - flushHeight;
- paint.setColor(SK_ColorRED);
- canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
- SkIntToScalar(x), SkIntToScalar(endY), paint);
- startY = endY;
- endY = startY - paintHeight;
- paint.setColor(SK_ColorGREEN);
- canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
- SkIntToScalar(x), SkIntToScalar(endY), paint);
- startY = endY;
- endY = startY - animateHeight;
- paint.setColor(SK_ColorMAGENTA);
- canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
- SkIntToScalar(x), SkIntToScalar(endY), paint);
- i++;
- i &= (kMeasurementCount - 1); // fast mod
- x += xStep;
- } while (i != fCurrentMeasurement);
-
- canvas->restore();
+bool Viewer::onFling(skui::InputState state) {
+ if (skui::InputState::kRight == state) {
+ this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.count() - 1);
+ return true;
+ } else if (skui::InputState::kLeft == state) {
+ this->setCurrentSlide(fCurrentSlide < fSlides.count() - 1 ? fCurrentSlide + 1 : 0);
+ return true;
+ }
+ return false;
}
-static ImVec2 ImGui_DragPrimary(const char* label, float* x, float* y,
- const ImVec2& pos, const ImVec2& size) {
- // Transform primaries ([0, 0] - [0.8, 0.9]) to screen coords (including Y-flip)
- ImVec2 center(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);
-
- // Invisible 10x10 button
- ImGui::SetCursorScreenPos(ImVec2(center.x - 5, center.y - 5));
- ImGui::InvisibleButton(label, ImVec2(10, 10));
-
- if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) {
- ImGuiIO& io = ImGui::GetIO();
- // Normalized mouse position, relative to our gamut box
- ImVec2 mousePosXY((io.MousePos.x - pos.x) / size.x, (io.MousePos.y - pos.y) / size.y);
- // Clamp to edge of box, convert back to primary scale
- *x = SkTPin(mousePosXY.x, 0.0f, 1.0f) * 0.8f;
- *y = SkTPin(1 - mousePosXY.y, 0.0f, 1.0f) * 0.9f;
+bool Viewer::onPinch(skui::InputState state, float scale, float x, float y) {
+ switch (state) {
+ case skui::InputState::kDown:
+ fGesture.startZoom();
+ return true;
+ break;
+ case skui::InputState::kMove:
+ fGesture.updateZoom(scale, x, y, x, y);
+ return true;
+ break;
+ case skui::InputState::kUp:
+ fGesture.endZoom();
+ return true;
+ break;
+ default:
+ SkASSERT(false);
+ break;
}
- if (ImGui::IsItemHovered()) {
- ImGui::SetTooltip("x: %.3f\ny: %.3f", *x, *y);
- }
-
- // Return screen coordinates for the caller. We could just return center here, but we'd have
- // one frame of lag during drag.
- return ImVec2(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);
+ return false;
}
static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPaint) {
- ImDrawList* drawList = ImGui::GetWindowDrawList();
-
- // The gamut image covers a (0.8 x 0.9) shaped region, so fit our image/canvas to the available
- // width, and scale the height to maintain aspect ratio.
- float canvasWidth = SkTMax(ImGui::GetContentRegionAvailWidth(), 50.0f);
- ImVec2 size = ImVec2(canvasWidth, canvasWidth * (0.9f / 0.8f));
- ImVec2 pos = ImGui::GetCursorScreenPos();
+ // The gamut image covers a (0.8 x 0.9) shaped region
+ ImGui::DragCanvas dc(primaries, { 0.0f, 0.9f }, { 0.8f, 0.0f });
// Background image. Only draw a subset of the image, to avoid the regions less than zero.
// Simplifes re-mapping math, clipping behavior, and increases resolution in the useful area.
// Magic numbers are pixel locations of the origin and upper-right corner.
- drawList->AddImage(gamutPaint, pos, ImVec2(pos.x + size.x, pos.y + size.y),
- ImVec2(242, 61), ImVec2(1897, 1922));
- ImVec2 endPos = ImGui::GetCursorPos();
+ dc.fDrawList->AddImage(gamutPaint, dc.fPos,
+ ImVec2(dc.fPos.x + dc.fSize.x, dc.fPos.y + dc.fSize.y),
+ ImVec2(242, 61), ImVec2(1897, 1922));
- // Primary markers
- ImVec2 r = ImGui_DragPrimary("R", &primaries->fRX, &primaries->fRY, pos, size);
- ImVec2 g = ImGui_DragPrimary("G", &primaries->fGX, &primaries->fGY, pos, size);
- ImVec2 b = ImGui_DragPrimary("B", &primaries->fBX, &primaries->fBY, pos, size);
- ImVec2 w = ImGui_DragPrimary("W", &primaries->fWX, &primaries->fWY, pos, size);
-
- // Gamut triangle
- drawList->AddCircle(r, 5.0f, 0xFF000040);
- drawList->AddCircle(g, 5.0f, 0xFF004000);
- drawList->AddCircle(b, 5.0f, 0xFF400000);
- drawList->AddCircle(w, 5.0f, 0xFFFFFFFF);
- drawList->AddTriangle(r, g, b, 0xFFFFFFFF);
-
- // Re-position cursor immediate after the diagram for subsequent controls
- ImGui::SetCursorPos(endPos);
+ dc.dragPoint((SkPoint*)(&primaries->fRX), true, 0xFF000040);
+ dc.dragPoint((SkPoint*)(&primaries->fGX), true, 0xFF004000);
+ dc.dragPoint((SkPoint*)(&primaries->fBX), true, 0xFF400000);
+ dc.dragPoint((SkPoint*)(&primaries->fWX), true);
+ dc.fDrawList->AddPolyline(dc.fScreenPoints.begin(), 3, 0xFFFFFFFF, true, 1.5f);
}
-void Viewer::drawImGui(SkCanvas* canvas) {
+static bool ImGui_DragLocation(SkPoint* pt) {
+ ImGui::DragCanvas dc(pt);
+ dc.fillColor(IM_COL32(0, 0, 0, 128));
+ dc.dragPoint(pt);
+ return dc.fDragging;
+}
+
+static bool ImGui_DragQuad(SkPoint* pts) {
+ ImGui::DragCanvas dc(pts);
+ dc.fillColor(IM_COL32(0, 0, 0, 128));
+
+ for (int i = 0; i < 4; ++i) {
+ dc.dragPoint(pts + i);
+ }
+
+ dc.fDrawList->AddLine(dc.fScreenPoints[0], dc.fScreenPoints[1], 0xFFFFFFFF);
+ dc.fDrawList->AddLine(dc.fScreenPoints[1], dc.fScreenPoints[3], 0xFFFFFFFF);
+ dc.fDrawList->AddLine(dc.fScreenPoints[3], dc.fScreenPoints[2], 0xFFFFFFFF);
+ dc.fDrawList->AddLine(dc.fScreenPoints[2], dc.fScreenPoints[0], 0xFFFFFFFF);
+
+ return dc.fDragging;
+}
+
+void Viewer::drawImGui() {
// Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
if (fShowImGuiTestWindow) {
- ImGui::ShowTestWindow(&fShowImGuiTestWindow);
+ ImGui::ShowDemoWindow(&fShowImGuiTestWindow);
}
if (fShowImGuiDebugWindow) {
// We have some dynamic content that sizes to fill available size. If the scroll bar isn't
// always visible, we can end up in a layout feedback loop.
- ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiSetCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
DisplayParams params = fWindow->getRequestedDisplayParams();
bool paramsChanged = false;
+ const GrContext* ctx = fWindow->getGrContext();
+
if (ImGui::Begin("Tools", &fShowImGuiDebugWindow,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
if (ImGui::CollapsingHeader("Backend")) {
@@ -1012,21 +1604,28 @@
ImGui::RadioButton("Raster", &newBackend, sk_app::Window::kRaster_BackendType);
ImGui::SameLine();
ImGui::RadioButton("OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ ImGui::SameLine();
+ ImGui::RadioButton("ANGLE", &newBackend, sk_app::Window::kANGLE_BackendType);
+#endif
+#if defined(SK_DAWN)
+ ImGui::SameLine();
+ ImGui::RadioButton("Dawn", &newBackend, sk_app::Window::kDawn_BackendType);
+#endif
#if defined(SK_VULKAN)
ImGui::SameLine();
ImGui::RadioButton("Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);
#endif
+#if defined(SK_METAL)
+ ImGui::SameLine();
+ ImGui::RadioButton("Metal", &newBackend, sk_app::Window::kMetal_BackendType);
+#endif
if (newBackend != fBackendType) {
fDeferredActions.push_back([=]() {
this->setBackend(static_cast<sk_app::Window::BackendType>(newBackend));
});
}
- const GrContext* ctx = fWindow->getGrContext();
- bool* inst = ¶ms.fGrContextOptions.fEnableInstancedRendering;
- if (ctx && ImGui::Checkbox("Instanced Rendering", inst)) {
- paramsChanged = true;
- }
bool* wire = ¶ms.fGrContextOptions.fWireframeMode;
if (ctx && ImGui::Checkbox("Wireframe Mode", wire)) {
paramsChanged = true;
@@ -1035,7 +1634,7 @@
if (ctx) {
int sampleCount = fWindow->sampleCount();
ImGui::Text("MSAA: "); ImGui::SameLine();
- ImGui::RadioButton("0", &sampleCount, 0); ImGui::SameLine();
+ ImGui::RadioButton("1", &sampleCount, 1); ImGui::SameLine();
ImGui::RadioButton("4", &sampleCount, 4); ImGui::SameLine();
ImGui::RadioButton("8", &sampleCount, 8); ImGui::SameLine();
ImGui::RadioButton("16", &sampleCount, 16);
@@ -1046,6 +1645,38 @@
}
}
+ int pixelGeometryIdx = 0;
+ if (fPixelGeometryOverrides) {
+ pixelGeometryIdx = params.fSurfaceProps.pixelGeometry() + 1;
+ }
+ if (ImGui::Combo("Pixel Geometry", &pixelGeometryIdx,
+ "Default\0Flat\0RGB\0BGR\0RGBV\0BGRV\0\0"))
+ {
+ uint32_t flags = params.fSurfaceProps.flags();
+ if (pixelGeometryIdx == 0) {
+ fPixelGeometryOverrides = false;
+ params.fSurfaceProps = SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+ } else {
+ fPixelGeometryOverrides = true;
+ SkPixelGeometry pixelGeometry = SkTo<SkPixelGeometry>(pixelGeometryIdx - 1);
+ params.fSurfaceProps = SkSurfaceProps(flags, pixelGeometry);
+ }
+ paramsChanged = true;
+ }
+
+ bool useDFT = params.fSurfaceProps.isUseDeviceIndependentFonts();
+ if (ImGui::Checkbox("DFT", &useDFT)) {
+ uint32_t flags = params.fSurfaceProps.flags();
+ if (useDFT) {
+ flags |= SkSurfaceProps::kUseDeviceIndependentFonts_Flag;
+ } else {
+ flags &= ~SkSurfaceProps::kUseDeviceIndependentFonts_Flag;
+ }
+ SkPixelGeometry pixelGeometry = params.fSurfaceProps.pixelGeometry();
+ params.fSurfaceProps = SkSurfaceProps(flags, pixelGeometry);
+ paramsChanged = true;
+ }
+
if (ImGui::TreeNode("Path Renderers")) {
GpuPathRenderers prevPr = params.fGrContextOptions.fGpuPathRenderers;
auto prButton = [&](GpuPathRenderers x) {
@@ -1059,20 +1690,17 @@
if (!ctx) {
ImGui::RadioButton("Software", true);
- } else if (fWindow->sampleCount()) {
+ } else if (fWindow->sampleCount() > 1) {
prButton(GpuPathRenderers::kAll);
- if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
+ if (ctx->priv().caps()->shaderCaps()->pathRenderingSupport()) {
prButton(GpuPathRenderers::kStencilAndCover);
}
- if (ctx->caps()->sampleShadingSupport()) {
- prButton(GpuPathRenderers::kMSAA);
- }
prButton(GpuPathRenderers::kTessellating);
- prButton(GpuPathRenderers::kDefault);
prButton(GpuPathRenderers::kNone);
} else {
prButton(GpuPathRenderers::kAll);
- if (GrCoverageCountingPathRenderer::IsSupported(*ctx->caps())) {
+ if (GrCoverageCountingPathRenderer::IsSupported(
+ *ctx->priv().caps())) {
prButton(GpuPathRenderers::kCoverageCounting);
}
prButton(GpuPathRenderers::kSmall);
@@ -1083,23 +1711,305 @@
}
}
- if (ImGui::CollapsingHeader("Slide")) {
- static ImGuiTextFilter filter;
- filter.Draw();
- int previousSlide = fCurrentSlide;
- fCurrentSlide = 0;
- for (auto slide : fSlides) {
- if (filter.PassFilter(slide->getName().c_str())) {
- ImGui::BulletText("%s", slide->getName().c_str());
- if (ImGui::IsItemClicked()) {
- setupCurrentSlide(previousSlide);
- break;
+ if (ImGui::CollapsingHeader("Tiling")) {
+ ImGui::Checkbox("Enable", &fTiled);
+ ImGui::Checkbox("Draw Boundaries", &fDrawTileBoundaries);
+ ImGui::SliderFloat("Horizontal", &fTileScale.fWidth, 0.1f, 1.0f);
+ ImGui::SliderFloat("Vertical", &fTileScale.fHeight, 0.1f, 1.0f);
+ }
+
+ if (ImGui::CollapsingHeader("Transform")) {
+ float zoom = fZoomLevel;
+ if (ImGui::SliderFloat("Zoom", &zoom, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL)) {
+ fZoomLevel = zoom;
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ }
+ float deg = fRotation;
+ if (ImGui::SliderFloat("Rotate", °, -30, 360, "%.3f deg")) {
+ fRotation = deg;
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ }
+ if (ImGui::CollapsingHeader("Subpixel offset", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
+ if (ImGui_DragLocation(&fOffset)) {
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ }
+ } else if (fOffset != SkVector{0.5f, 0.5f}) {
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ fOffset = {0.5f, 0.5f};
+ }
+ int perspectiveMode = static_cast<int>(fPerspectiveMode);
+ if (ImGui::Combo("Perspective", &perspectiveMode, "Off\0Real\0Fake\0\0")) {
+ fPerspectiveMode = static_cast<PerspectiveMode>(perspectiveMode);
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ }
+ if (perspectiveMode != kPerspective_Off && ImGui_DragQuad(fPerspectivePoints)) {
+ this->preTouchMatrixChanged();
+ paramsChanged = true;
+ }
+ }
+
+ if (ImGui::CollapsingHeader("Paint")) {
+ int aliasIdx = 0;
+ if (fPaintOverrides.fAntiAlias) {
+ aliasIdx = SkTo<int>(fPaintOverrides.fAntiAliasState) + 1;
+ }
+ if (ImGui::Combo("Anti-Alias", &aliasIdx,
+ "Default\0Alias\0Normal\0AnalyticAAEnabled\0AnalyticAAForced\0\0"))
+ {
+ gSkUseAnalyticAA = fPaintOverrides.fOriginalSkUseAnalyticAA;
+ gSkForceAnalyticAA = fPaintOverrides.fOriginalSkForceAnalyticAA;
+ if (aliasIdx == 0) {
+ fPaintOverrides.fAntiAliasState = SkPaintFields::AntiAliasState::Alias;
+ fPaintOverrides.fAntiAlias = false;
+ } else {
+ fPaintOverrides.fAntiAlias = true;
+ fPaintOverrides.fAntiAliasState = SkTo<SkPaintFields::AntiAliasState>(aliasIdx-1);
+ fPaint.setAntiAlias(aliasIdx > 1);
+ switch (fPaintOverrides.fAntiAliasState) {
+ case SkPaintFields::AntiAliasState::Alias:
+ break;
+ case SkPaintFields::AntiAliasState::Normal:
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAEnabled:
+ gSkUseAnalyticAA = true;
+ gSkForceAnalyticAA = false;
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAForced:
+ gSkUseAnalyticAA = gSkForceAnalyticAA = true;
+ break;
}
}
- ++fCurrentSlide;
+ paramsChanged = true;
}
- if (fCurrentSlide >= fSlides.count()) {
- fCurrentSlide = previousSlide;
+
+ auto paintFlag = [this, ¶msChanged](const char* label, const char* items,
+ bool SkPaintFields::* flag,
+ bool (SkPaint::* isFlag)() const,
+ void (SkPaint::* setFlag)(bool) )
+ {
+ int itemIndex = 0;
+ if (fPaintOverrides.*flag) {
+ itemIndex = (fPaint.*isFlag)() ? 2 : 1;
+ }
+ if (ImGui::Combo(label, &itemIndex, items)) {
+ if (itemIndex == 0) {
+ fPaintOverrides.*flag = false;
+ } else {
+ fPaintOverrides.*flag = true;
+ (fPaint.*setFlag)(itemIndex == 2);
+ }
+ paramsChanged = true;
+ }
+ };
+
+ paintFlag("Dither",
+ "Default\0No Dither\0Dither\0\0",
+ &SkPaintFields::fDither,
+ &SkPaint::isDither, &SkPaint::setDither);
+
+ int filterQualityIdx = 0;
+ if (fPaintOverrides.fFilterQuality) {
+ filterQualityIdx = SkTo<int>(fPaint.getFilterQuality()) + 1;
+ }
+ if (ImGui::Combo("Filter Quality", &filterQualityIdx,
+ "Default\0None\0Low\0Medium\0High\0\0"))
+ {
+ if (filterQualityIdx == 0) {
+ fPaintOverrides.fFilterQuality = false;
+ fPaint.setFilterQuality(kNone_SkFilterQuality);
+ } else {
+ fPaint.setFilterQuality(SkTo<SkFilterQuality>(filterQualityIdx - 1));
+ fPaintOverrides.fFilterQuality = true;
+ }
+ paramsChanged = true;
+ }
+ }
+
+ if (ImGui::CollapsingHeader("Font")) {
+ int hintingIdx = 0;
+ if (fFontOverrides.fHinting) {
+ hintingIdx = SkTo<int>(fFont.getHinting()) + 1;
+ }
+ if (ImGui::Combo("Hinting", &hintingIdx,
+ "Default\0None\0Slight\0Normal\0Full\0\0"))
+ {
+ if (hintingIdx == 0) {
+ fFontOverrides.fHinting = false;
+ fFont.setHinting(SkFontHinting::kNone);
+ } else {
+ fFont.setHinting(SkTo<SkFontHinting>(hintingIdx - 1));
+ fFontOverrides.fHinting = true;
+ }
+ paramsChanged = true;
+ }
+
+ auto fontFlag = [this, ¶msChanged](const char* label, const char* items,
+ bool SkFontFields::* flag,
+ bool (SkFont::* isFlag)() const,
+ void (SkFont::* setFlag)(bool) )
+ {
+ int itemIndex = 0;
+ if (fFontOverrides.*flag) {
+ itemIndex = (fFont.*isFlag)() ? 2 : 1;
+ }
+ if (ImGui::Combo(label, &itemIndex, items)) {
+ if (itemIndex == 0) {
+ fFontOverrides.*flag = false;
+ } else {
+ fFontOverrides.*flag = true;
+ (fFont.*setFlag)(itemIndex == 2);
+ }
+ paramsChanged = true;
+ }
+ };
+
+ fontFlag("Fake Bold Glyphs",
+ "Default\0No Fake Bold\0Fake Bold\0\0",
+ &SkFontFields::fEmbolden,
+ &SkFont::isEmbolden, &SkFont::setEmbolden);
+
+ fontFlag("Baseline Snapping",
+ "Default\0No Baseline Snapping\0Baseline Snapping\0\0",
+ &SkFontFields::fBaselineSnap,
+ &SkFont::isBaselineSnap, &SkFont::setBaselineSnap);
+
+ fontFlag("Linear Text",
+ "Default\0No Linear Text\0Linear Text\0\0",
+ &SkFontFields::fLinearMetrics,
+ &SkFont::isLinearMetrics, &SkFont::setLinearMetrics);
+
+ fontFlag("Subpixel Position Glyphs",
+ "Default\0Pixel Text\0Subpixel Text\0\0",
+ &SkFontFields::fSubpixel,
+ &SkFont::isSubpixel, &SkFont::setSubpixel);
+
+ fontFlag("Embedded Bitmap Text",
+ "Default\0No Embedded Bitmaps\0Embedded Bitmaps\0\0",
+ &SkFontFields::fEmbeddedBitmaps,
+ &SkFont::isEmbeddedBitmaps, &SkFont::setEmbeddedBitmaps);
+
+ fontFlag("Force Auto-Hinting",
+ "Default\0No Force Auto-Hinting\0Force Auto-Hinting\0\0",
+ &SkFontFields::fForceAutoHinting,
+ &SkFont::isForceAutoHinting, &SkFont::setForceAutoHinting);
+
+ int edgingIdx = 0;
+ if (fFontOverrides.fEdging) {
+ edgingIdx = SkTo<int>(fFont.getEdging()) + 1;
+ }
+ if (ImGui::Combo("Edging", &edgingIdx,
+ "Default\0Alias\0Antialias\0Subpixel Antialias\0\0"))
+ {
+ if (edgingIdx == 0) {
+ fFontOverrides.fEdging = false;
+ fFont.setEdging(SkFont::Edging::kAlias);
+ } else {
+ fFont.setEdging(SkTo<SkFont::Edging>(edgingIdx-1));
+ fFontOverrides.fEdging = true;
+ }
+ paramsChanged = true;
+ }
+
+ ImGui::Checkbox("Override Size", &fFontOverrides.fSize);
+ if (fFontOverrides.fSize) {
+ ImGui::DragFloat2("TextRange", fFontOverrides.fSizeRange,
+ 0.001f, -10.0f, 300.0f, "%.6f", 2.0f);
+ float textSize = fFont.getSize();
+ if (ImGui::DragFloat("TextSize", &textSize, 0.001f,
+ fFontOverrides.fSizeRange[0],
+ fFontOverrides.fSizeRange[1],
+ "%.6f", 2.0f))
+ {
+ fFont.setSize(textSize);
+ paramsChanged = true;
+ }
+ }
+
+ ImGui::Checkbox("Override ScaleX", &fFontOverrides.fScaleX);
+ if (fFontOverrides.fScaleX) {
+ float scaleX = fFont.getScaleX();
+ if (ImGui::SliderFloat("ScaleX", &scaleX, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL)) {
+ fFont.setScaleX(scaleX);
+ paramsChanged = true;
+ }
+ }
+
+ ImGui::Checkbox("Override SkewX", &fFontOverrides.fSkewX);
+ if (fFontOverrides.fSkewX) {
+ float skewX = fFont.getSkewX();
+ if (ImGui::SliderFloat("SkewX", &skewX, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL)) {
+ fFont.setSkewX(skewX);
+ paramsChanged = true;
+ }
+ }
+ }
+
+ {
+ SkMetaData controls;
+ if (fSlides[fCurrentSlide]->onGetControls(&controls)) {
+ if (ImGui::CollapsingHeader("Current Slide")) {
+ SkMetaData::Iter iter(controls);
+ const char* name;
+ SkMetaData::Type type;
+ int count;
+ while ((name = iter.next(&type, &count)) != nullptr) {
+ if (type == SkMetaData::kScalar_Type) {
+ float val[3];
+ SkASSERT(count == 3);
+ controls.findScalars(name, &count, val);
+ if (ImGui::SliderFloat(name, &val[0], val[1], val[2])) {
+ controls.setScalars(name, 3, val);
+ }
+ } else if (type == SkMetaData::kBool_Type) {
+ bool val;
+ SkASSERT(count == 1);
+ controls.findBool(name, &val);
+ if (ImGui::Checkbox(name, &val)) {
+ controls.setBool(name, val);
+ }
+ }
+ }
+ fSlides[fCurrentSlide]->onSetControls(controls);
+ }
+ }
+ }
+
+ if (fShowSlidePicker) {
+ ImGui::SetNextTreeNodeOpen(true);
+ }
+ if (ImGui::CollapsingHeader("Slide")) {
+ static ImGuiTextFilter filter;
+ static ImVector<const char*> filteredSlideNames;
+ static ImVector<int> filteredSlideIndices;
+
+ if (fShowSlidePicker) {
+ ImGui::SetKeyboardFocusHere();
+ fShowSlidePicker = false;
+ }
+
+ filter.Draw();
+ filteredSlideNames.clear();
+ filteredSlideIndices.clear();
+ int filteredIndex = 0;
+ for (int i = 0; i < fSlides.count(); ++i) {
+ const char* slideName = fSlides[i]->getName().c_str();
+ if (filter.PassFilter(slideName) || i == fCurrentSlide) {
+ if (i == fCurrentSlide) {
+ filteredIndex = filteredSlideIndices.size();
+ }
+ filteredSlideNames.push_back(slideName);
+ filteredSlideIndices.push_back(i);
+ }
+ }
+
+ if (ImGui::ListBox("", &filteredIndex, filteredSlideNames.begin(),
+ filteredSlideNames.size(), 20)) {
+ this->setCurrentSlide(filteredSlideIndices[filteredIndex]);
}
}
@@ -1112,17 +2022,12 @@
};
cmButton(ColorMode::kLegacy, "Legacy 8888");
- cmButton(ColorMode::kColorManagedSRGB8888_NonLinearBlending,
- "Color Managed 8888 (Nonlinear blending)");
- cmButton(ColorMode::kColorManagedSRGB8888, "Color Managed 8888");
- cmButton(ColorMode::kColorManagedLinearF16, "Color Managed F16");
+ cmButton(ColorMode::kColorManaged8888, "Color Managed 8888");
+ cmButton(ColorMode::kColorManagedF16, "Color Managed F16");
+ cmButton(ColorMode::kColorManagedF16Norm, "Color Managed F16 Norm");
if (newMode != fColorMode) {
- // It isn't safe to switch color mode now (in the middle of painting). We might
- // tear down the back-end, etc... Defer this change until the next onIdle.
- fDeferredActions.push_back([=]() {
- this->setColorMode(newMode);
- });
+ this->setColorMode(newMode);
}
// Pick from common gamuts:
@@ -1134,6 +2039,9 @@
}
}
+ // Let user adjust the gamma
+ ImGui::SliderFloat("Gamma", &fColorSpaceTransferFn.g, 0.5f, 3.5f);
+
if (ImGui::Combo("Primaries", &primariesIdx,
"sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
if (primariesIdx >= 0 && primariesIdx <= 3) {
@@ -1144,6 +2052,142 @@
// Allow direct editing of gamut
ImGui_Primaries(&fColorSpacePrimaries, &fImGuiGamutPaint);
}
+
+ if (ImGui::CollapsingHeader("Animation")) {
+ bool isPaused = AnimTimer::kPaused_State == fAnimTimer.state();
+ if (ImGui::Checkbox("Pause", &isPaused)) {
+ fAnimTimer.togglePauseResume();
+ }
+
+ float speed = fAnimTimer.getSpeed();
+ if (ImGui::DragFloat("Speed", &speed, 0.1f)) {
+ fAnimTimer.setSpeed(speed);
+ }
+ }
+
+ bool backendIsGL = Window::kNativeGL_BackendType == fBackendType
+#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
+ || Window::kANGLE_BackendType == fBackendType
+#endif
+ ;
+
+ // HACK: If we get here when SKSL caching isn't enabled, and we're on a backend other
+ // than GL, we need to force it on. Just do that on the first frame after the backend
+ // switch, then resume normal operation.
+ if (!backendIsGL &&
+ params.fGrContextOptions.fShaderCacheStrategy !=
+ GrContextOptions::ShaderCacheStrategy::kSkSL) {
+ params.fGrContextOptions.fShaderCacheStrategy =
+ GrContextOptions::ShaderCacheStrategy::kSkSL;
+ paramsChanged = true;
+ fPersistentCache.reset();
+ } else if (ImGui::CollapsingHeader("Shaders")) {
+ // To re-load shaders from the currently active programs, we flush all caches on one
+ // frame, then set a flag to poll the cache on the next frame.
+ static bool gLoadPending = false;
+ if (gLoadPending) {
+ auto collectShaders = [this](sk_sp<const SkData> key, sk_sp<SkData> data,
+ int hitCount) {
+ CachedGLSL& entry(fCachedGLSL.push_back());
+ entry.fKey = key;
+ SkMD5 hash;
+ hash.write(key->bytes(), key->size());
+ SkMD5::Digest digest = hash.finish();
+ for (int i = 0; i < 16; ++i) {
+ entry.fKeyString.appendf("%02x", digest.data[i]);
+ }
+
+ SkReader32 reader(data->data(), data->size());
+ entry.fShaderType = reader.readU32();
+ GrPersistentCacheUtils::UnpackCachedShaders(&reader, entry.fShader,
+ entry.fInputs,
+ kGrShaderTypeCount);
+ };
+ fCachedGLSL.reset();
+ fPersistentCache.foreach(collectShaders);
+ gLoadPending = false;
+ }
+
+ // Defer actually doing the load/save logic so that we can trigger a save when we
+ // start or finish hovering on a tree node in the list below:
+ bool doLoad = ImGui::Button("Load"); ImGui::SameLine();
+ bool doSave = ImGui::Button("Save");
+ if (backendIsGL) {
+ ImGui::SameLine();
+ bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
+ GrContextOptions::ShaderCacheStrategy::kSkSL;
+ if (ImGui::Checkbox("SkSL", &sksl)) {
+ params.fGrContextOptions.fShaderCacheStrategy = sksl
+ ? GrContextOptions::ShaderCacheStrategy::kSkSL
+ : GrContextOptions::ShaderCacheStrategy::kBackendSource;
+ paramsChanged = true;
+ doLoad = true;
+ fDeferredActions.push_back([=]() { fPersistentCache.reset(); });
+ }
+ }
+
+ ImGui::BeginChild("##ScrollingRegion");
+ for (auto& entry : fCachedGLSL) {
+ bool inTreeNode = ImGui::TreeNode(entry.fKeyString.c_str());
+ bool hovered = ImGui::IsItemHovered();
+ if (hovered != entry.fHovered) {
+ // Force a save to patch the highlight shader in/out
+ entry.fHovered = hovered;
+ doSave = true;
+ }
+ if (inTreeNode) {
+ // Full width, and a reasonable amount of space for each shader.
+ ImVec2 boxSize(-1.0f, ImGui::GetTextLineHeight() * 20.0f);
+ ImGui::InputTextMultiline("##VP", &entry.fShader[kVertex_GrShaderType],
+ boxSize);
+ ImGui::InputTextMultiline("##FP", &entry.fShader[kFragment_GrShaderType],
+ boxSize);
+ ImGui::TreePop();
+ }
+ }
+ ImGui::EndChild();
+
+ if (doLoad) {
+ fPersistentCache.reset();
+ fWindow->getGrContext()->priv().getGpu()->resetShaderCacheForTesting();
+ gLoadPending = true;
+ }
+ if (doSave) {
+ // The hovered item (if any) gets a special shader to make it identifiable
+ auto shaderCaps = ctx->priv().caps()->shaderCaps();
+ bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
+ GrContextOptions::ShaderCacheStrategy::kSkSL;
+
+ SkSL::String highlight;
+ if (!sksl) {
+ highlight = shaderCaps->versionDeclString();
+ if (shaderCaps->usesPrecisionModifiers()) {
+ highlight.append("precision mediump float;\n");
+ }
+ }
+ const char* f4Type = sksl ? "half4" : "vec4";
+ highlight.appendf("out %s sk_FragColor;\n"
+ "void main() { sk_FragColor = %s(1, 0, 1, 0.5); }",
+ f4Type, f4Type);
+
+ fPersistentCache.reset();
+ fWindow->getGrContext()->priv().getGpu()->resetShaderCacheForTesting();
+ for (auto& entry : fCachedGLSL) {
+ SkSL::String backup = entry.fShader[kFragment_GrShaderType];
+ if (entry.fHovered) {
+ entry.fShader[kFragment_GrShaderType] = highlight;
+ }
+
+ auto data = GrPersistentCacheUtils::PackCachedShaders(entry.fShaderType,
+ entry.fShader,
+ entry.fInputs,
+ kGrShaderTypeCount);
+ fPersistentCache.store(*entry.fKey, *data);
+
+ entry.fShader[kFragment_GrShaderType] = backup;
+ }
+ }
+ }
}
if (paramsChanged) {
fDeferredActions.push_back([=]() {
@@ -1155,80 +2199,65 @@
ImGui::End();
}
- SkPaint zoomImagePaint;
+ if (gShaderErrorHandler.fErrors.count()) {
+ ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Shader Errors");
+ for (int i = 0; i < gShaderErrorHandler.fErrors.count(); ++i) {
+ ImGui::TextWrapped("%s", gShaderErrorHandler.fErrors[i].c_str());
+ ImGui::TextWrapped("%s", gShaderErrorHandler.fShaders[i].c_str());
+ }
+ ImGui::End();
+ gShaderErrorHandler.reset();
+ }
+
if (fShowZoomWindow && fLastImage) {
- if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) {
- static int zoomFactor = 4;
- ImGui::SliderInt("Scale", &zoomFactor, 1, 16);
+ ImGui::SetNextWindowSize(ImVec2(200, 200), ImGuiCond_FirstUseEver);
+ if (ImGui::Begin("Zoom", &fShowZoomWindow)) {
+ static int zoomFactor = 8;
+ if (ImGui::Button("<<")) {
+ zoomFactor = SkTMax(zoomFactor / 2, 4);
+ }
+ ImGui::SameLine(); ImGui::Text("%2d", zoomFactor); ImGui::SameLine();
+ if (ImGui::Button(">>")) {
+ zoomFactor = SkTMin(zoomFactor * 2, 32);
+ }
- zoomImagePaint.setShader(fLastImage->makeShader());
- zoomImagePaint.setColor(SK_ColorWHITE);
-
- // Zoom by shrinking the corner UVs towards the mouse cursor
- ImVec2 mousePos = ImGui::GetMousePos();
+ if (!fZoomWindowFixed) {
+ ImVec2 mousePos = ImGui::GetMousePos();
+ fZoomWindowLocation = SkPoint::Make(mousePos.x, mousePos.y);
+ }
+ SkScalar x = fZoomWindowLocation.x();
+ SkScalar y = fZoomWindowLocation.y();
+ int xInt = SkScalarRoundToInt(x);
+ int yInt = SkScalarRoundToInt(y);
ImVec2 avail = ImGui::GetContentRegionAvail();
- ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor,
- (avail.y * 0.5f) / zoomFactor);
- ImGui::Image(&zoomImagePaint, avail,
- ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y),
- ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y));
+ uint32_t pixel = 0;
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
+ if (fLastImage->readPixels(info, &pixel, info.minRowBytes(), xInt, yInt)) {
+ ImGui::SameLine();
+ ImGui::Text("(X, Y): %d, %d RGBA: %X %X %X %X",
+ xInt, yInt,
+ SkGetPackedR32(pixel), SkGetPackedG32(pixel),
+ SkGetPackedB32(pixel), SkGetPackedA32(pixel));
+ }
+
+ fImGuiLayer.skiaWidget(avail, [=](SkCanvas* c) {
+ // Translate so the region of the image that's under the mouse cursor is centered
+ // in the zoom canvas:
+ c->scale(zoomFactor, zoomFactor);
+ c->translate(avail.x * 0.5f / zoomFactor - x - 0.5f,
+ avail.y * 0.5f / zoomFactor - y - 0.5f);
+ c->drawImage(this->fLastImage, 0, 0);
+
+ SkPaint outline;
+ outline.setStyle(SkPaint::kStroke_Style);
+ c->drawRect(SkRect::MakeXYWH(x, y, 1, 1), outline);
+ });
}
ImGui::End();
}
-
- // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
- // (widgets, etc...) that have been issued
- ImGui::Render();
-
- // Then we fetch the most recent data, and convert it so we can render with Skia
- const ImDrawData* drawData = ImGui::GetDrawData();
- SkTDArray<SkPoint> pos;
- SkTDArray<SkPoint> uv;
- SkTDArray<SkColor> color;
-
- for (int i = 0; i < drawData->CmdListsCount; ++i) {
- const ImDrawList* drawList = drawData->CmdLists[i];
-
- // De-interleave all vertex data (sigh), convert to Skia types
- pos.rewind(); uv.rewind(); color.rewind();
- for (int i = 0; i < drawList->VtxBuffer.size(); ++i) {
- const ImDrawVert& vert = drawList->VtxBuffer[i];
- pos.push(SkPoint::Make(vert.pos.x, vert.pos.y));
- uv.push(SkPoint::Make(vert.uv.x, vert.uv.y));
- color.push(vert.col);
- }
- // ImGui colors are RGBA
- SkSwapRB(color.begin(), color.begin(), color.count());
-
- int indexOffset = 0;
-
- // Draw everything with canvas.drawVertices...
- for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
- const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
-
- // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
- if (drawCmd->UserCallback) {
- drawCmd->UserCallback(drawList, drawCmd);
- } else {
- SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
- SkASSERT(paint);
-
- canvas->save();
- canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
- drawCmd->ClipRect.z, drawCmd->ClipRect.w));
- canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
- drawList->VtxBuffer.size(), pos.begin(),
- uv.begin(), color.begin(),
- drawCmd->ElemCount,
- drawList->IdxBuffer.begin() + indexOffset),
- SkBlendMode::kModulate, *paint);
- indexOffset += drawCmd->ElemCount;
- canvas->restore();
- }
- }
- }
}
void Viewer::onIdle() {
@@ -1237,133 +2266,130 @@
}
fDeferredActions.reset();
- double startTime = SkTime::GetMSecs();
+ fStatsLayer.beginTiming(fAnimateTimer);
fAnimTimer.updateTime();
- bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer);
- fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
+ bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer.nanos());
+ fStatsLayer.endTiming(fAnimateTimer);
ImGuiIO& io = ImGui::GetIO();
- if (animateWantsInval || fDisplayStats || fRefresh || io.MetricsActiveWindows) {
+ // ImGui always has at least one "active" window, which is the default "Debug" window. It may
+ // not be visible, though. So we need to redraw if there is at least one visible window, or
+ // more than one active window. Newly created windows are active but not visible for one frame
+ // while they determine their layout and sizing.
+ if (animateWantsInval || fStatsLayer.getActive() || fRefresh ||
+ io.MetricsActiveWindows > 1 || io.MetricsRenderWindows > 0) {
fWindow->inval();
}
}
+template <typename OptionsFunc>
+static void WriteStateObject(SkJSONWriter& writer, const char* name, const char* value,
+ OptionsFunc&& optionsFunc) {
+ writer.beginObject();
+ {
+ writer.appendString(kName , name);
+ writer.appendString(kValue, value);
+
+ writer.beginArray(kOptions);
+ {
+ optionsFunc(writer);
+ }
+ writer.endArray();
+ }
+ writer.endObject();
+}
+
+
void Viewer::updateUIState() {
if (!fWindow) {
return;
}
- if (fWindow->sampleCount() < 0) {
+ if (fWindow->sampleCount() < 1) {
return; // Surface hasn't been created yet.
}
+ SkDynamicMemoryWStream memStream;
+ SkJSONWriter writer(&memStream);
+ writer.beginArray();
+
// Slide state
- Json::Value slideState(Json::objectValue);
- slideState[kName] = kSlideStateName;
- slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str();
- if (fAllSlideNames.size() == 0) {
- for(auto slide : fSlides) {
- fAllSlideNames.append(Json::Value(slide->getName().c_str()));
- }
- }
- slideState[kOptions] = fAllSlideNames;
+ WriteStateObject(writer, kSlideStateName, fSlides[fCurrentSlide]->getName().c_str(),
+ [this](SkJSONWriter& writer) {
+ for(const auto& slide : fSlides) {
+ writer.appendString(slide->getName().c_str());
+ }
+ });
// Backend state
- Json::Value backendState(Json::objectValue);
- backendState[kName] = kBackendStateName;
- backendState[kValue] = kBackendTypeStrings[fBackendType];
- backendState[kOptions] = Json::Value(Json::arrayValue);
- for (auto str : kBackendTypeStrings) {
- backendState[kOptions].append(Json::Value(str));
- }
+ WriteStateObject(writer, kBackendStateName, kBackendTypeStrings[fBackendType],
+ [](SkJSONWriter& writer) {
+ for (const auto& str : kBackendTypeStrings) {
+ writer.appendString(str);
+ }
+ });
// MSAA state
- Json::Value msaaState(Json::objectValue);
- msaaState[kName] = kMSAAStateName;
- msaaState[kValue] = fWindow->sampleCount();
- msaaState[kOptions] = Json::Value(Json::arrayValue);
- if (sk_app::Window::kRaster_BackendType == fBackendType) {
- msaaState[kOptions].append(Json::Value(0));
- } else {
- for (int msaa : {0, 4, 8, 16}) {
- msaaState[kOptions].append(Json::Value(msaa));
- }
- }
+ const auto countString = SkStringPrintf("%d", fWindow->sampleCount());
+ WriteStateObject(writer, kMSAAStateName, countString.c_str(),
+ [this](SkJSONWriter& writer) {
+ writer.appendS32(0);
+
+ if (sk_app::Window::kRaster_BackendType == fBackendType) {
+ return;
+ }
+
+ for (int msaa : {4, 8, 16}) {
+ writer.appendS32(msaa);
+ }
+ });
// Path renderer state
GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
- Json::Value prState(Json::objectValue);
- prState[kName] = kPathRendererStateName;
- prState[kValue] = gPathRendererNames[pr];
- prState[kOptions] = Json::Value(Json::arrayValue);
- const GrContext* ctx = fWindow->getGrContext();
- if (!ctx) {
- prState[kOptions].append("Software");
- } else if (fWindow->sampleCount()) {
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
- if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kStencilAndCover]);
- }
- if (ctx->caps()->sampleShadingSupport()) {
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kMSAA]);
- }
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kDefault]);
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
- } else {
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
- if (GrCoverageCountingPathRenderer::IsSupported(*ctx->caps())) {
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kCoverageCounting]);
- }
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kSmall]);
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
- prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
- }
+ WriteStateObject(writer, kPathRendererStateName, gPathRendererNames[pr].c_str(),
+ [this](SkJSONWriter& writer) {
+ const GrContext* ctx = fWindow->getGrContext();
+ if (!ctx) {
+ writer.appendString("Software");
+ } else {
+ const auto* caps = ctx->priv().caps();
- // Instanced rendering state
- Json::Value instState(Json::objectValue);
- instState[kName] = kInstancedRenderingStateName;
- if (ctx) {
- if (fWindow->getRequestedDisplayParams().fGrContextOptions.fEnableInstancedRendering) {
- instState[kValue] = kON;
- } else {
- instState[kValue] = kOFF;
- }
- instState[kOptions] = Json::Value(Json::arrayValue);
- instState[kOptions].append(kOFF);
- instState[kOptions].append(kON);
- }
+ writer.appendString(gPathRendererNames[GpuPathRenderers::kAll].c_str());
+ if (fWindow->sampleCount() > 1) {
+ if (caps->shaderCaps()->pathRenderingSupport()) {
+ writer.appendString(
+ gPathRendererNames[GpuPathRenderers::kStencilAndCover].c_str());
+ }
+ } else {
+ if(GrCoverageCountingPathRenderer::IsSupported(*caps)) {
+ writer.appendString(
+ gPathRendererNames[GpuPathRenderers::kCoverageCounting].c_str());
+ }
+ writer.appendString(gPathRendererNames[GpuPathRenderers::kSmall].c_str());
+ }
+ writer.appendString(
+ gPathRendererNames[GpuPathRenderers::kTessellating].c_str());
+ writer.appendString(gPathRendererNames[GpuPathRenderers::kNone].c_str());
+ }
+ });
// Softkey state
- Json::Value softkeyState(Json::objectValue);
- softkeyState[kName] = kSoftkeyStateName;
- softkeyState[kValue] = kSoftkeyHint;
- softkeyState[kOptions] = Json::Value(Json::arrayValue);
- softkeyState[kOptions].append(kSoftkeyHint);
- for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
- softkeyState[kOptions].append(Json::Value(softkey.c_str()));
- }
+ WriteStateObject(writer, kSoftkeyStateName, kSoftkeyHint,
+ [this](SkJSONWriter& writer) {
+ writer.appendString(kSoftkeyHint);
+ for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
+ writer.appendString(softkey.c_str());
+ }
+ });
- // FPS state
- Json::Value fpsState(Json::objectValue);
- fpsState[kName] = kFpsStateName;
- int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1);
- fpsState[kValue] = SkStringPrintf("%8.3lf ms\n\nA %8.3lf\nP %8.3lf\nF%8.3lf",
- fAnimateTimes[idx] + fPaintTimes[idx] + fFlushTimes[idx],
- fAnimateTimes[idx],
- fPaintTimes[idx],
- fFlushTimes[idx]).c_str();
- fpsState[kOptions] = Json::Value(Json::arrayValue);
+ writer.endArray();
+ writer.flush();
- Json::Value state(Json::arrayValue);
- state.append(slideState);
- state.append(backendState);
- state.append(msaaState);
- state.append(prState);
- state.append(instState);
- state.append(softkeyState);
- state.append(fpsState);
+ auto data = memStream.detachAsData();
- fWindow->setUIState(state);
+ // TODO: would be cool to avoid this copy
+ const SkString cstring(static_cast<const char*>(data->data()), data->size());
+
+ fWindow->setUIState(cstring.c_str());
}
void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
@@ -1372,26 +2398,21 @@
// For example, after slide change, updateUIState is called inside setupCurrentSlide;
// after backend change, updateUIState is called in this function.
if (stateName.equals(kSlideStateName)) {
- int previousSlide = fCurrentSlide;
- fCurrentSlide = 0;
- for(auto slide : fSlides) {
- if (slide->getName().equals(stateValue)) {
- this->setupCurrentSlide(previousSlide);
- break;
+ for (int i = 0; i < fSlides.count(); ++i) {
+ if (fSlides[i]->getName().equals(stateValue)) {
+ this->setCurrentSlide(i);
+ return;
}
- fCurrentSlide++;
}
- if (fCurrentSlide >= fSlides.count()) {
- fCurrentSlide = previousSlide;
- SkDebugf("Slide not found: %s", stateValue.c_str());
- }
+
+ SkDebugf("Slide not found: %s", stateValue.c_str());
} else if (stateName.equals(kBackendStateName)) {
for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) {
if (stateValue.equals(kBackendTypeStrings[i])) {
if (fBackendType != i) {
fBackendType = (sk_app::Window::BackendType)i;
fWindow->detach();
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
}
break;
}
@@ -1420,16 +2441,6 @@
break;
}
}
- } else if (stateName.equals(kInstancedRenderingStateName)) {
- DisplayParams params = fWindow->getRequestedDisplayParams();
- bool value = !strcmp(stateValue.c_str(), kON);
- if (params.fGrContextOptions.fEnableInstancedRendering != value) {
- params.fGrContextOptions.fEnableInstancedRendering = value;
- fWindow->setRequestedDisplayParams(params);
- fWindow->inval();
- this->updateTitle();
- this->updateUIState();
- }
} else if (stateName.equals(kSoftkeyStateName)) {
if (!stateValue.equals(kSoftkeyHint)) {
fCommands.onSoftkey(stateValue);
@@ -1444,15 +2455,15 @@
}
}
-bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
+bool Viewer::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {
return fCommands.onKey(key, state, modifiers);
}
-bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
+bool Viewer::onChar(SkUnichar c, skui::ModifierKey modifiers) {
if (fSlides[fCurrentSlide]->onChar(c)) {
fWindow->inval();
return true;
+ } else {
+ return fCommands.onChar(c, modifiers);
}
-
- return fCommands.onChar(c, modifiers);
}
diff --git a/src/third_party/skia/tools/viewer/Viewer.h b/src/third_party/skia/tools/viewer/Viewer.h
index 1b68007..0549187 100644
--- a/src/third_party/skia/tools/viewer/Viewer.h
+++ b/src/third_party/skia/tools/viewer/Viewer.h
@@ -8,86 +8,155 @@
#ifndef Viewer_DEFINED
#define Viewer_DEFINED
-#include "sk_app/Application.h"
-#include "sk_app/CommandSet.h"
-#include "sk_app/Window.h"
-#include "gm.h"
-#include "SkAnimTimer.h"
-#include "SkTouchGesture.h"
-#include "Slide.h"
+#include "gm/gm.h"
+#include "include/core/SkExecutor.h"
+#include "include/core/SkFont.h"
+#include "src/core/SkScan.h"
+#include "src/sksl/SkSLString.h"
+#include "src/sksl/ir/SkSLProgram.h"
+#include "tools/gpu/MemoryCache.h"
+#include "tools/sk_app/Application.h"
+#include "tools/sk_app/CommandSet.h"
+#include "tools/sk_app/Window.h"
+#include "tools/viewer/AnimTimer.h"
+#include "tools/viewer/ImGuiLayer.h"
+#include "tools/viewer/Slide.h"
+#include "tools/viewer/StatsLayer.h"
+#include "tools/viewer/TouchGesture.h"
class SkCanvas;
+class SkData;
-class Viewer : public sk_app::Application {
+class Viewer : public sk_app::Application, sk_app::Window::Layer {
public:
Viewer(int argc, char** argv, void* platformData);
~Viewer() override;
- void onBackendCreated();
- void onPaint(SkCanvas* canvas);
void onIdle() override;
- bool onTouch(intptr_t owner, sk_app::Window::InputState state, float x, float y);
- bool onMouse(float x, float y, sk_app::Window::InputState state, uint32_t modifiers);
- void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
- bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
- bool onChar(SkUnichar c, uint32_t modifiers);
+ void onBackendCreated() override;
+ void onPaint(SkSurface*) override;
+ void onResize(int width, int height) override;
+ bool onTouch(intptr_t owner, skui::InputState state, float x, float y) override;
+ bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override;
+ void onUIStateChanged(const SkString& stateName, const SkString& stateValue) override;
+ bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override;
+ bool onChar(SkUnichar c, skui::ModifierKey modifiers) override;
+ bool onPinch(skui::InputState state, float scale, float x, float y) override;
+ bool onFling(skui::InputState state) override;
+
+ struct SkFontFields {
+ bool fTypeface = false;
+ bool fSize = false;
+ SkScalar fSizeRange[2] = { 0, 20 };
+ bool fScaleX = false;
+ bool fSkewX = false;
+ bool fHinting = false;
+ bool fEdging = false;
+ bool fSubpixel = false;
+ bool fForceAutoHinting = false;
+ bool fEmbeddedBitmaps = false;
+ bool fLinearMetrics = false;
+ bool fEmbolden = false;
+ bool fBaselineSnap = false;
+ };
+ struct SkPaintFields {
+ bool fPathEffect = false;
+ bool fShader = false;
+ bool fMaskFilter = false;
+ bool fColorFilter = false;
+ bool fDrawLooper = false;
+ bool fImageFilter = false;
+
+ bool fColor = false;
+ bool fWidth = false;
+ bool fMiterLimit = false;
+ bool fBlendMode = false;
+
+ bool fAntiAlias = false;
+ bool fDither = false;
+ enum class AntiAliasState {
+ Alias,
+ Normal,
+ AnalyticAAEnabled,
+ AnalyticAAForced,
+ } fAntiAliasState = AntiAliasState::Alias;
+ const bool fOriginalSkUseAnalyticAA = gSkUseAnalyticAA;
+ const bool fOriginalSkForceAnalyticAA = gSkForceAnalyticAA;
+
+ bool fCapType = false;
+ bool fJoinType = false;
+ bool fStyle = false;
+ bool fFilterQuality = false;
+ };
private:
enum class ColorMode {
- kLegacy, // N32, no color management
- kColorManagedSRGB8888_NonLinearBlending, // N32, sRGB transfer function, nonlinear blending
- kColorManagedSRGB8888, // N32, sRGB transfer function, linear blending
- kColorManagedLinearF16, // F16, linear transfer function, linear blending
+ kLegacy, // 8888, no color management
+ kColorManaged8888, // 8888 with color management
+ kColorManagedF16, // F16 with color management
+ kColorManagedF16Norm, // Normalized F16 with color management
};
void initSlides();
void updateTitle();
void setBackend(sk_app::Window::BackendType);
void setColorMode(ColorMode);
- void setStartupSlide();
- void setupCurrentSlide(int previousSlide);
- void listNames();
+ int startupSlide() const;
+ void setCurrentSlide(int);
+ void setupCurrentSlide();
+ void listNames() const;
void updateUIState();
- void drawSlide(SkCanvas* canvs);
- void drawStats(SkCanvas* canvas);
- void drawImGui(SkCanvas* canvas);
+ void drawSlide(SkSurface* surface);
+ void drawImGui();
void changeZoomLevel(float delta);
+ void preTouchMatrixChanged();
+ SkMatrix computePreTouchMatrix();
+ SkMatrix computePerspectiveMatrix();
SkMatrix computeMatrix();
+ SkPoint mapEvent(float x, float y);
sk_app::Window* fWindow;
- static const int kMeasurementCount = 64; // should be power of 2 for fast mod
- double fPaintTimes[kMeasurementCount];
- double fFlushTimes[kMeasurementCount];
- double fAnimateTimes[kMeasurementCount];
- int fCurrentMeasurement;
+ StatsLayer fStatsLayer;
+ StatsLayer::Timer fPaintTimer;
+ StatsLayer::Timer fFlushTimer;
+ StatsLayer::Timer fAnimateTimer;
- SkAnimTimer fAnimTimer;
+ AnimTimer fAnimTimer;
SkTArray<sk_sp<Slide>> fSlides;
int fCurrentSlide;
- bool fDisplayStats;
bool fRefresh; // whether to continuously refresh for measuring render time
- SkPaint fImGuiFontPaint;
+ bool fSaveToSKP;
+ bool fShowSlideDimensions;
+
+ ImGuiLayer fImGuiLayer;
SkPaint fImGuiGamutPaint;
bool fShowImGuiDebugWindow;
+ bool fShowSlidePicker;
bool fShowImGuiTestWindow;
bool fShowZoomWindow;
+ bool fZoomWindowFixed;
+ SkPoint fZoomWindowLocation;
sk_sp<SkImage> fLastImage;
+ bool fZoomUI;
sk_app::Window::BackendType fBackendType;
// Color properties for slide rendering
ColorMode fColorMode;
SkColorSpacePrimaries fColorSpacePrimaries;
+ skcms_TransferFunction fColorSpaceTransferFn;
// transform data
SkScalar fZoomLevel;
+ SkScalar fRotation;
+ SkVector fOffset;
sk_app::CommandSet fCommands;
@@ -97,16 +166,45 @@
kMouse,
};
- SkTouchGesture fGesture;
+ TouchGesture fGesture;
GestureDevice fGestureDevice;
// identity unless the window initially scales the content to fit the screen.
SkMatrix fDefaultMatrix;
+ bool fTiled;
+ bool fDrawTileBoundaries;
+ SkSize fTileScale;
+
+ enum PerspectiveMode {
+ kPerspective_Off,
+ kPerspective_Real,
+ kPerspective_Fake,
+ };
+ PerspectiveMode fPerspectiveMode;
+ SkPoint fPerspectivePoints[4];
+
SkTArray<std::function<void(void)>> fDeferredActions;
- Json::Value fAllSlideNames; // cache all slide names for fast updateUIState
-};
+ SkPaint fPaint;
+ SkPaintFields fPaintOverrides;
+ SkFont fFont;
+ SkFontFields fFontOverrides;
+ bool fPixelGeometryOverrides = false;
+ struct CachedGLSL {
+ bool fHovered = false;
+
+ sk_sp<const SkData> fKey;
+ SkString fKeyString;
+
+ SkFourByteTag fShaderType;
+ SkSL::String fShader[kGrShaderTypeCount];
+ SkSL::Program::Inputs fInputs[kGrShaderTypeCount];
+ };
+
+ sk_gpu_test::MemoryCache fPersistentCache;
+ SkTArray<CachedGLSL> fCachedGLSL;
+};
#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp b/src/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp
deleted file mode 100644
index 2f0d5dc..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrBackendSurface.h"
-#include "GrContext.h"
-#include "GLWindowContext.h"
-
-#include "gl/GrGLDefines.h"
-#include "gl/GrGLUtil.h"
-
-#include "SkCanvas.h"
-#include "SkImage_Base.h"
-#include "SkMathPriv.h"
-#include "SkSurface.h"
-
-namespace sk_app {
-
-GLWindowContext::GLWindowContext(const DisplayParams& params)
- : WindowContext(params)
- , fBackendContext(nullptr)
- , fSurface(nullptr) {
- fDisplayParams.fMSAASampleCount = fDisplayParams.fMSAASampleCount ?
- GrNextPow2(fDisplayParams.fMSAASampleCount) :
- 0;
-}
-
-void GLWindowContext::initializeContext() {
- this->onInitializeContext();
- SkASSERT(nullptr == fContext);
-
- fBackendContext.reset(GrGLCreateNativeInterface());
- fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fBackendContext.get(),
- fDisplayParams.fGrContextOptions);
- if (!fContext && fDisplayParams.fMSAASampleCount) {
- fDisplayParams.fMSAASampleCount /= 2;
- this->initializeContext();
- return;
- }
-
- if (fContext) {
- // We may not have real sRGB support (ANGLE, in particular), so check for
- // that, and fall back to L32:
- fPixelConfig = fContext->caps()->srgbSupport() && fDisplayParams.fColorSpace
- ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
- } else {
- fPixelConfig = kUnknown_GrPixelConfig;
- }
-}
-
-void GLWindowContext::destroyContext() {
- fSurface.reset(nullptr);
-
- if (fContext) {
- // in case we have outstanding refs to this guy (lua?)
- fContext->abandonContext();
- fContext->unref();
- fContext = nullptr;
- }
-
- fBackendContext.reset(nullptr);
-
- this->onDestroyContext();
-}
-
-sk_sp<SkSurface> GLWindowContext::getBackbufferSurface() {
- if (nullptr == fSurface) {
- if (fContext) {
- GrGLFramebufferInfo fbInfo;
- GrGLint buffer;
- GR_GL_CALL(fBackendContext.get(), GetIntegerv(GR_GL_FRAMEBUFFER_BINDING,
- &buffer));
- fbInfo.fFBOID = buffer;
-
- GrBackendRenderTarget backendRT(fWidth,
- fHeight,
- fSampleCount,
- fStencilBits,
- fPixelConfig,
- fbInfo);
-
- fSurface = SkSurface::MakeFromBackendRenderTarget(fContext, backendRT,
- kBottomLeft_GrSurfaceOrigin,
- fDisplayParams.fColorSpace,
- &fSurfaceProps);
- }
- }
-
- return fSurface;
-}
-
-void GLWindowContext::swapBuffers() {
- this->onSwapBuffers();
-}
-
-void GLWindowContext::resize(int w, int h) {
- this->destroyContext();
- this->initializeContext();
-}
-
-void GLWindowContext::setDisplayParams(const DisplayParams& params) {
- this->destroyContext();
- fDisplayParams = params;
- this->initializeContext();
-}
-
-} //namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp b/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp
deleted file mode 100644
index 261206c..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrBackendSurface.h"
-#include "GrContext.h"
-#include "SkAutoMalloc.h"
-#include "SkSurface.h"
-#include "VulkanWindowContext.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkMemory.h"
-#include "vk/GrVkUtil.h"
-#include "vk/GrVkTypes.h"
-
-#ifdef VK_USE_PLATFORM_WIN32_KHR
-// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
-#undef CreateSemaphore
-#endif
-
-#define GET_PROC(F) f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
-#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
-
-namespace sk_app {
-
-VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
- CreateVkSurfaceFn createVkSurface,
- CanPresentFn canPresent)
- : WindowContext(params)
- , fCreateVkSurfaceFn(createVkSurface)
- , fCanPresentFn(canPresent)
- , fSurface(VK_NULL_HANDLE)
- , fSwapchain(VK_NULL_HANDLE)
- , fImages(nullptr)
- , fImageLayouts(nullptr)
- , fSurfaces(nullptr)
- , fCommandPool(VK_NULL_HANDLE)
- , fBackbuffers(nullptr) {
- this->initializeContext();
-}
-
-void VulkanWindowContext::initializeContext() {
- // any config code here (particularly for msaa)?
- fBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
- &fPresentQueueIndex, fCanPresentFn));
-
- if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
- !(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) {
- fBackendContext.reset(nullptr);
- return;
- }
-
- VkInstance instance = fBackendContext->fInstance;
- VkDevice device = fBackendContext->fDevice;
- GET_PROC(DestroySurfaceKHR);
- GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
- GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
- GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
- GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
- GET_DEV_PROC(CreateSwapchainKHR);
- GET_DEV_PROC(DestroySwapchainKHR);
- GET_DEV_PROC(GetSwapchainImagesKHR);
- GET_DEV_PROC(AcquireNextImageKHR);
- GET_DEV_PROC(QueuePresentKHR);
-
- fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get(),
- fDisplayParams.fGrContextOptions);
-
- fSurface = fCreateVkSurfaceFn(instance);
- if (VK_NULL_HANDLE == fSurface) {
- fBackendContext.reset(nullptr);
- return;
- }
-
- VkBool32 supported;
- VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fBackendContext->fPhysicalDevice,
- fPresentQueueIndex, fSurface,
- &supported);
- if (VK_SUCCESS != res) {
- this->destroyContext();
- return;
- }
-
- if (!this->createSwapchain(-1, -1, fDisplayParams)) {
- this->destroyContext();
- return;
- }
-
- // create presentQueue
- vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
-}
-
-bool VulkanWindowContext::createSwapchain(int width, int height,
- const DisplayParams& params) {
- // check for capabilities
- VkSurfaceCapabilitiesKHR caps;
- VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fBackendContext->fPhysicalDevice,
- fSurface, &caps);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t surfaceFormatCount;
- res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
- &surfaceFormatCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
- VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
- res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
- &surfaceFormatCount, surfaceFormats);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t presentModeCount;
- res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
- &presentModeCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
- VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
- res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
- &presentModeCount, presentModes);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- VkExtent2D extent = caps.currentExtent;
- // use the hints
- if (extent.width == (uint32_t)-1) {
- extent.width = width;
- extent.height = height;
- }
-
- // clamp width; to protect us from broken hints
- if (extent.width < caps.minImageExtent.width) {
- extent.width = caps.minImageExtent.width;
- } else if (extent.width > caps.maxImageExtent.width) {
- extent.width = caps.maxImageExtent.width;
- }
- // clamp height
- if (extent.height < caps.minImageExtent.height) {
- extent.height = caps.minImageExtent.height;
- } else if (extent.height > caps.maxImageExtent.height) {
- extent.height = caps.maxImageExtent.height;
- }
-
- fWidth = (int)extent.width;
- fHeight = (int)extent.height;
-
- uint32_t imageCount = caps.minImageCount + 2;
- if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
- // Application must settle for fewer images than desired:
- imageCount = caps.maxImageCount;
- }
-
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
- SkASSERT(caps.supportedTransforms & caps.currentTransform);
- SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
- VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-
- // Pick our surface format. For now, just make sure it matches our sRGB request:
- VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
- VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- auto srgbColorSpace = SkColorSpace::MakeSRGB();
- bool wantSRGB = srgbColorSpace == params.fColorSpace;
- for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
- GrPixelConfig config = GrVkFormatToPixelConfig(surfaceFormats[i].format);
- if (kUnknown_GrPixelConfig != config &&
- GrPixelConfigIsSRGB(config) == wantSRGB) {
- surfaceFormat = surfaceFormats[i].format;
- colorSpace = surfaceFormats[i].colorSpace;
- break;
- }
- }
- fDisplayParams = params;
- fSampleCount = params.fMSAASampleCount;
- fStencilBits = 8;
-
- if (VK_FORMAT_UNDEFINED == surfaceFormat) {
- return false;
- }
-
- // If mailbox mode is available, use it, as it is the lowest-latency non-
- // tearing mode. If not, fall back to FIFO which is always available.
- VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
- for (uint32_t i = 0; i < presentModeCount; ++i) {
- // use mailbox
- if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
- mode = presentModes[i];
- break;
- }
- }
-
- VkSwapchainCreateInfoKHR swapchainCreateInfo;
- memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
- swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainCreateInfo.surface = fSurface;
- swapchainCreateInfo.minImageCount = imageCount;
- swapchainCreateInfo.imageFormat = surfaceFormat;
- swapchainCreateInfo.imageColorSpace = colorSpace;
- swapchainCreateInfo.imageExtent = extent;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage = usageFlags;
-
- uint32_t queueFamilies[] = { fBackendContext->fGraphicsQueueIndex, fPresentQueueIndex };
- if (fBackendContext->fGraphicsQueueIndex != fPresentQueueIndex) {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchainCreateInfo.queueFamilyIndexCount = 2;
- swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
- } else {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainCreateInfo.queueFamilyIndexCount = 0;
- swapchainCreateInfo.pQueueFamilyIndices = nullptr;
- }
-
- swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- swapchainCreateInfo.compositeAlpha = composite_alpha;
- swapchainCreateInfo.presentMode = mode;
- swapchainCreateInfo.clipped = true;
- swapchainCreateInfo.oldSwapchain = fSwapchain;
-
- res = fCreateSwapchainKHR(fBackendContext->fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- // destroy the old swapchain
- if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
- GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
-
- this->destroyBuffers();
-
- fDestroySwapchainKHR(fBackendContext->fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
- }
-
- this->createBuffers(swapchainCreateInfo.imageFormat);
-
- return true;
-}
-
-void VulkanWindowContext::createBuffers(VkFormat format) {
- fPixelConfig = GrVkFormatToPixelConfig(format);
- SkASSERT(kUnknown_GrPixelConfig != fPixelConfig);
-
- fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, nullptr);
- SkASSERT(fImageCount);
- fImages = new VkImage[fImageCount];
- fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, fImages);
-
- // set up initial image layouts and create surfaces
- fImageLayouts = new VkImageLayout[fImageCount];
- fSurfaces = new sk_sp<SkSurface>[fImageCount];
- for (uint32_t i = 0; i < fImageCount; ++i) {
- fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
-
- GrVkImageInfo info;
- info.fImage = fImages[i];
- info.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
- info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info.fFormat = format;
- info.fLevelCount = 1;
-
- GrBackendTexture backendTex(fWidth, fHeight, info);
-
- fSurfaces[i] = SkSurface::MakeFromBackendTextureAsRenderTarget(fContext, backendTex,
- kTopLeft_GrSurfaceOrigin,
- fSampleCount,
- fDisplayParams.fColorSpace,
- &fSurfaceProps);
- }
-
- // create the command pool for the command buffers
- if (VK_NULL_HANDLE == fCommandPool) {
- VkCommandPoolCreateInfo commandPoolInfo;
- memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo));
- commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- // this needs to be on the render queue
- commandPoolInfo.queueFamilyIndex = fBackendContext->fGraphicsQueueIndex;
- commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateCommandPool(fBackendContext->fDevice, &commandPoolInfo,
- nullptr, &fCommandPool));
- }
-
- // set up the backbuffers
- VkSemaphoreCreateInfo semaphoreInfo;
- memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = nullptr;
- semaphoreInfo.flags = 0;
- VkCommandBufferAllocateInfo commandBuffersInfo;
- memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
- commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandBuffersInfo.pNext = nullptr;
- commandBuffersInfo.commandPool = fCommandPool;
- commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandBuffersInfo.commandBufferCount = 2;
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.pNext = nullptr;
- fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- // we create one additional backbuffer structure here, because we want to
- // give the command buffers they contain a chance to finish before we cycle back
- fBackbuffers = new BackbufferInfo[fImageCount + 1];
- for (uint32_t i = 0; i < fImageCount + 1; ++i) {
- fBackbuffers[i].fImageIndex = -1;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
- nullptr, &fBackbuffers[i].fAcquireSemaphore));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
- nullptr, &fBackbuffers[i].fRenderSemaphore));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- AllocateCommandBuffers(fBackendContext->fDevice, &commandBuffersInfo,
- fBackbuffers[i].fTransitionCmdBuffers));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
- &fBackbuffers[i].fUsageFences[0]));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
- &fBackbuffers[i].fUsageFences[1]));
- }
- fCurrentBackbufferIndex = fImageCount;
-}
-
-void VulkanWindowContext::destroyBuffers() {
-
- if (fBackbuffers) {
- for (uint32_t i = 0; i < fImageCount + 1; ++i) {
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- WaitForFences(fBackendContext->fDevice, 2,
- fBackbuffers[i].fUsageFences,
- true, UINT64_MAX));
- fBackbuffers[i].fImageIndex = -1;
- GR_VK_CALL(fBackendContext->fInterface,
- DestroySemaphore(fBackendContext->fDevice,
- fBackbuffers[i].fAcquireSemaphore,
- nullptr));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroySemaphore(fBackendContext->fDevice,
- fBackbuffers[i].fRenderSemaphore,
- nullptr));
- GR_VK_CALL(fBackendContext->fInterface,
- FreeCommandBuffers(fBackendContext->fDevice, fCommandPool, 2,
- fBackbuffers[i].fTransitionCmdBuffers));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[0], 0));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[1], 0));
- }
- }
-
- delete[] fBackbuffers;
- fBackbuffers = nullptr;
-
- // Does this actually free the surfaces?
- delete[] fSurfaces;
- fSurfaces = nullptr;
- delete[] fImageLayouts;
- fImageLayouts = nullptr;
- delete[] fImages;
- fImages = nullptr;
-}
-
-VulkanWindowContext::~VulkanWindowContext() {
- this->destroyContext();
-}
-
-void VulkanWindowContext::destroyContext() {
- if (!fBackendContext.get()) {
- return;
- }
-
- GR_VK_CALL(fBackendContext->fInterface, QueueWaitIdle(fPresentQueue));
- GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
-
- this->destroyBuffers();
-
- if (VK_NULL_HANDLE != fCommandPool) {
- GR_VK_CALL(fBackendContext->fInterface, DestroyCommandPool(fBackendContext->fDevice,
- fCommandPool, nullptr));
- fCommandPool = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != fSwapchain) {
- fDestroySwapchainKHR(fBackendContext->fDevice, fSwapchain, nullptr);
- fSwapchain = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != fSurface) {
- fDestroySurfaceKHR(fBackendContext->fInstance, fSurface, nullptr);
- fSurface = VK_NULL_HANDLE;
- }
-
- fContext->unref();
-
- fBackendContext.reset(nullptr);
-}
-
-VulkanWindowContext::BackbufferInfo* VulkanWindowContext::getAvailableBackbuffer() {
- SkASSERT(fBackbuffers);
-
- ++fCurrentBackbufferIndex;
- if (fCurrentBackbufferIndex > fImageCount) {
- fCurrentBackbufferIndex = 0;
- }
-
- BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- WaitForFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences,
- true, UINT64_MAX));
- return backbuffer;
-}
-
-sk_sp<SkSurface> VulkanWindowContext::getBackbufferSurface() {
- BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
- SkASSERT(backbuffer);
-
- // reset the fence
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences));
- // semaphores should be in unsignaled state
-
- // acquire the image
- VkResult res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
- backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->fImageIndex);
- if (VK_ERROR_SURFACE_LOST_KHR == res) {
- // need to figure out how to create a new vkSurface without the platformData*
- // maybe use attach somehow? but need a Window
- return nullptr;
- }
- if (VK_ERROR_OUT_OF_DATE_KHR == res) {
- // tear swapchain down and try again
- if (!this->createSwapchain(-1, -1, fDisplayParams)) {
- return nullptr;
- }
- backbuffer = this->getAvailableBackbuffer();
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences));
-
- // acquire the image
- res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
- backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->fImageIndex);
-
- if (VK_SUCCESS != res) {
- return nullptr;
- }
- }
-
- // set up layout transfer from initial to color attachment
- VkImageLayout layout = fImageLayouts[backbuffer->fImageIndex];
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
- VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- 0 : VK_ACCESS_MEMORY_READ_BIT;
- VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- fPresentQueueIndex, // srcQueueFamilyIndex
- fBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
- fImages[backbuffer->fImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
- };
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[0], 0));
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[0], &info));
-
- GR_VK_CALL(fBackendContext->fInterface,
- CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[0],
- srcStageMask, dstStageMask, 0,
- 0, nullptr,
- 0, nullptr,
- 1, &imageMemoryBarrier));
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- EndCommandBuffer(backbuffer->fTransitionCmdBuffers[0]));
-
- VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 1;
- submitInfo.pWaitSemaphores = &backbuffer->fAcquireSemaphore;
- submitInfo.pWaitDstStageMask = &waitDstStageFlags;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[0];
- submitInfo.signalSemaphoreCount = 0;
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
- backbuffer->fUsageFences[0]));
-
- GrVkImageInfo* imageInfo;
- SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
- surface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
- imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- return sk_ref_sp(surface);
-}
-
-void VulkanWindowContext::swapBuffers() {
-
- BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
- GrVkImageInfo* imageInfo;
- SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
- surface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
- // Check to make sure we never change the actually wrapped image
- SkASSERT(imageInfo->fImage == fImages[backbuffer->fImageIndex]);
-
- VkImageLayout layout = imageInfo->fImageLayout;
- VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
- VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- fBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
- fPresentQueueIndex, // dstQueueFamilyIndex
- fImages[backbuffer->fImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
- };
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[1], 0));
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[1], &info));
- GR_VK_CALL(fBackendContext->fInterface,
- CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[1],
- srcStageMask, dstStageMask, 0,
- 0, nullptr,
- 0, nullptr,
- 1, &imageMemoryBarrier));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- EndCommandBuffer(backbuffer->fTransitionCmdBuffers[1]));
-
- fImageLayouts[backbuffer->fImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitDstStageMask = 0;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[1];
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &backbuffer->fRenderSemaphore;
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
- backbuffer->fUsageFences[1]));
-
- // Submit present operation to present queue
- const VkPresentInfoKHR presentInfo =
- {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->fRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &fSwapchain, // pSwapchains
- &backbuffer->fImageIndex, // pImageIndices
- NULL // pResults
- };
-
- fQueuePresentKHR(fPresentQueue, &presentInfo);
-}
-
-} //namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h b/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h
deleted file mode 100644
index 81e5f3d..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h
+++ /dev/null
@@ -1,117 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef VulkanWindowContext_DEFINED
-#define VulkanWindowContext_DEFINED
-
-#include "SkTypes.h" // required to pull in any SkUserConfig defines
-
-#ifdef SK_VULKAN
-
-#include "vk/GrVkBackendContext.h"
-#include "WindowContext.h"
-
-class GrRenderTarget;
-
-namespace sk_app {
-
-class VulkanWindowContext : public WindowContext {
-public:
- ~VulkanWindowContext() override;
-
- sk_sp<SkSurface> getBackbufferSurface() override;
- void swapBuffers() override;
-
- bool isValid() override { return SkToBool(fBackendContext.get()); }
-
- void resize(int w, int h) override {
- this->createSwapchain(w, h, fDisplayParams);
- }
-
- void setDisplayParams(const DisplayParams& params) override {
- this->destroyContext();
- fDisplayParams = params;
- this->initializeContext();
- }
-
- GrBackendContext getBackendContext() override {
- return (GrBackendContext) fBackendContext.get();
- }
-
- /** Platform specific function that creates a VkSurfaceKHR for a window */
- using CreateVkSurfaceFn = std::function<VkSurfaceKHR(VkInstance)>;
- /** Platform specific function that determines whether presentation will succeed. */
- using CanPresentFn = GrVkBackendContext::CanPresentFn;
-
- VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn);
-
-private:
- void initializeContext();
- void destroyContext();
-
- struct BackbufferInfo {
- uint32_t fImageIndex; // image this is associated with
- VkSemaphore fAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore fRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer fTransitionCmdBuffers[2]; // to transition layout between present and render
- VkFence fUsageFences[2]; // used to ensure this data is no longer used on GPU
- };
-
- BackbufferInfo* getAvailableBackbuffer();
- bool createSwapchain(int width, int height, const DisplayParams& params);
- void createBuffers(VkFormat format);
- void destroyBuffers();
-
- sk_sp<const GrVkBackendContext> fBackendContext;
-
- // simple wrapper class that exists only to initialize a pointer to NULL
- template <typename FNPTR_TYPE> class VkPtr {
- public:
- VkPtr() : fPtr(NULL) {}
- VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
- operator FNPTR_TYPE() const { return fPtr; }
- private:
- FNPTR_TYPE fPtr;
- };
-
- // Create functions
- CreateVkSurfaceFn fCreateVkSurfaceFn;
- CanPresentFn fCanPresentFn;
-
- // WSI interface functions
- VkPtr<PFN_vkDestroySurfaceKHR> fDestroySurfaceKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceSupportKHR> fGetPhysicalDeviceSurfaceSupportKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR> fGetPhysicalDeviceSurfaceCapabilitiesKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR> fGetPhysicalDeviceSurfaceFormatsKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR> fGetPhysicalDeviceSurfacePresentModesKHR;
-
- VkPtr<PFN_vkCreateSwapchainKHR> fCreateSwapchainKHR;
- VkPtr<PFN_vkDestroySwapchainKHR> fDestroySwapchainKHR;
- VkPtr<PFN_vkGetSwapchainImagesKHR> fGetSwapchainImagesKHR;
- VkPtr<PFN_vkAcquireNextImageKHR> fAcquireNextImageKHR;
- VkPtr<PFN_vkQueuePresentKHR> fQueuePresentKHR;
- VkPtr<PFN_vkCreateSharedSwapchainsKHR> fCreateSharedSwapchainsKHR;
-
- VkSurfaceKHR fSurface;
- VkSwapchainKHR fSwapchain;
- uint32_t fPresentQueueIndex;
- VkQueue fPresentQueue;
-
- uint32_t fImageCount;
- VkImage* fImages; // images in the swapchain
- VkImageLayout* fImageLayouts; // layouts of these images when not color attachment
- sk_sp<SkSurface>* fSurfaces; // surfaces client renders to (may not be based on rts)
- VkCommandPool fCommandPool;
- BackbufferInfo* fBackbuffers;
- uint32_t fCurrentBackbufferIndex;
-};
-
-} // namespace sk_app
-
-#endif // SK_VULKAN
-
-#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/Window.cpp b/src/third_party/skia/tools/viewer/sk_app/Window.cpp
deleted file mode 100644
index 9acea3f..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/Window.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#include "Window.h"
-
-#include "SkSurface.h"
-#include "SkCanvas.h"
-#include "WindowContext.h"
-
-namespace sk_app {
-
-static void default_backend_created_func(void* userData) {}
-
-static bool default_char_func(SkUnichar c, uint32_t modifiers, void* userData) {
- return false;
-}
-
-static bool default_key_func(Window::Key key, Window::InputState state, uint32_t modifiers,
- void* userData) {
- return false;
-}
-
-static bool default_mouse_func(int x, int y, Window::InputState state, uint32_t modifiers,
- void* userData) {
- return false;
-}
-
-static bool default_mouse_wheel_func(float delta, uint32_t modifiers, void* userData) {
- return false;
-}
-
-static bool default_touch_func(intptr_t owner, Window::InputState state, float x, float y,
- void* userData) {
- return false;
-}
-
-static void default_ui_state_changed_func(
- const SkString& stateName, const SkString& stateValue, void* userData) {}
-
-static void default_paint_func(SkCanvas*, void* userData) {}
-
-Window::Window() : fBackendCreatedFunc(default_backend_created_func)
- , fCharFunc(default_char_func)
- , fKeyFunc(default_key_func)
- , fMouseFunc(default_mouse_func)
- , fMouseWheelFunc(default_mouse_wheel_func)
- , fTouchFunc(default_touch_func)
- , fUIStateChangedFunc(default_ui_state_changed_func)
- , fPaintFunc(default_paint_func) {
-}
-
-void Window::detach() {
- delete fWindowContext;
- fWindowContext = nullptr;
-}
-
-void Window::onBackendCreated() {
- fBackendCreatedFunc(fBackendCreatedUserData);
-}
-
-bool Window::onChar(SkUnichar c, uint32_t modifiers) {
- return fCharFunc(c, modifiers, fCharUserData);
-}
-
-bool Window::onKey(Key key, InputState state, uint32_t modifiers) {
- return fKeyFunc(key, state, modifiers, fKeyUserData);
-}
-
-bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
- return fMouseFunc(x, y, state, modifiers, fMouseUserData);
-}
-
-bool Window::onMouseWheel(float delta, uint32_t modifiers) {
- return fMouseWheelFunc(delta, modifiers, fMouseWheelUserData);
-}
-
-bool Window::onTouch(intptr_t owner, InputState state, float x, float y) {
- return fTouchFunc(owner, state, x, y, fTouchUserData);
-}
-
-void Window::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
- return fUIStateChangedFunc(stateName, stateValue, fUIStateChangedUserData);
-}
-
-void Window::onPaint() {
- if (!fWindowContext) {
- return;
- }
- markInvalProcessed();
- sk_sp<SkSurface> backbuffer = fWindowContext->getBackbufferSurface();
- if (backbuffer) {
- // draw into the canvas of this surface
- SkCanvas* canvas = backbuffer->getCanvas();
-
- fPaintFunc(canvas, fPaintUserData);
-
- canvas->flush();
-
- fWindowContext->swapBuffers();
- } else {
- printf("no backbuffer!?\n");
- // try recreating testcontext
- }
-}
-
-void Window::onResize(int w, int h) {
- if (!fWindowContext) {
- return;
- }
- fWindowContext->resize(w, h);
-}
-
-int Window::width() {
- if (!fWindowContext) {
- return 0;
- }
- return fWindowContext->width();
-}
-
-int Window::height() {
- if (!fWindowContext) {
- return 0;
- }
- return fWindowContext->height();
-}
-
-void Window::setRequestedDisplayParams(const DisplayParams& params, bool /* allowReattach */) {
- fRequestedDisplayParams = params;
- if (fWindowContext) {
- fWindowContext->setDisplayParams(fRequestedDisplayParams);
- }
-}
-
-int Window::sampleCount() const {
- if (!fWindowContext) {
- return -1;
- }
- return fWindowContext->sampleCount();
-}
-
-int Window::stencilBits() const {
- if (!fWindowContext) {
- return -1;
- }
- return fWindowContext->stencilBits();
-}
-
-const GrContext* Window::getGrContext() const {
- if (!fWindowContext) {
- return nullptr;
- }
- return fWindowContext->getGrContext();
-}
-
-void Window::inval() {
- if (!fWindowContext) {
- return;
- }
- if (!fIsContentInvalidated) {
- fIsContentInvalidated = true;
- onInval();
- }
-}
-
-void Window::markInvalProcessed() {
- fIsContentInvalidated = false;
-}
-
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/Window.h b/src/third_party/skia/tools/viewer/sk_app/Window.h
deleted file mode 100644
index 7d0c097..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/Window.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#ifndef Window_DEFINED
-#define Window_DEFINED
-
-#include "DisplayParams.h"
-#include "SkRect.h"
-#include "SkTouchGesture.h"
-#include "SkTypes.h"
-#include "SkJSONCPP.h"
-
-class GrContext;
-class SkCanvas;
-class SkSurface;
-
-namespace sk_app {
-
-class WindowContext;
-
-class Window {
-public:
- static Window* CreateNativeWindow(void* platformData);
-
- virtual ~Window() { this->detach(); }
-
- virtual void setTitle(const char*) = 0;
- virtual void show() = 0;
- virtual void setUIState(const Json::Value& state) {} // do nothing in default
-
- // Shedules an invalidation event for window if one is not currently pending.
- // Make sure that either onPaint or markInvalReceived is called when the client window consumes
- // the the inval event. They unset fIsContentInvalided which allow future onInval.
- void inval();
-
- virtual bool scaleContentToFit() const { return false; }
-
- enum BackendType {
- kNativeGL_BackendType,
-#ifdef SK_VULKAN
- kVulkan_BackendType,
-#endif
- kRaster_BackendType,
-
- kLast_BackendType = kRaster_BackendType
- };
- enum {
- kBackendTypeCount = kLast_BackendType + 1
- };
-
- virtual bool attach(BackendType) = 0;
- void detach();
-
- // input handling
- enum class Key {
- kNONE, //corresponds to android's UNKNOWN
-
- kLeftSoftKey,
- kRightSoftKey,
-
- kHome, //!< the home key - added to match android
- kBack, //!< (CLR)
- kSend, //!< the green (talk) key
- kEnd, //!< the red key
-
- k0,
- k1,
- k2,
- k3,
- k4,
- k5,
- k6,
- k7,
- k8,
- k9,
- kStar, //!< the * key
- kHash, //!< the # key
-
- kUp,
- kDown,
- kLeft,
- kRight,
-
- // Keys needed by ImGui
- kTab,
- kPageUp,
- kPageDown,
- kDelete,
- kEscape,
- kShift,
- kCtrl,
- kOption, // AKA Alt
- kA,
- kC,
- kV,
- kX,
- kY,
- kZ,
-
- kOK, //!< the center key
-
- kVolUp, //!< volume up - match android
- kVolDown, //!< volume down - same
- kPower, //!< power button - same
- kCamera, //!< camera - same
-
- kLast = kCamera
- };
- static const int kKeyCount = static_cast<int>(Key::kLast) + 1;
-
- enum ModifierKeys {
- kShift_ModifierKey = 1 << 0,
- kControl_ModifierKey = 1 << 1,
- kOption_ModifierKey = 1 << 2, // same as ALT
- kCommand_ModifierKey = 1 << 3,
- kFirstPress_ModifierKey = 1 << 4,
- };
-
- enum InputState {
- kDown_InputState,
- kUp_InputState,
- kMove_InputState // only valid for mouse
- };
-
- // return value of 'true' means 'I have handled this event'
- typedef void(*OnBackendCreatedFunc)(void* userData);
- typedef bool(*OnCharFunc)(SkUnichar c, uint32_t modifiers, void* userData);
- typedef bool(*OnKeyFunc)(Key key, InputState state, uint32_t modifiers, void* userData);
- typedef bool(*OnMouseFunc)(int x, int y, InputState state, uint32_t modifiers, void* userData);
- typedef bool(*OnMouseWheelFunc)(float delta, uint32_t modifiers, void* userData);
- typedef bool(*OnTouchFunc)(intptr_t owner, InputState state, float x, float y, void* userData);
- typedef void(*OnUIStateChangedFunc)(
- const SkString& stateName, const SkString& stateValue, void* userData);
- typedef void(*OnPaintFunc)(SkCanvas*, void* userData);
-
- void registerBackendCreatedFunc(OnBackendCreatedFunc func, void* userData) {
- fBackendCreatedFunc = func;
- fBackendCreatedUserData = userData;
- }
-
- void registerCharFunc(OnCharFunc func, void* userData) {
- fCharFunc = func;
- fCharUserData = userData;
- }
-
- void registerKeyFunc(OnKeyFunc func, void* userData) {
- fKeyFunc = func;
- fKeyUserData = userData;
- }
-
- void registerMouseFunc(OnMouseFunc func, void* userData) {
- fMouseFunc = func;
- fMouseUserData = userData;
- }
-
- void registerMouseWheelFunc(OnMouseWheelFunc func, void* userData) {
- fMouseWheelFunc = func;
- fMouseWheelUserData = userData;
- }
-
- void registerPaintFunc(OnPaintFunc func, void* userData) {
- fPaintFunc = func;
- fPaintUserData = userData;
- }
-
- void registerTouchFunc(OnTouchFunc func, void* userData) {
- fTouchFunc = func;
- fTouchUserData = userData;
- }
-
- void registerUIStateChangedFunc(OnUIStateChangedFunc func, void* userData) {
- fUIStateChangedFunc = func;
- fUIStateChangedUserData = userData;
- }
-
- void onBackendCreated();
- bool onChar(SkUnichar c, uint32_t modifiers);
- bool onKey(Key key, InputState state, uint32_t modifiers);
- bool onMouse(int x, int y, InputState state, uint32_t modifiers);
- bool onMouseWheel(float delta, uint32_t modifiers);
- bool onTouch(intptr_t owner, InputState state, float x, float y); // multi-owner = multi-touch
- void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
- void onPaint();
- void onResize(int width, int height);
-
- int width();
- int height();
-
- virtual const DisplayParams& getRequestedDisplayParams() { return fRequestedDisplayParams; }
- virtual void setRequestedDisplayParams(const DisplayParams&, bool allowReattach = true);
-
- // Actual parameters in effect, obtained from the native window.
- int sampleCount() const;
- int stencilBits() const;
-
- // Returns null if there is not a GPU backend or if the backend is not yet created.
- const GrContext* getGrContext() const;
-
-protected:
- Window();
-
- OnBackendCreatedFunc fBackendCreatedFunc;
- void* fBackendCreatedUserData;
- OnCharFunc fCharFunc;
- void* fCharUserData;
- OnKeyFunc fKeyFunc;
- void* fKeyUserData;
- OnMouseFunc fMouseFunc;
- void* fMouseUserData;
- OnMouseWheelFunc fMouseWheelFunc;
- void* fMouseWheelUserData;
- OnTouchFunc fTouchFunc;
- void* fTouchUserData;
- OnUIStateChangedFunc fUIStateChangedFunc;
- void* fUIStateChangedUserData;
- OnPaintFunc fPaintFunc;
- void* fPaintUserData;
- DisplayParams fRequestedDisplayParams;
-
- WindowContext* fWindowContext = nullptr;
-
- virtual void onInval() = 0;
-
- // Uncheck fIsContentInvalided to allow future inval/onInval.
- void markInvalProcessed();
-
- bool fIsContentInvalidated = false; // use this to avoid duplicate invalidate events
-};
-
-} // namespace sk_app
-#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp b/src/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
deleted file mode 100644
index b50e152..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "WindowContextFactory_android.h"
-#include "../VulkanWindowContext.h"
-
-namespace sk_app {
-
-namespace window_context_factory {
-
-WindowContext* NewVulkanForAndroid(ANativeWindow* window, const DisplayParams& params) {
- auto createVkSurface = [window] (VkInstance instance) -> VkSurfaceKHR {
- PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR =
- (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance,
- "vkCreateAndroidSurfaceKHR");
-
- if (!window) {
- return VK_NULL_HANDLE;
- }
- VkSurfaceKHR surface;
-
- VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
- memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.pNext = nullptr;
- surfaceCreateInfo.flags = 0;
- surfaceCreateInfo.window = window;
-
- VkResult res = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
- nullptr, &surface);
- return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
- };
-
- auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
-
- WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-
-} // namespace window_context_factory
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp b/src/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
deleted file mode 100644
index 5bdba64..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../GLWindowContext.h"
-#include "WindowContextFactory_mac.h"
-
-#include "SDL.h"
-
-#include <OpenGL/gl.h>
-
-using sk_app::DisplayParams;
-using sk_app::window_context_factory::MacWindowInfo;
-using sk_app::GLWindowContext;
-
-namespace {
-
-class GLWindowContext_mac : public GLWindowContext {
-public:
- GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
-
- ~GLWindowContext_mac() override;
-
- void onSwapBuffers() override;
-
- void onInitializeContext() override;
- void onDestroyContext() override;
-
-private:
- SDL_Window* fWindow;
- SDL_GLContext fGLContext;
-
- typedef GLWindowContext INHERITED;
-};
-
-GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
- : INHERITED(params)
- , fWindow(info.fWindow)
- , fGLContext(nullptr) {
-
- // any config code here (particularly for msaa)?
-
- this->initializeContext();
-}
-
-GLWindowContext_mac::~GLWindowContext_mac() {
- this->destroyContext();
-}
-
-void GLWindowContext_mac::onInitializeContext() {
- SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return;
- }
-
- if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
- glClearStencil(0);
- glClearColor(0, 0, 0, 0);
- glStencilMask(0xffffffff);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
- SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
- SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
-
- SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
- glViewport(0, 0, fWidth, fHeight);
- } else {
- SkDebugf("MakeCurrent failed: %s\n", SDL_GetError());
- }
-}
-
-void GLWindowContext_mac::onDestroyContext() {
- if (!fWindow || !fGLContext) {
- return;
- }
- SDL_GL_DeleteContext(fGLContext);
- fGLContext = nullptr;
-}
-
-
-void GLWindowContext_mac::onSwapBuffers() {
- if (fWindow && fGLContext) {
- SDL_GL_SwapWindow(fWindow);
- }
-}
-
-} // anonymous namespace
-
-namespace sk_app {
-namespace window_context_factory {
-
-WindowContext* NewGLForMac(const MacWindowInfo& info, const DisplayParams& params) {
- WindowContext* ctx = new GLWindowContext_mac(info, params);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-
-} // namespace window_context_factory
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp b/src/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
deleted file mode 100644
index a88ed13..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../GLWindowContext.h"
-#include "SkCanvas.h"
-#include "SkColorFilter.h"
-#include "sk_tool_utils.h"
-#include "WindowContextFactory_mac.h"
-
-#include "SDL.h"
-
-#include <OpenGL/gl.h>
-
-using sk_app::DisplayParams;
-using sk_app::window_context_factory::MacWindowInfo;
-using sk_app::GLWindowContext;
-
-namespace {
-
-// We use SDL to support Mac windowing mainly for convenience's sake. However, it
-// does not allow us to support a purely raster backend because we have no hooks into
-// the NSWindow's drawRect: method. Hence we use GL to handle the update. Should we
-// want to avoid this, we will probably need to write our own windowing backend.
-
-class RasterWindowContext_mac : public GLWindowContext {
-public:
- RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
-
- ~RasterWindowContext_mac() override;
-
- sk_sp<SkSurface> getBackbufferSurface() override;
-
- void onSwapBuffers() override;
-
- void onInitializeContext() override;
- void onDestroyContext() override;
-
-private:
- SDL_Window* fWindow;
- SDL_GLContext fGLContext;
- sk_sp<SkSurface> fBackbufferSurface;
-
- typedef GLWindowContext INHERITED;
-};
-
-RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
- const DisplayParams& params)
- : INHERITED(params)
- , fWindow(info.fWindow)
- , fGLContext(nullptr) {
-
- // any config code here (particularly for msaa)?
-
- this->initializeContext();
-}
-
-RasterWindowContext_mac::~RasterWindowContext_mac() {
- this->destroyContext();
-}
-
-void RasterWindowContext_mac::onInitializeContext() {
- SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return;
- }
-
- if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
- glClearStencil(0);
- glClearColor(0, 0, 0, 0);
- glStencilMask(0xffffffff);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
- SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
- SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
-
- SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
- glViewport(0, 0, fWidth, fHeight);
- } else {
- SkDebugf("MakeCurrent failed: %s\n", SDL_GetError());
- }
-
- // make the offscreen image
- SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
- kPremul_SkAlphaType, fDisplayParams.fColorSpace);
- fBackbufferSurface = SkSurface::MakeRaster(info);
-}
-
-void RasterWindowContext_mac::onDestroyContext() {
- if (!fWindow || !fGLContext) {
- return;
- }
- fBackbufferSurface.reset(nullptr);
- SDL_GL_DeleteContext(fGLContext);
- fGLContext = nullptr;
-}
-
-sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
-
-void RasterWindowContext_mac::onSwapBuffers() {
- if (fWindow && fGLContext) {
- // We made/have an off-screen surface. Get the contents as an SkImage:
- sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
-
- sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface();
- SkCanvas* gpuCanvas = gpuSurface->getCanvas();
- gpuCanvas->drawImage(snapshot, 0, 0);
- gpuCanvas->flush();
-
- SDL_GL_SwapWindow(fWindow);
- }
-}
-
-} // anonymous namespace
-
-namespace sk_app {
-namespace window_context_factory {
-
-WindowContext* NewRasterForMac(const MacWindowInfo& info, const DisplayParams& params) {
- WindowContext* ctx = new RasterWindowContext_mac(info, params);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-
-} // namespace window_context_factory
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h b/src/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h
deleted file mode 100644
index 3adc68b..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef WindowContextFactory_mac_DEFINED
-#define WindowContextFactory_mac_DEFINED
-
-#include "SDL.h"
-
-namespace sk_app {
-
-class WindowContext;
-struct DisplayParams;
-
-namespace window_context_factory {
-
-struct MacWindowInfo {
- SDL_Window* fWindow;
-};
-
-inline WindowContext* NewVulkanForMac(const MacWindowInfo&, const DisplayParams&) {
- // No Vulkan support on Mac.
- return nullptr;
-}
-
-WindowContext* NewGLForMac(const MacWindowInfo&, const DisplayParams&);
-
-WindowContext* NewRasterForMac(const MacWindowInfo&, const DisplayParams&);
-
-} // namespace window_context_factory
-
-} // namespace sk_app
-
-#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp b/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp
deleted file mode 100644
index dff7ccb..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#include "SkUtils.h"
-#include "Timer.h"
-#include "WindowContextFactory_mac.h"
-#include "Window_mac.h"
-
-namespace sk_app {
-
-SkTDynamicHash<Window_mac, Uint32> Window_mac::gWindowMap;
-
-Window* Window::CreateNativeWindow(void*) {
- Window_mac* window = new Window_mac();
- if (!window->initWindow()) {
- delete window;
- return nullptr;
- }
-
- return window;
-}
-
-bool Window_mac::initWindow() {
- if (fRequestedDisplayParams.fMSAASampleCount != fMSAASampleCount) {
- this->closeWindow();
- }
- // we already have a window
- if (fWindow) {
- return true;
- }
-
- constexpr int initialWidth = 1280;
- constexpr int initialHeight = 960;
-
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-
- SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
-
- if (fRequestedDisplayParams.fMSAASampleCount > 0) {
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount);
- } else {
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
- }
- // TODO: handle other display params
-
- uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
- fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
- initialWidth, initialHeight, windowFlags);
-
- if (!fWindow) {
- return false;
- }
-
- fMSAASampleCount = fRequestedDisplayParams.fMSAASampleCount;
-
- // add to hashtable of windows
- fWindowID = SDL_GetWindowID(fWindow);
- gWindowMap.add(this);
-
- return true;
-}
-
-void Window_mac::closeWindow() {
- if (fWindow) {
- gWindowMap.remove(fWindowID);
- SDL_DestroyWindow(fWindow);
- fWindowID = 0;
- fWindow = nullptr;
- }
-}
-
-static Window::Key get_key(const SDL_Keysym& keysym) {
- static const struct {
- SDL_Keycode fSDLK;
- Window::Key fKey;
- } gPair[] = {
- { SDLK_BACKSPACE, Window::Key::kBack },
- { SDLK_CLEAR, Window::Key::kBack },
- { SDLK_RETURN, Window::Key::kOK },
- { SDLK_UP, Window::Key::kUp },
- { SDLK_DOWN, Window::Key::kDown },
- { SDLK_LEFT, Window::Key::kLeft },
- { SDLK_RIGHT, Window::Key::kRight },
- { SDLK_TAB, Window::Key::kTab },
- { SDLK_PAGEUP, Window::Key::kPageUp },
- { SDLK_PAGEDOWN, Window::Key::kPageDown },
- { SDLK_HOME, Window::Key::kHome },
- { SDLK_END, Window::Key::kEnd },
- { SDLK_DELETE, Window::Key::kDelete },
- { SDLK_ESCAPE, Window::Key::kEscape },
- { SDLK_LSHIFT, Window::Key::kShift },
- { SDLK_RSHIFT, Window::Key::kShift },
- { SDLK_LCTRL, Window::Key::kCtrl },
- { SDLK_RCTRL, Window::Key::kCtrl },
- { SDLK_LALT, Window::Key::kOption },
- { SDLK_LALT, Window::Key::kOption },
- { 'A', Window::Key::kA },
- { 'C', Window::Key::kC },
- { 'V', Window::Key::kV },
- { 'X', Window::Key::kX },
- { 'Y', Window::Key::kY },
- { 'Z', Window::Key::kZ },
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fSDLK == keysym.sym) {
- return gPair[i].fKey;
- }
- }
- return Window::Key::kNONE;
-}
-
-static uint32_t get_modifiers(const SDL_Event& event) {
- static const struct {
- unsigned fSDLMask;
- unsigned fSkMask;
- } gModifiers[] = {
- { KMOD_SHIFT, Window::kShift_ModifierKey },
- { KMOD_CTRL, Window::kControl_ModifierKey },
- { KMOD_ALT, Window::kOption_ModifierKey },
- };
-
- auto modifiers = 0;
-
- switch (event.type) {
- case SDL_KEYDOWN:
- // fall through
- case SDL_KEYUP: {
- for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
- if (event.key.keysym.mod & gModifiers[i].fSDLMask) {
- modifiers |= gModifiers[i].fSkMask;
- }
- }
- if (0 == event.key.repeat) {
- modifiers |= Window::kFirstPress_ModifierKey;
- }
- break;
- }
-
- default: {
- SDL_Keymod mod = SDL_GetModState();
- for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
- if (mod & gModifiers[i].fSDLMask) {
- modifiers |= gModifiers[i].fSkMask;
- }
- }
- break;
- }
- }
- return modifiers;
-}
-
-bool Window_mac::HandleWindowEvent(const SDL_Event& event) {
- Window_mac* win = gWindowMap.find(event.window.windowID);
- if (win && win->handleEvent(event)) {
- return true;
- }
-
- return false;
-}
-
-bool Window_mac::handleEvent(const SDL_Event& event) {
- switch (event.type) {
- case SDL_WINDOWEVENT:
- if (SDL_WINDOWEVENT_EXPOSED == event.window.event) {
- this->onPaint();
- } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) {
- this->onResize(event.window.data1, event.window.data2);
- }
- break;
-
- case SDL_MOUSEBUTTONDOWN:
- if (event.button.button == SDL_BUTTON_LEFT) {
- this->onMouse(event.button.x, event.button.y,
- Window::kDown_InputState, get_modifiers(event));
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- if (event.button.button == SDL_BUTTON_LEFT) {
- this->onMouse(event.button.x, event.button.y,
- Window::kUp_InputState, get_modifiers(event));
- }
- break;
-
- case SDL_MOUSEMOTION:
- this->onMouse(event.motion.x, event.motion.y,
- Window::kMove_InputState, get_modifiers(event));
- break;
-
- case SDL_MOUSEWHEEL:
- this->onMouseWheel(event.wheel.y, get_modifiers(event));
- break;
-
- case SDL_KEYDOWN: {
- Window::Key key = get_key(event.key.keysym);
- if (key != Window::Key::kNONE) {
- if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) {
- if (event.key.keysym.sym == SDLK_ESCAPE) {
- return true;
- }
- }
- }
- } break;
-
- case SDL_KEYUP: {
- Window::Key key = get_key(event.key.keysym);
- if (key != Window::Key::kNONE) {
- (void) this->onKey(key, Window::kUp_InputState,
- get_modifiers(event));
- }
- } break;
-
- case SDL_TEXTINPUT: {
- const char* textIter = &event.text.text[0];
- while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) {
- (void) this->onChar(c, get_modifiers(event));
- }
- } break;
-
- default:
- break;
- }
-
- return false;
-}
-
-void Window_mac::setTitle(const char* title) {
- SDL_SetWindowTitle(fWindow, title);
-}
-
-void Window_mac::show() {
- SDL_ShowWindow(fWindow);
-}
-
-bool Window_mac::attach(BackendType attachType) {
- this->initWindow();
-
- window_context_factory::MacWindowInfo info;
- info.fWindow = fWindow;
- switch (attachType) {
- case kRaster_BackendType:
- fWindowContext = NewRasterForMac(info, fRequestedDisplayParams);
- break;
-
- case kNativeGL_BackendType:
- default:
- fWindowContext = NewGLForMac(info, fRequestedDisplayParams);
- break;
- }
- this->onBackendCreated();
-
- return (SkToBool(fWindowContext));
-}
-
-void Window_mac::onInval() {
- SDL_Event sdlevent;
- sdlevent.type = SDL_WINDOWEVENT;
- sdlevent.window.windowID = fWindowID;
- sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED;
- SDL_PushEvent(&sdlevent);
-}
-
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h b/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h
deleted file mode 100644
index eb28ff4..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#ifndef Window_mac_DEFINED
-#define Window_mac_DEFINED
-
-#include "../Window.h"
-#include "SkChecksum.h"
-#include "SkTDynamicHash.h"
-
-#include "SDL.h"
-
-namespace sk_app {
-
-class Window_mac : public Window {
-public:
- Window_mac()
- : INHERITED()
- , fWindow(nullptr)
- , fWindowID(0)
- , fMSAASampleCount(0) {}
- ~Window_mac() override { this->closeWindow(); }
-
- bool initWindow();
-
- void setTitle(const char*) override;
- void show() override;
-
- bool attach(BackendType) override;
-
- void onInval() override;
-
- static bool HandleWindowEvent(const SDL_Event& event);
-
- static const Uint32& GetKey(const Window_mac& w) {
- return w.fWindowID;
- }
-
- static uint32_t Hash(const Uint32& winID) {
- return winID;
- }
-
-private:
- bool handleEvent(const SDL_Event& event);
-
- void closeWindow();
-
- static SkTDynamicHash<Window_mac, Uint32> gWindowMap;
-
- SDL_Window* fWindow;
- Uint32 fWindowID;
-
- int fMSAASampleCount;
-
- typedef Window INHERITED;
-};
-
-} // namespace sk_app
-
-#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp b/src/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp
deleted file mode 100644
index b30a7ea..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#include "SkTypes.h"
-#include "SkTHash.h"
-#include "SDL.h"
-#include "Timer.h"
-#include "Window_mac.h"
-#include "../Application.h"
-
-using sk_app::Application;
-
-int main(int argc, char* argv[]) {
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
- SkDebugf("Could not initialize SDL!\n");
- return 1;
- }
-
- Application* app = Application::Create(argc, argv, nullptr);
-
- SDL_Event event;
- bool done = false;
- while (!done) {
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- // events handled by the windows
- case SDL_WINDOWEVENT:
- case SDL_MOUSEMOTION:
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- case SDL_MOUSEWHEEL:
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- case SDL_TEXTINPUT:
- done = sk_app::Window_mac::HandleWindowEvent(event);
- break;
-
- case SDL_QUIT:
- done = true;
- break;
-
- default:
- break;
- }
- }
-
- app->onIdle();
- }
- delete app;
-
- SDL_Quit();
-
- return 0;
-}
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp b/src/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
deleted file mode 100644
index ce2727e..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../GLWindowContext.h"
-#include "WindowContextFactory_unix.h"
-
-#include <GL/gl.h>
-
-using sk_app::window_context_factory::XlibWindowInfo;
-using sk_app::DisplayParams;
-using sk_app::GLWindowContext;
-
-namespace {
-
-class GLWindowContext_xlib : public GLWindowContext {
-public:
- GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
- ~GLWindowContext_xlib() override;
-
- void onSwapBuffers() override;
-
- void onDestroyContext() override;
-
-protected:
- void onInitializeContext() override;
-
-private:
- GLWindowContext_xlib(void*, const DisplayParams&);
-
- Display* fDisplay;
- XWindow fWindow;
- GLXFBConfig* fFBConfig;
- XVisualInfo* fVisualInfo;
- GLXContext fGLContext;
-
- typedef GLWindowContext INHERITED;
-};
-
-GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
- : INHERITED(params)
- , fDisplay(winInfo.fDisplay)
- , fWindow(winInfo.fWindow)
- , fFBConfig(winInfo.fFBConfig)
- , fVisualInfo(winInfo.fVisualInfo)
- , fGLContext() {
- fWidth = winInfo.fWidth;
- fHeight = winInfo.fHeight;
- this->initializeContext();
-}
-
-using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
-
-void GLWindowContext_xlib::onInitializeContext() {
- SkASSERT(fDisplay);
- SkASSERT(!fGLContext);
- // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
- // created with this rather than glXCreateContext.
- CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB(
- (const GLubyte*)"glXCreateContextAttribsARB");
- if (createContextAttribs && fFBConfig) {
- // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features
- // have been removed).
- for (int minor = 2; minor >= 0 && !fGLContext; --minor) {
- // Ganesh prefers a compatibility profile for possible NVPR support. However, RenderDoc
- // requires a core profile. Edit this code to use RenderDoc.
- for (int profile : {GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB}) {
- int attribs[] = {
- GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor,
- GLX_CONTEXT_PROFILE_MASK_ARB, profile,
- 0
- };
- fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs);
- if (fGLContext) {
- break;
- }
- }
- }
- }
- if (!fGLContext) {
- fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
- }
- if (!fGLContext) {
- return;
- }
-
- if (glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
- glClearStencil(0);
- glClearColor(0, 0, 0, 0);
- glStencilMask(0xffffffff);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
- glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
- glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
-
- XWindow root;
- int x, y;
- unsigned int border_width, depth;
- XGetGeometry(fDisplay, fWindow, &root, &x, &y,
- (unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth);
- glViewport(0, 0, fWidth, fHeight);
- }
-}
-
-GLWindowContext_xlib::~GLWindowContext_xlib() {
- this->destroyContext();
-}
-
-void GLWindowContext_xlib::onDestroyContext() {
- if (!fDisplay || !fGLContext) {
- return;
- }
- glXMakeCurrent(fDisplay, None, nullptr);
- glXDestroyContext(fDisplay, fGLContext);
- fGLContext = nullptr;
-}
-
-void GLWindowContext_xlib::onSwapBuffers() {
- if (fDisplay && fGLContext) {
- glXSwapBuffers(fDisplay, fWindow);
- }
-}
-
-} // anonymous namespace
-
-namespace sk_app {
-
-namespace window_context_factory {
-
-WindowContext* NewGLForXlib(const XlibWindowInfo& winInfo, const DisplayParams& params) {
- WindowContext* ctx = new GLWindowContext_xlib(winInfo, params);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-
-} // namespace window_context_factory
-
-} // namespace sk_app
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h b/src/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h
deleted file mode 100644
index e6d033b..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef WindowContextFactory_unix_DEFINED
-#define WindowContextFactory_unix_DEFINED
-
-#include <X11/Xlib.h>
-#include <GL/glx.h>
-typedef Window XWindow;
-
-namespace sk_app {
-
-class WindowContext;
-struct DisplayParams;
-
-namespace window_context_factory {
-
-struct XlibWindowInfo {
- Display* fDisplay;
- XWindow fWindow;
- GLXFBConfig* fFBConfig;
- XVisualInfo* fVisualInfo;
- int fWidth;
- int fHeight;
-};
-
-WindowContext* NewVulkanForXlib(const XlibWindowInfo&, const DisplayParams&);
-
-WindowContext* NewGLForXlib(const XlibWindowInfo&, const DisplayParams&);
-
-WindowContext* NewRasterForXlib(const XlibWindowInfo&, const DisplayParams&);
-
-} // namespace window_context_factory
-
-} // namespace sk_app
-
-#endif
diff --git a/src/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp b/src/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp
deleted file mode 100644
index beb3eda..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#include "SkTypes.h"
-#include "SkTHash.h"
-#include "Timer.h"
-#include "Window_unix.h"
-#include "../Application.h"
-
-using sk_app::Application;
-
-void finishWindow(sk_app::Window_unix* win) {
- win->finishResize();
- win->finishPaint();
-}
-
-int main(int argc, char**argv) {
-
- Display* display = XOpenDisplay(nullptr);
-
- Application* app = Application::Create(argc, argv, (void*)display);
-
- // Get the file descriptor for the X display
- int x11_fd = ConnectionNumber(display);
- int count = x11_fd + 1;
-
- SkTHashSet<sk_app::Window_unix*> pendingWindows;
- bool done = false;
- while (!done) {
- // Create a file description set containing x11_fd
- fd_set in_fds;
- FD_ZERO(&in_fds);
- FD_SET(x11_fd, &in_fds);
-
- // Set a sleep timer
- struct timeval tv;
- tv.tv_usec = 100;
- tv.tv_sec = 0;
-
- while (!XPending(display)) {
- // Wait for an event on the file descriptor or for timer expiration
- (void) select(count, &in_fds, NULL, NULL, &tv);
- }
-
- // Handle XEvents (if any) and flush the input
- int count = XPending(display);
- while (count-- && !done) {
- XEvent event;
- XNextEvent(display, &event);
-
- sk_app::Window_unix* win = sk_app::Window_unix::gWindowMap.find(event.xany.window);
- if (!win) {
- continue;
- }
-
- // paint and resize events get collapsed
- switch (event.type) {
- case Expose:
- win->markPendingPaint();
- pendingWindows.add(win);
- break;
- case ConfigureNotify:
- win->markPendingResize(event.xconfigurerequest.width,
- event.xconfigurerequest.height);
- pendingWindows.add(win);
- break;
- default:
- if (win->handleEvent(event)) {
- done = true;
- }
- break;
- }
- }
-
- pendingWindows.foreach(finishWindow);
- if (pendingWindows.count() > 0) {
- app->onIdle();
- }
- pendingWindows.reset();
-
- XFlush(display);
- }
-
- delete app;
-
- XCloseDisplay(display);
-
- return 0;
-}
diff --git a/src/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h b/src/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h
deleted file mode 100644
index 4367492..0000000
--- a/src/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef WindowContextFactory_win_DEFINED
-#define WindowContextFactory_win_DEFINED
-
-#include <Windows.h>
-
-namespace sk_app {
-
-class WindowContext;
-struct DisplayParams;
-
-namespace window_context_factory {
-
-WindowContext* NewVulkanForWin(HWND, const DisplayParams&);
-
-WindowContext* NewGLForWin(HWND, const DisplayParams&);
-
-WindowContext* NewRasterForWin(HWND, const DisplayParams&);
-
-} // namespace window_context_factory
-
-} // namespace sk_app
-
-#endif
diff --git a/src/third_party/skia/tools/whitelist_typefaces.cpp b/src/third_party/skia/tools/whitelist_typefaces.cpp
index 5cdfb6a..546dd96 100644
--- a/src/third_party/skia/tools/whitelist_typefaces.cpp
+++ b/src/third_party/skia/tools/whitelist_typefaces.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "SkGraphics.h"
+#include "include/core/SkGraphics.h"
extern bool CheckChecksums();
extern bool GenerateChecksums();
diff --git a/src/third_party/skia/tools/win_dbghelp.cpp b/src/third_party/skia/tools/win_dbghelp.cpp
index 7291f36..37e5f7f 100644
--- a/src/third_party/skia/tools/win_dbghelp.cpp
+++ b/src/third_party/skia/tools/win_dbghelp.cpp
@@ -5,8 +5,9 @@
* found in the LICENSE file.
*/
-#include "windows.h"
-#include "win_dbghelp.h"
+#include <windows.h>
+#include "tools/win_dbghelp.h"
+
#include <process.h>
#include <string.h>
#include <stdlib.h>
diff --git a/src/third_party/skia/tools/win_dbghelp.h b/src/third_party/skia/tools/win_dbghelp.h
index d334318..226249f 100644
--- a/src/third_party/skia/tools/win_dbghelp.h
+++ b/src/third_party/skia/tools/win_dbghelp.h
@@ -8,7 +8,7 @@
#ifndef win_dbghelp_DEFINED
#define win_dbghelp_DEFINED
-#ifdef SK_BUILD_FOR_WIN32
+#ifdef SK_BUILD_FOR_WIN
#include <dbghelp.h>
#include <shellapi.h>
@@ -30,6 +30,6 @@
int GenerateDumpAndPrintCallstack(EXCEPTION_POINTERS* pExceptionPointers);
-#endif // SK_BUILD_FOR_WIN32
+#endif // SK_BUILD_FOR_WIN
#endif // win_dbghelp_DEFINED
diff --git a/src/third_party/skia/tools/win_lcid.cpp b/src/third_party/skia/tools/win_lcid.cpp
index 8cb7463..791f6bc 100644
--- a/src/third_party/skia/tools/win_lcid.cpp
+++ b/src/third_party/skia/tools/win_lcid.cpp
@@ -4,8 +4,8 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "windows.h"
-#include "stdio.h"
+#include <windows.h>
+#include <stdio.h>
#define BUFFER_SIZE 512
BOOL CALLBACK MyFuncLocaleEx(LPWSTR pStr, DWORD dwFlags, LPARAM lparam) {
diff --git a/src/third_party/skia/tools/xsan.blacklist b/src/third_party/skia/tools/xsan.blacklist
index a917e2d..df2b384 100644
--- a/src/third_party/skia/tools/xsan.blacklist
+++ b/src/third_party/skia/tools/xsan.blacklist
@@ -1,2 +1,15 @@
-# Suppress third_party/externals. We mostly care about our own code.
-src:*third_party/externals*
+#if 0
+
+# This file must be a no-op C #include header, and a valid *SAN blacklist file.
+# Luckily, anything starting with # is a comment to *SAN blacklist files,
+# and anything inside #if 0 is ignored by C. Yippee!
+#
+# If you want to type '*', type '.*' instead. Don't make C comments!
+
+# libpng and zlib both dereference under-aligned pointers.
+# TODO: it'd be nice to tag these as [alignment] only but our Mac toolchain can't yet.
+# [alignment]
+src:.*third_party/externals/libpng/intel/filter_sse2_intrinsics.c
+src:.*third_party/externals/zlib/deflate.c
+
+#endif