summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia/tools
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-03 13:42:47 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:27:51 +0000
commit8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (patch)
treed29d987c4d7b173cf853279b79a51598f104b403 /chromium/third_party/skia/tools
parent830c9e163d31a9180fadca926b3e1d7dfffb5021 (diff)
downloadqtwebengine-chromium-8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec.tar.gz
BASELINE: Update Chromium to 66.0.3359.156
Change-Id: I0c9831ad39911a086b6377b16f995ad75a51e441 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/third_party/skia/tools')
-rw-r--r--chromium/third_party/skia/tools/BinaryAsset.h18
-rw-r--r--chromium/third_party/skia/tools/OverwriteLine.h2
-rw-r--r--chromium/third_party/skia/tools/ProcStats.cpp4
-rw-r--r--chromium/third_party/skia/tools/ResourceFactory.h14
-rw-r--r--chromium/third_party/skia/tools/Resources.cpp28
-rw-r--r--chromium/third_party/skia/tools/bookmaker/bookmaker.cpp488
-rw-r--r--chromium/third_party/skia/tools/bookmaker/bookmaker.h186
-rw-r--r--chromium/third_party/skia/tools/bookmaker/definition.cpp109
-rw-r--r--chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp26
-rw-r--r--chromium/third_party/skia/tools/bookmaker/includeParser.cpp294
-rw-r--r--chromium/third_party/skia/tools/bookmaker/includeWriter.cpp390
-rw-r--r--chromium/third_party/skia/tools/bookmaker/mdOut.cpp386
-rw-r--r--chromium/third_party/skia/tools/bookmaker/parserCommon.cpp1
-rw-r--r--chromium/third_party/skia/tools/bookmaker/selfCheck.cpp215
-rw-r--r--chromium/third_party/skia/tools/bookmaker/spellCheck.cpp47
-rwxr-xr-xchromium/third_party/skia/tools/check-headers-self-sufficient1
-rw-r--r--chromium/third_party/skia/tools/colorspaceinfo.cpp2
-rw-r--r--chromium/third_party/skia/tools/debugger/SkDrawCommand.cpp8
-rw-r--r--chromium/third_party/skia/tools/debugger/SkObjectParser.cpp3
-rw-r--r--chromium/third_party/skia/tools/fiddle/fiddle_main.cpp4
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlags.cpp28
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlags.h4
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp15
-rw-r--r--chromium/third_party/skia/tools/fonts/SkRandomScalerContext.cpp (renamed from chromium/third_party/skia/tools/SkRandomScalerContext.cpp)1
-rw-r--r--chromium/third_party/skia/tools/fonts/SkRandomScalerContext.h (renamed from chromium/third_party/skia/tools/SkRandomScalerContext.h)0
-rw-r--r--chromium/third_party/skia/tools/fonts/SkTestFontMgr.cpp147
-rw-r--r--chromium/third_party/skia/tools/fonts/SkTestFontMgr.h19
-rw-r--r--chromium/third_party/skia/tools/fonts/SkTestScalerContext.cpp (renamed from chromium/third_party/skia/tools/SkTestScalerContext.cpp)0
-rw-r--r--chromium/third_party/skia/tools/fonts/SkTestScalerContext.h (renamed from chromium/third_party/skia/tools/SkTestScalerContext.h)0
-rw-r--r--chromium/third_party/skia/tools/fonts/create_test_font.cpp (renamed from chromium/third_party/skia/tools/create_test_font.cpp)9
-rw-r--r--chromium/third_party/skia/tools/fonts/generate_fir_coeff.py (renamed from chromium/third_party/skia/tools/generate_fir_coeff.py)46
-rw-r--r--chromium/third_party/skia/tools/fonts/sk_tool_utils_font.cpp148
-rw-r--r--chromium/third_party/skia/tools/fonts/test_font_index.inc (renamed from chromium/third_party/skia/tools/test_font_index.inc)0
-rw-r--r--chromium/third_party/skia/tools/fonts/test_font_monospace.inc (renamed from chromium/third_party/skia/tools/test_font_monospace.inc)20
-rw-r--r--chromium/third_party/skia/tools/fonts/test_font_sans_serif.inc (renamed from chromium/third_party/skia/tools/test_font_sans_serif.inc)17
-rw-r--r--chromium/third_party/skia/tools/fonts/test_font_serif.inc (renamed from chromium/third_party/skia/tools/test_font_serif.inc)20
-rw-r--r--chromium/third_party/skia/tools/gpu/GrContextFactory.cpp2
-rw-r--r--chromium/third_party/skia/tools/gpu/GrTest.cpp33
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp6
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/GrVulkanDefines.h2
-rwxr-xr-xchromium/third_party/skia/tools/install_dependencies.sh5
-rw-r--r--chromium/third_party/skia/tools/list_gms.cpp25
-rw-r--r--chromium/third_party/skia/tools/list_gpu_unit_tests.cpp27
-rw-r--r--chromium/third_party/skia/tools/ok.cpp389
-rw-r--r--chromium/third_party/skia/tools/ok.h69
-rw-r--r--chromium/third_party/skia/tools/ok_dsts.cpp70
-rw-r--r--chromium/third_party/skia/tools/ok_engines.cpp100
-rw-r--r--chromium/third_party/skia/tools/ok_srcs.cpp214
-rw-r--r--chromium/third_party/skia/tools/ok_test.cpp97
-rw-r--r--chromium/third_party/skia/tools/ok_vias.cpp317
-rw-r--r--chromium/third_party/skia/tools/pathops_sorter.htm16
-rw-r--r--chromium/third_party/skia/tools/remote_demo.cpp396
-rw-r--r--chromium/third_party/skia/tools/shape/SkShaper.h5
-rw-r--r--chromium/third_party/skia/tools/shape/SkShaper_harfbuzz.cpp780
-rw-r--r--chromium/third_party/skia/tools/shape/SkShaper_primitive.cpp22
-rw-r--r--chromium/third_party/skia/tools/shape/using_skia_and_harfbuzz.cpp19
-rw-r--r--chromium/third_party/skia/tools/sk_app/CommandSet.cpp2
-rw-r--r--chromium/third_party/skia/tools/sk_app/DisplayParams.h5
-rw-r--r--chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp6
-rw-r--r--chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp2
-rw-r--r--chromium/third_party/skia/tools/sk_app/Window.cpp2
-rw-r--r--chromium/third_party/skia/tools/sk_app/WindowContext.h10
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp7
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp21
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp13
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h3
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp15
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/Window_ios.h14
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp21
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp15
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h3
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp15
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/Window_mac.h14
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp1
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp2
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/Window_unix.h15
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp5
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp3
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/Window_win.cpp8
-rw-r--r--chromium/third_party/skia/tools/sk_pixel_iter.h61
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils.cpp102
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils.h31
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils_font.cpp70
-rw-r--r--chromium/third_party/skia/tools/skdiff/skdiff.h2
-rw-r--r--chromium/third_party/skia/tools/skdiff/skdiff_html.cpp2
-rw-r--r--chromium/third_party/skia/tools/skdiff/skdiff_main.cpp6
-rw-r--r--chromium/third_party/skia/tools/skp/webpages_playback.py2
-rw-r--r--chromium/third_party/skia/tools/skpbench/skpbench.cpp7
-rw-r--r--chromium/third_party/skia/tools/skqp/README.md138
-rwxr-xr-xchromium/third_party/skia/tools/skqp/download_model71
-rwxr-xr-xchromium/third_party/skia/tools/skqp/extract_report.py29
-rwxr-xr-xchromium/third_party/skia/tools/skqp/generate_gn_args58
-rw-r--r--chromium/third_party/skia/tools/skqp/gm_knowledge.cpp339
-rw-r--r--chromium/third_party/skia/tools/skqp/gm_knowledge.h10
-rw-r--r--chromium/third_party/skia/tools/skqp/gm_runner.cpp87
-rw-r--r--chromium/third_party/skia/tools/skqp/gm_runner.h12
-rw-r--r--chromium/third_party/skia/tools/skqp/gn_to_bp.py216
-rw-r--r--chromium/third_party/skia/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp55
-rwxr-xr-xchromium/third_party/skia/tools/skqp/make_apk.sh49
-rw-r--r--chromium/third_party/skia/tools/skqp/make_gmkb.go44
-rwxr-xr-xchromium/third_party/skia/tools/skqp/make_known_tests.sh26
-rwxr-xr-xchromium/third_party/skia/tools/skqp/make_model.sh20
-rwxr-xr-xchromium/third_party/skia/tools/skqp/make_universal_apk97
-rwxr-xr-xchromium/third_party/skia/tools/skqp/remove_unneeded_assets34
-rwxr-xr-xchromium/third_party/skia/tools/skqp/run_skqp_exe53
-rwxr-xr-xchromium/third_party/skia/tools/skqp/setup_resources20
-rw-r--r--chromium/third_party/skia/tools/skqp/skqp.cpp7
-rwxr-xr-xchromium/third_party/skia/tools/skqp/upload_model62
-rwxr-xr-xchromium/third_party/skia/tools/test_gpuveto.py169
-rw-r--r--chromium/third_party/skia/tools/viewer/BisectSlide.cpp130
-rw-r--r--chromium/third_party/skia/tools/viewer/BisectSlide.h54
-rw-r--r--chromium/third_party/skia/tools/viewer/SkottieSlide.cpp25
-rw-r--r--chromium/third_party/skia/tools/viewer/SkottieSlide.h45
-rw-r--r--chromium/third_party/skia/tools/viewer/SkottieSlide2.cpp128
-rw-r--r--chromium/third_party/skia/tools/viewer/SlideDir.cpp418
-rw-r--r--chromium/third_party/skia/tools/viewer/SlideDir.h67
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.cpp363
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.h43
-rw-r--r--chromium/third_party/skia/tools/win_dbghelp.h4
-rw-r--r--chromium/third_party/skia/tools/xsan.blacklist2
120 files changed, 5569 insertions, 3085 deletions
diff --git a/chromium/third_party/skia/tools/BinaryAsset.h b/chromium/third_party/skia/tools/BinaryAsset.h
deleted file mode 100644
index 6fb7157596e..00000000000
--- a/chromium/third_party/skia/tools/BinaryAsset.h
+++ /dev/null
@@ -1,18 +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 BinaryAsset_DEFINED
-#define BinaryAsset_DEFINED
-
-#include <cstddef>
-
-struct BinaryAsset {
- const char* name;
- const void* data;
- size_t len;
-};
-
-#endif // BinaryAsset_DEFINED
diff --git a/chromium/third_party/skia/tools/OverwriteLine.h b/chromium/third_party/skia/tools/OverwriteLine.h
index e8f0504b1af..8985a6a01c6 100644
--- a/chromium/third_party/skia/tools/OverwriteLine.h
+++ b/chromium/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/chromium/third_party/skia/tools/ProcStats.cpp b/chromium/third_party/skia/tools/ProcStats.cpp
index 51ddf55aa50..9515368f9e7 100644
--- a/chromium/third_party/skia/tools/ProcStats.cpp
+++ b/chromium/third_party/skia/tools/ProcStats.cpp
@@ -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/chromium/third_party/skia/tools/ResourceFactory.h b/chromium/third_party/skia/tools/ResourceFactory.h
new file mode 100644
index 00000000000..7e890173128
--- /dev/null
+++ b/chromium/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 <SkData.h>
+
+extern sk_sp<SkData> (*gResourceFactory)(const char*);
+
+#endif // ResourceFactory_DEFINED
diff --git a/chromium/third_party/skia/tools/Resources.cpp b/chromium/third_party/skia/tools/Resources.cpp
index 9d540269869..0e343c4883c 100644
--- a/chromium/third_party/skia/tools/Resources.cpp
+++ b/chromium/third_party/skia/tools/Resources.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "BinaryAsset.h"
+#include "ResourceFactory.h"
#include "Resources.h"
#include "SkBitmap.h"
#include "SkCommandLineFlags.h"
@@ -19,6 +19,8 @@
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);
}
@@ -27,7 +29,6 @@ void SetResourcePath(const char* resource) {
FLAGS_resourcePath.set(0, resource);
}
-
bool DecodeDataToBitmap(sk_sp<SkData> data, SkBitmap* dst) {
std::unique_ptr<SkImageGenerator> gen(SkImageGenerator::MakeFromEncoded(std::move(data)));
return gen && dst->tryAllocPixels(gen->getInfo()) &&
@@ -41,27 +42,20 @@ std::unique_ptr<SkStreamAsset> GetResourceAsStream(const char* resource) {
: nullptr;
}
-#ifdef SK_EMBED_RESOURCES
-extern BinaryAsset gResources[];
sk_sp<SkData> GetResourceAsData(const char* resource) {
- for (const BinaryAsset* ptr = gResources; ptr->name; ++ptr) {
- if (0 == strcmp(resource, ptr->name)) {
- return SkData::MakeWithoutCopy(ptr->data, ptr->len);
+ if (gResourceFactory) {
+ if (auto data = gResourceFactory(resource)) {
+ return data;
}
+ SkDebugf("Resource \"%s\" not found.\n", resource);
+ SK_ABORT("missing resource");
+ }
+ if (auto data = SkData::MakeFromFileName(GetResourcePath(resource).c_str())) {
+ return data;
}
SkDebugf("Resource \"%s\" not found.\n", resource);
- SK_ABORT("missing resource");
return nullptr;
}
-#else
-sk_sp<SkData> GetResourceAsData(const char* resource) {
- auto data = SkData::MakeFromFileName(GetResourcePath(resource).c_str());
- if (!data) {
- SkDebugf("Resource \"%s\" not found.\n", resource);
- }
- return data;
-}
-#endif
sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource) {
std::unique_ptr<SkStreamAsset> stream(GetResourceAsStream(resource));
diff --git a/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp b/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
index b63813d6675..02dbbc1961f 100644
--- a/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
@@ -7,26 +7,36 @@
#include "bookmaker.h"
+#ifdef SK_BUILD_FOR_WIN
+#include <Windows.h>
+#endif
+
DEFINE_string2(status, a, "", "File containing status of documentation. (Use in place of -b -i)");
DEFINE_string2(bmh, b, "", "Path to a *.bmh file or a directory.");
DEFINE_bool2(catalog, c, false, "Write example catalog.htm. (Requires -b -f -r)");
DEFINE_string2(examples, e, "", "File of fiddlecli input, usually fiddle.json (For now, disables -r -f -s)");
DEFINE_string2(fiddle, f, "", "File of fiddlecli output, usually fiddleout.json.");
-DEFINE_bool2(hack, h, false, "Do a find/replace hack to update all *.bmh files. (Requires -b)");
+DEFINE_bool2(hack, H, false, "Do a find/replace hack to update all *.bmh files. (Requires -b)");
+// h is reserved for help
DEFINE_string2(include, i, "", "Path to a *.h file or a directory.");
DEFINE_bool2(selfcheck, k, false, "Check bmh against itself. (Requires -b)");
DEFINE_bool2(stdout, o, false, "Write file out to standard out.");
DEFINE_bool2(populate, p, false, "Populate include from bmh. (Requires -b -i)");
+// q is reserved for quiet
DEFINE_string2(ref, r, "", "Resolve refs and write *.md files to path. (Requires -b -f)");
DEFINE_string2(spellcheck, s, "", "Spell-check [once, all, mispelling]. (Requires -b)");
DEFINE_bool2(tokens, t, false, "Write bmh from include. (Requires -b -i)");
DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)");
+// v is reserved for verbose
DEFINE_bool2(skip, z, false, "Skip degenerate missed in legacy preprocessor.");
/* recipe for generating timestamps for existing doxygen comments
find include/core -type f -name '*.h' -print -exec git blame {} \; > ~/all.blame.txt
todos:
+add new markup to associate typedef SaveLayerFlags with Enum so that, for
+ documentation purposes, this enum is named rather than anonymous
+check column 1 of subtopic tables to see that they start lowercase and don't have a trailing period
space table better for Constants
should Return be on same line as 'Return Value'?
remove anonymous header, e.g. Enum SkPaint::::anonymous_2
@@ -38,6 +48,7 @@ enum comments should be disallowed unless after #Enum and before first #Const
trouble with aliases, plurals
need to keep first letter of includeWriter @param / @return lowercase
Quad -> quad, Quads -> quads
+deprecated methods should be sorted down in md out, and show include "Deprecated." text body.
see head of selfCheck.cpp for additional todos
*/
@@ -50,7 +61,7 @@ see head of selfCheck.cpp for additional todos
*/
bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markType,
- const vector<string>& typeNameBuilder) {
+ const vector<string>& typeNameBuilder, HasTag hasTag) {
Definition* definition = nullptr;
switch (markType) {
case MarkType::kComment:
@@ -134,6 +145,11 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
return false;
}
}
+ if (HasTag::kYes == hasTag) {
+ if (!this->checkEndMarker(markType, definition->fName)) {
+ return false;
+ }
+ }
if (!this->popParentStack(definition)) {
return false;
}
@@ -178,20 +194,42 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
definition = rootDefinition;
definition->fFileName = fFileName;
definition->fContentStart = fChar;
- definition->fName = typeNameBuilder[0];
- Definition* parent = fParent;
- while (parent && MarkType::kTopic != parent->fMarkType
- && MarkType::kSubtopic != parent->fMarkType) {
- parent = parent->fParent;
+ if (MarkType::kTopic == markType) {
+ if (fParent) {
+ return this->reportError<bool>("#Topic must be root");
+ }
+ // topic name is unappended
+ definition->fName = typeNameBuilder[0];
+ } else {
+ if (!fParent) {
+ return this->reportError<bool>("#Subtopic may not be root");
+ }
+ Definition* parent = fParent;
+ while (MarkType::kTopic != parent->fMarkType && MarkType::kSubtopic != parent->fMarkType) {
+ parent = parent->fParent;
+ if (!parent) {
+ // subtopic must have subtopic or topic in parent chain
+ return this->reportError<bool>("#Subtopic missing parent");
+ }
+ }
+ if (MarkType::kSubtopic == parent->fMarkType) {
+ // subtopic prepends parent subtopic name, but not parent topic name
+ definition->fName = parent->fName + '_';
+ }
+ definition->fName += typeNameBuilder[0];
+ definition->fFiddle = parent->fFiddle + '_';
}
- definition->fFiddle = parent ? parent->fFiddle + '_' : "";
definition->fFiddle += Definition::NormalizedName(typeNameBuilder[0]);
this->setAsParent(definition);
}
{
- const string& fullTopic = hasEnd ? fParent->fFiddle : definition->fFiddle;
+ SkASSERT(hasEnd ? fParent : definition);
+ string fullTopic = hasEnd ? fParent->fFiddle : definition->fFiddle;
Definition* defPtr = fTopicMap[fullTopic];
if (hasEnd) {
+ if (HasTag::kYes == hasTag && !this->checkEndMarker(markType, fullTopic)) {
+ return false;
+ }
if (!definition) {
definition = defPtr;
} else if (definition != defPtr) {
@@ -237,7 +275,6 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
case MarkType::kDescription:
case MarkType::kStdOut:
// may be one-liner
- case MarkType::kBug:
case MarkType::kNoExample:
case MarkType::kParam:
case MarkType::kReturn:
@@ -274,7 +311,6 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
}
// not one-liners
case MarkType::kCode:
- case MarkType::kDeprecated:
case MarkType::kExample:
case MarkType::kExperimental:
case MarkType::kFormula:
@@ -333,22 +369,28 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
// always treated as one-liners (can't detect misuse easily)
case MarkType::kAlias:
case MarkType::kAnchor:
+ case MarkType::kBug:
case MarkType::kDefine:
+ case MarkType::kDeprecated:
case MarkType::kDuration:
- case MarkType::kError:
case MarkType::kFile:
case MarkType::kHeight:
+ case MarkType::kIllustration:
case MarkType::kImage:
- case MarkType::kLiteral:
+ case MarkType::kIn:
+ case MarkType::kLine:
+ case MarkType::kLiteral:
case MarkType::kOutdent:
case MarkType::kPlatform:
+ case MarkType::kPopulate:
case MarkType::kSeeAlso:
case MarkType::kSet:
case MarkType::kSubstitute:
case MarkType::kTime:
case MarkType::kVolatile:
case MarkType::kWidth:
- if (hasEnd && MarkType::kAnchor != markType) {
+ // todo : add check disallowing children?
+ if (hasEnd && MarkType::kAnchor != markType && MarkType::kLine != markType) {
return this->reportError<bool>("one liners omit end element");
} else if (!hasEnd && MarkType::kAnchor == markType) {
return this->reportError<bool>("anchor line must have end element last");
@@ -385,6 +427,32 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
return this->reportError<bool>("duplicate alias");
}
fAliasMap[alias] = definition;
+ definition->fFiddle = definition->fParent->fFiddle;
+ }
+ else if (MarkType::kLine == markType) {
+ const char* nextLF = this->strnchr('\n', this->fEnd);
+ const char* start = fChar;
+ const char* end = this->trimmedBracketEnd(fMC);
+ this->skipToEndBracket(fMC, nextLF);
+ if (fMC != this->next() || fMC != this->next()) {
+ return this->reportError<bool>("expected ## to delineate line");
+ }
+ fMarkup.emplace_front(MarkType::kText, start, fLineCount, definition);
+ Definition* text = &fMarkup.front();
+ text->fContentStart = start;
+ text->fContentEnd = end;
+ text->fTerminator = fChar;
+ definition->fContentEnd = text->fContentEnd;
+ definition->fTerminator = fChar;
+ definition->fChildren.emplace_back(text);
+ } else if (MarkType::kDeprecated == markType) {
+ this->skipSpace();
+ fParent->fDeprecated = true;
+ fParent->fToBeDeprecated = this->skipExact("soon");
+ this->skipSpace();
+ if ('\n' != this->peek()) {
+ return this->reportError<bool>("unexpected text after #Deprecated");
+ }
}
break;
case MarkType::kExternal:
@@ -411,6 +479,33 @@ void BmhParser::reportDuplicates(const Definition& def, const string& dup) const
}
}
+
+static Definition* find_fiddle(Definition* def, string name) {
+ if (MarkType::kExample == def->fMarkType && name == def->fFiddle) {
+ return def;
+ }
+ for (auto& child : def->fChildren) {
+ Definition* result = find_fiddle(child, name);
+ if (result) {
+ return result;
+ }
+ }
+ return nullptr;
+}
+
+Definition* BmhParser::findExample(string name) const {
+ for (const auto& topic : fTopicMap) {
+ if (topic.second->fParent) {
+ continue;
+ }
+ Definition* def = find_fiddle(topic.second, name);
+ if (def) {
+ return def;
+ }
+ }
+ return nullptr;
+}
+
static void find_examples(const Definition& def, vector<string>* exampleNames) {
if (MarkType::kExample == def.fMarkType) {
exampleNames->push_back(def.fFiddle);
@@ -420,6 +515,39 @@ static void find_examples(const Definition& def, vector<string>* exampleNames) {
}
}
+bool BmhParser::checkEndMarker(MarkType markType, string match) const {
+ TextParser tp(fFileName, fLine, fChar, fLineCount);
+ tp.skipSpace();
+ if (fMC != tp.next()) {
+ return this->reportError<bool>("mismatched end marker expect #");
+ }
+ const char* nameStart = tp.fChar;
+ tp.skipToNonAlphaNum();
+ string markName(nameStart, tp.fChar - nameStart);
+ if (fMaps[(int) markType].fName != markName) {
+ return this->reportError<bool>("expected #XXX ## to match");
+ }
+ tp.skipSpace();
+ nameStart = tp.fChar;
+ tp.skipToNonAlphaNum();
+ markName = string(nameStart, tp.fChar - nameStart);
+ if ("" == markName) {
+ if (fMC != tp.next() || fMC != tp.next()) {
+ return this->reportError<bool>("expected ##");
+ }
+ return true;
+ }
+ std::replace(markName.begin(), markName.end(), '-', '_');
+ auto defPos = match.rfind(markName);
+ if (string::npos == defPos) {
+ return this->reportError<bool>("mismatched end marker v1");
+ }
+ if (markName.size() != match.size() - defPos) {
+ return this->reportError<bool>("mismatched end marker v2");
+ }
+ return true;
+}
+
bool BmhParser::checkExamples() const {
vector<string> exampleNames;
for (const auto& topic : fTopicMap) {
@@ -673,7 +801,8 @@ bool BmhParser::findDefinitions() {
} else {
vector<string> parentName;
parentName.push_back(fParent->fName);
- if (!this->addDefinition(fChar - 1, true, fParent->fMarkType, parentName)) {
+ if (!this->addDefinition(fChar - 1, true, fParent->fMarkType, parentName,
+ HasTag::kNo)) {
return false;
}
}
@@ -717,14 +846,16 @@ bool BmhParser::findDefinitions() {
if (hasEnd && expectEnd) {
SkASSERT(fMC != this->peek());
}
- if (!this->addDefinition(defStart, hasEnd, markType, typeNameBuilder)) {
+ if (!this->addDefinition(defStart, hasEnd, markType, typeNameBuilder,
+ HasTag::kYes)) {
return false;
}
continue;
} else if (this->peek() == ' ') {
if (!fParent || (MarkType::kTable != fParent->fMarkType
&& MarkType::kLegend != fParent->fMarkType
- && MarkType::kList != fParent->fMarkType)) {
+ && MarkType::kList != fParent->fMarkType
+ && MarkType::kLine != fParent->fMarkType)) {
int endHashes = this->endHashCount();
if (endHashes <= 1) {
if (fParent) {
@@ -814,6 +945,9 @@ fail:
return MarkType::kNone;
}
+ // write #In to show containing #Topic
+ // write #Line with one liner from Member_Functions, Constructors, Operators if method,
+ // from Constants if enum, otherwise from #Subtopic containing match
bool HackParser::hackFiles() {
string filename(fFileName);
size_t len = filename.length() - 1;
@@ -821,42 +955,219 @@ bool HackParser::hackFiles() {
--len;
}
filename = filename.substr(len + 1);
- // remove trailing period from #Param and #Return
- FILE* out = fopen(filename.c_str(), "wb");
- if (!out) {
+ if (filename.substr(0, 2) != "Sk") {
+ return true;
+ }
+ size_t under = filename.find('_');
+ SkASSERT(under);
+ string className = filename.substr(0, under);
+ fOut = fopen(filename.c_str(), "wb");
+ if (!fOut) {
SkDebugf("could not open output file %s\n", filename.c_str());
return false;
}
- const char* start = fStart;
- do {
- const char* match = this->strnchr('#', fEnd);
- if (!match) {
- break;
- }
- this->skipTo(match);
- this->next();
- if (!this->startsWith("Param") && !this->startsWith("Return")) {
- continue;
- }
- const char* end = this->strnstr("##", fEnd);
- while (true) {
- TextParser::Save lastPeriod(this);
- this->next();
- if (!this->skipToEndBracket('.', end)) {
- lastPeriod.restore();
- break;
+ auto mapEntry = fBmhParser.fClassMap.find(className);
+ SkASSERT(fBmhParser.fClassMap.end() != mapEntry);
+ const Definition* classMarkup = &mapEntry->second;
+ const Definition* root = classMarkup->fParent;
+ SkASSERT(root);
+ SkASSERT(root->fTerminator);
+ SkASSERT('\n' == root->fTerminator[0]);
+ SkASSERT(!root->fParent);
+ fStart = root->fStart;
+ fChar = fStart;
+ fClassesAndStructs = nullptr;
+ fConstants = nullptr;
+ fConstructors = nullptr;
+ fMemberFunctions = nullptr;
+ fMembers = nullptr;
+ fOperators = nullptr;
+ fRelatedFunctions = nullptr;
+ this->topicIter(root);
+ fprintf(fOut, "%.*s", (int) (fEnd - fChar), fChar);
+ fclose(fOut);
+ if (this->writtenFileDiffers(filename, root->fFileName)) {
+ SkDebugf("wrote %s\n", filename.c_str());
+ } else {
+ remove(filename.c_str());
+ }
+ return true;
+}
+
+string HackParser::searchTable(const Definition* tableHolder, const Definition* match) {
+ if (!tableHolder) {
+ return "";
+ }
+ string bestMatch;
+ string result;
+ for (auto table : tableHolder->fChildren) {
+ if (MarkType::kTable == table->fMarkType) {
+ for (auto row : table->fChildren) {
+ if (MarkType::kRow == row->fMarkType) {
+ const Definition* col0 = row->fChildren[0];
+ size_t len = col0->fContentEnd - col0->fContentStart;
+ string method = string(col0->fContentStart, len);
+ if (len - 2 == method.find("()") && islower(method[0])
+ && Definition::MethodType::kOperator != match->fMethodType) {
+ method = method.substr(0, len - 2);
+ }
+ if (string::npos == match->fName.find(method)) {
+ continue;
+ }
+ if (bestMatch.length() < method.length()) {
+ bestMatch = method;
+ const Definition * col1 = row->fChildren[1];
+ if (col1->fContentEnd <= col1->fContentStart) {
+ SkASSERT(string::npos != col1->fFileName.find("SkImageInfo"));
+ result = "incomplete";
+ } else {
+ result = string(col1->fContentStart, col1->fContentEnd -
+ col1->fContentStart);
+ }
+ }
+ }
}
}
- if ('.' == this->peek()) {
- fprintf(out, "%.*s", (int) (fChar - start), start);
- this->next();
- start = fChar;
+ }
+ return result;
+}
+
+// returns true if topic has method
+void HackParser::topicIter(const Definition* topic) {
+ if (string::npos != topic->fName.find(MdOut::kClassesAndStructs)) {
+ SkASSERT(!fClassesAndStructs);
+ fClassesAndStructs = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kConstants)) {
+ SkASSERT(!fConstants);
+ fConstants = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kConstructors)) {
+ SkASSERT(!fConstructors);
+ fConstructors = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kMemberFunctions)) {
+ SkASSERT(!fMemberFunctions);
+ fMemberFunctions = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kMembers)) {
+ SkASSERT(!fMembers);
+ fMembers = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kOperators)) {
+ SkASSERT(!fOperators);
+ fOperators = topic;
+ }
+ if (string::npos != topic->fName.find(MdOut::kRelatedFunctions)) {
+ SkASSERT(!fRelatedFunctions);
+ fRelatedFunctions = topic;
+ }
+ for (auto child : topic->fChildren) {
+ string oneLiner;
+ bool hasIn = false;
+ bool hasLine = false;
+ for (auto part : child->fChildren) {
+ hasIn |= MarkType::kIn == part->fMarkType;
+ hasLine |= MarkType::kLine == part->fMarkType;
+ }
+ switch (child->fMarkType) {
+ case MarkType::kMethod: {
+ hasIn |= MarkType::kTopic != topic->fMarkType &&
+ MarkType::kSubtopic != topic->fMarkType; // don't write #In if parent is class
+ hasLine |= child->fClone;
+ if (!hasLine) {
+ // find member_functions, add entry 2nd column text to #Line
+ for (auto tableHolder : { fMemberFunctions, fConstructors, fOperators }) {
+ if (!tableHolder) {
+ continue;
+ }
+ if (Definition::MethodType::kConstructor == child->fMethodType
+ && fConstructors != tableHolder) {
+ continue;
+ }
+ if (Definition::MethodType::kOperator == child->fMethodType
+ && fOperators != tableHolder) {
+ continue;
+ }
+ string temp = this->searchTable(tableHolder, child);
+ if ("" != temp) {
+ SkASSERT("" == oneLiner || temp == oneLiner);
+ oneLiner = temp;
+ }
+ }
+ if ("" == oneLiner) {
+ #ifdef SK_DEBUG
+ const Definition* rootParent = topic;
+ while (rootParent->fParent && MarkType::kClass != rootParent->fMarkType
+ && MarkType::kStruct != rootParent->fMarkType) {
+ rootParent = rootParent->fParent;
+ }
+ #endif
+ SkASSERT(rootParent);
+ SkASSERT(MarkType::kClass == rootParent->fMarkType
+ || MarkType::kStruct == rootParent->fMarkType);
+ hasLine = true;
+ }
+ }
+
+ if (hasIn && hasLine) {
+ continue;
+ }
+ const char* start = fChar;
+ const char* end = child->fContentStart;
+ fprintf(fOut, "%.*s", (int) (end - start), start);
+ fChar = end;
+ // write to method markup header end
+ if (!hasIn) {
+ fprintf(fOut, "\n#In %s", topic->fName.c_str());
+ }
+ if (!hasLine) {
+ fprintf(fOut, "\n#Line # %s ##", oneLiner.c_str());
+ }
+ } break;
+ case MarkType::kTopic:
+ case MarkType::kSubtopic:
+ this->addOneLiner(fRelatedFunctions, child, hasLine, true);
+ this->topicIter(child);
+ break;
+ case MarkType::kStruct:
+ case MarkType::kClass:
+ this->addOneLiner(fClassesAndStructs, child, hasLine, false);
+ this->topicIter(child);
+ break;
+ case MarkType::kEnum:
+ case MarkType::kEnumClass:
+ this->addOneLiner(fConstants, child, hasLine, true);
+ break;
+ case MarkType::kMember:
+ this->addOneLiner(fMembers, child, hasLine, false);
+ break;
+ default:
+ ;
}
- } while (!this->eof());
- fprintf(out, "%.*s", (int) (fEnd - start), start);
- fclose(out);
- SkDebugf("wrote %s\n", filename.c_str());
- return true;
+ }
+}
+
+void HackParser::addOneLiner(const Definition* defTable, const Definition* child, bool hasLine,
+ bool lfAfter) {
+ if (hasLine) {
+ return;
+ }
+ string oneLiner = this->searchTable(defTable, child);
+ if ("" == oneLiner) {
+ return;
+ }
+ const char* start = fChar;
+ const char* end = child->fContentStart;
+ fprintf(fOut, "%.*s", (int) (end - start), start);
+ fChar = end;
+ if (!lfAfter) {
+ fprintf(fOut, "\n");
+ }
+ fprintf(fOut, "#Line # %s ##", oneLiner.c_str());
+ if (lfAfter) {
+ fprintf(fOut, "\n");
+ }
}
bool BmhParser::hasEndToken() const {
@@ -1032,6 +1343,20 @@ TextParser::TextParser(const Definition* definition) :
definition->fLineCount) {
}
+string TextParser::ReportFilename(string file) {
+ string fullName;
+#ifdef SK_BUILD_FOR_WIN
+ TCHAR pathChars[MAX_PATH];
+ DWORD pathLen = GetCurrentDirectory(MAX_PATH, pathChars);
+ for (DWORD index = 0; index < pathLen; ++index) {
+ fullName += pathChars[index] == (char)pathChars[index] ? (char)pathChars[index] : '?';
+ }
+ fullName += '\\';
+#endif
+ fullName += file;
+ return fullName;
+}
+
void TextParser::reportError(const char* errorStr) const {
this->reportWarning(errorStr);
SkDebugf(""); // convenient place to set a breakpoint
@@ -1047,7 +1372,8 @@ void TextParser::reportWarning(const char* errorStr) const {
spaces -= lineLen;
lineLen = err.lineLength();
}
- SkDebugf("\n%s(%zd): error: %s\n", fFileName.c_str(), err.fLineCount, errorStr);
+ string fullName = this->ReportFilename(fFileName);
+ SkDebugf("\n%s(%zd): error: %s\n", fullName.c_str(), err.fLineCount, errorStr);
if (0 == lineLen) {
SkDebugf("[blank line]\n");
} else {
@@ -1185,6 +1511,18 @@ bool BmhParser::skipToDefinitionEnd(MarkType markType) {
return this->reportError<bool>("unbalanced stack");
}
+bool BmhParser::skipToString() {
+ this->skipSpace();
+ if (fMC != this->peek()) {
+ return this->reportError<bool>("expected end mark");
+ }
+ this->next();
+ this->skipSpace();
+ // body is text from here to double fMC
+ // no single fMC allowed, no linefeed allowed
+ return true;
+}
+
vector<string> BmhParser::topicName() {
vector<string> result;
this->skipWhiteSpace();
@@ -1236,7 +1574,6 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
this->skipNoName();
break;
case MarkType::kCode:
- case MarkType::kDeprecated:
case MarkType::kDescription:
case MarkType::kDoxygen:
case MarkType::kExperimental:
@@ -1250,19 +1587,25 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kTrack:
this->skipNoName();
break;
+ case MarkType::kLine:
+ this->skipToString();
+ break;
case MarkType::kAlias:
case MarkType::kAnchor:
case MarkType::kBug: // fixme: expect number
case MarkType::kDefine:
case MarkType::kDefinedBy:
+ case MarkType::kDeprecated:
case MarkType::kDuration:
- case MarkType::kError:
case MarkType::kFile:
case MarkType::kHeight:
+ case MarkType::kIllustration:
case MarkType::kImage:
+ case MarkType::kIn:
case MarkType::kLiteral:
case MarkType::kOutdent:
case MarkType::kPlatform:
+ case MarkType::kPopulate:
case MarkType::kReturn:
case MarkType::kSeeAlso:
case MarkType::kSet:
@@ -1343,10 +1686,14 @@ string BmhParser::uniqueName(const string& base, MarkType markType) {
int number = 2;
string numBuilder(builder);
do {
- for (const auto& iter : fParent->fChildren) {
+ for (auto& iter : fParent->fChildren) {
if (markType == iter->fMarkType) {
if (iter->fName == numBuilder) {
- fCloned = true;
+ if (iter->fDeprecated) {
+ iter->fClone = true;
+ } else {
+ fCloned = true;
+ }
numBuilder = builder + '_' + to_string(number);
goto tryNext;
}
@@ -1399,8 +1746,14 @@ tryNext: ;
}
if (MarkType::kMethod == markType) {
cloned->fCloned = true;
+ if (cloned->fDeprecated) {
+ cloned->fClone = true;
+ } else {
+ fCloned = true;
+ }
+ } else {
+ fCloned = true;
}
- fCloned = true;
numBuilder = builder + '_' + to_string(number);
} while (++number);
return numBuilder;
@@ -1549,19 +1902,6 @@ int main(int argc, char** const argv) {
SkCommandLineFlags::PrintUsage();
return 1;
}
- if (FLAGS_hack) {
- if (FLAGS_bmh.isEmpty()) {
- SkDebugf("-k or --hack requires -b\n");
- SkCommandLineFlags::PrintUsage();
- return 1;
- }
- HackParser hacker;
- if (!hacker.parseFile(FLAGS_bmh[0], ".bmh")) {
- SkDebugf("hack failed\n");
- return -1;
- }
- return 0;
- }
if ((FLAGS_include.isEmpty() || FLAGS_bmh.isEmpty()) && FLAGS_status.isEmpty() &&
FLAGS_populate) {
SkDebugf("-p requires -b -i or -a\n");
@@ -1591,6 +1931,9 @@ int main(int argc, char** const argv) {
}
bmhParser.reset();
if (!FLAGS_bmh.isEmpty()) {
+ if (FLAGS_tokens) {
+ IncludeParser::RemoveFile(FLAGS_bmh[0], FLAGS_include[0]);
+ }
if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh")) {
return -1;
}
@@ -1599,6 +1942,19 @@ int main(int argc, char** const argv) {
return -1;
}
}
+ if (FLAGS_hack) {
+ if (FLAGS_bmh.isEmpty()) {
+ SkDebugf("-k or --hack requires -b\n");
+ SkCommandLineFlags::PrintUsage();
+ return 1;
+ }
+ HackParser hacker(bmhParser);
+ if (!hacker.parseFile(FLAGS_bmh[0], ".bmh")) {
+ SkDebugf("hack failed\n");
+ return -1;
+ }
+ return 0;
+ }
if (FLAGS_selfcheck && !SelfCheck(bmhParser)) {
return -1;
}
diff --git a/chromium/third_party/skia/tools/bookmaker/bookmaker.h b/chromium/third_party/skia/tools/bookmaker/bookmaker.h
index 6752225d527..7bb743c9cb3 100644
--- a/chromium/third_party/skia/tools/bookmaker/bookmaker.h
+++ b/chromium/third_party/skia/tools/bookmaker/bookmaker.h
@@ -53,6 +53,7 @@ enum class KeyWord {
kElse,
kEndif,
kEnum,
+ kError,
kFloat,
kFriend,
kIf,
@@ -98,7 +99,6 @@ enum class MarkType {
kDuration,
kEnum,
kEnumClass,
- kError,
kExample,
kExperimental,
kExternal,
@@ -106,8 +106,11 @@ enum class MarkType {
kFormula,
kFunction,
kHeight,
+ kIllustration,
kImage,
+ kIn,
kLegend,
+ kLine,
kLink,
kList,
kLiteral, // don't lookup hyperlinks, do substitution, etc
@@ -118,6 +121,7 @@ enum class MarkType {
kOutdent,
kParam,
kPlatform,
+ kPopulate,
kPrivate,
kReturn,
kRoot,
@@ -387,6 +391,7 @@ public:
}
void reportError(const char* errorStr) const;
+ static string ReportFilename(string file);
void reportWarning(const char* errorStr) const;
template <typename T> T reportError(const char* errorStr) const {
@@ -763,6 +768,11 @@ public:
kSubtractFrom,
};
+ enum class Format {
+ kIncludeReturn,
+ kOmitReturn,
+ };
+
Definition() {}
Definition(const char* start, const char* end, int line, Definition* parent)
@@ -823,10 +833,23 @@ public:
bool crossCheck2(const Definition& includeToken) const;
bool crossCheck(const Definition& includeToken) const;
bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
+
+ const Definition* csParent() const {
+ Definition* test = fParent;
+ while (test) {
+ if (MarkType::kStruct == test->fMarkType || MarkType::kClass == test->fMarkType) {
+ return test;
+ }
+ test = test->fParent;
+ }
+ return nullptr;
+ }
+
bool exampleToScript(string* result, ExampleOptions ) const;
string extractText(TrimExtract trimExtract) const;
string fiddleName() const;
- string formatFunction() const;
+ const Definition* findClone(string match) const;
+ string formatFunction(Format format) const;
const Definition* hasChild(MarkType markType) const;
bool hasMatch(const string& name) const;
const Definition* hasParam(const string& ref) const;
@@ -844,6 +867,7 @@ public:
}
virtual bool isRoot() const { return false; }
+ bool isStructOrClass() const;
int length() const {
return (int) (fContentEnd - fContentStart);
@@ -870,6 +894,7 @@ public:
}
virtual RootDefinition* rootParent() { SkASSERT(0); return nullptr; }
+ virtual const RootDefinition* rootParent() const { SkASSERT(0); return nullptr; }
void setCanonicalFiddle();
void setParentIndex() {
@@ -878,6 +903,17 @@ public:
void setWrapper();
+ const Definition* topicParent() const {
+ Definition* test = fParent;
+ while (test) {
+ if (MarkType::kTopic == test->fMarkType) {
+ return test;
+ }
+ test = test->fParent;
+ }
+ return nullptr;
+ }
+
string fText; // if text is constructed instead of in a file, it's put here
const char* fStart = nullptr; // .. in original text file, or the start of fText
const char* fContentStart; // start past optional markup name
@@ -902,9 +938,11 @@ public:
Type fType = Type::kNone;
bool fClone = false;
bool fCloned = false;
+ bool fDeprecated = false;
bool fOperatorConst = false;
bool fPrivate = false;
bool fShort = false;
+ bool fToBeDeprecated = false;
bool fMemberStart = false;
bool fAnonymous = false;
mutable bool fVisited = false;
@@ -941,6 +979,7 @@ public:
const Definition* find(const string& ref, AllowParens ) const;
bool isRoot() const override { return true; }
RootDefinition* rootParent() override { return fRootParent; }
+ const RootDefinition* rootParent() const override { return fRootParent; }
void setRootParent(RootDefinition* rootParent) { fRootParent = rootParent; }
unordered_map<string, RootDefinition*> fBranches;
@@ -1159,10 +1198,11 @@ public:
};
enum class Resolvable {
- kNo, // neither resolved nor output
- kYes, // resolved, output
- kOut, // not resolved, but output
+ kNo, // neither resolved nor output
+ kYes, // resolved, output
+ kOut, // not resolved, but output
kLiteral, // output untouched (FIXME: is this really different from kOut?)
+ kClone, // resolved, output, with references to clones as well
};
enum class Exemplary {
@@ -1177,6 +1217,11 @@ public:
kColumnEnd,
};
+ enum class HasTag {
+ kNo,
+ kYes,
+ };
+
#define M(mt) (1LL << (int) MarkType::k##mt)
#define M_D M(Description)
#define M_CS M(Class) | M(Struct)
@@ -1190,6 +1235,7 @@ public:
#define R_Y Resolvable::kYes
#define R_N Resolvable::kNo
#define R_O Resolvable::kOut
+#define R_C Resolvable::kClone
#define E_Y Exemplary::kYes
#define E_N Exemplary::kNo
@@ -1207,7 +1253,7 @@ public:
, { "Code", nullptr, MarkType::kCode, R_O, E_N, M_CSST | M_E | M(Method) }
, { "", nullptr, MarkType::kColumn, R_Y, E_N, M(Row) }
, { "", nullptr, MarkType::kComment, R_N, E_N, 0 }
-, { "Const", &fConstMap, MarkType::kConst, R_Y, E_N, M_E | M_ST }
+, { "Const", &fConstMap, MarkType::kConst, R_Y, E_O, M_E | M_ST }
, { "Define", nullptr, MarkType::kDefine, R_O, E_N, M_ST }
, { "DefinedBy", nullptr, MarkType::kDefinedBy, R_N, E_N, M(Method) }
, { "Deprecated", nullptr, MarkType::kDeprecated, R_Y, E_N, 0 }
@@ -1216,32 +1262,38 @@ public:
, { "Duration", nullptr, MarkType::kDuration, R_N, E_N, M(Example) | M(NoExample) }
, { "Enum", &fEnumMap, MarkType::kEnum, R_Y, E_O, M_CSST | M(Root) }
, { "EnumClass", &fClassMap, MarkType::kEnumClass, R_Y, E_O, M_CSST | M(Root) }
-, { "Error", nullptr, MarkType::kError, R_N, E_N, M(Example) | M(NoExample) }
-, { "Example", nullptr, MarkType::kExample, R_O, E_N, M_CSST | M_E | M(Method) }
+, { "Example", nullptr, MarkType::kExample,
+ R_O, E_N, M_CSST | M_E | M(Method) | M(Const) }
, { "Experimental", nullptr, MarkType::kExperimental, R_Y, E_N, 0 }
, { "External", nullptr, MarkType::kExternal, R_Y, E_N, M(Root) }
, { "File", nullptr, MarkType::kFile, R_N, E_N, M(Track) }
, { "Formula", nullptr, MarkType::kFormula, R_O, E_N,
- M(Column) | M_ST | M(Member) | M(Method) | M_D }
+ M(Column) | M_E | M_ST | M(Member) | M(Method) | M_D }
, { "Function", nullptr, MarkType::kFunction, R_O, E_N, M(Example) | M(NoExample) }
, { "Height", nullptr, MarkType::kHeight, R_N, E_N, M(Example) | M(NoExample) }
+, { "Illustration", nullptr, MarkType::kIllustration, R_N, E_N, M(Subtopic) }
, { "Image", nullptr, MarkType::kImage, R_N, E_N, M(Example) | M(NoExample) }
+, { "In", nullptr, MarkType::kIn, R_N, E_N,
+ M_CSST | M_E | M(Method) | M(Typedef) }
, { "Legend", nullptr, MarkType::kLegend, R_Y, E_N, M(Table) }
+, { "Line", nullptr, MarkType::kLine, R_N, E_N,
+ M_CSST | M_E | M(Method) | M(Typedef) }
, { "", nullptr, MarkType::kLink, R_N, E_N, M(Anchor) }
, { "List", nullptr, MarkType::kList, R_Y, E_N, M(Method) | M_CSST | M_E | M_D }
, { "Literal", nullptr, MarkType::kLiteral, R_N, E_N, M(Code) }
, { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 }
-, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M(Class) | M(Struct) }
+, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M_CSST }
, { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST }
, { "NoExample", nullptr, MarkType::kNoExample, R_O, E_N, M_CSST | M_E | M(Method) }
, { "Outdent", nullptr, MarkType::kOutdent, R_N, E_N, M(Code) }
, { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) }
, { "Platform", nullptr, MarkType::kPlatform, R_N, E_N, M(Example) | M(NoExample) }
+, { "Populate", nullptr, MarkType::kPopulate, R_N, E_N, M(Subtopic) }
, { "Private", nullptr, MarkType::kPrivate, R_N, E_N, 0 }
, { "Return", nullptr, MarkType::kReturn, R_Y, E_N, M(Method) }
, { "", nullptr, MarkType::kRoot, R_Y, E_N, 0 }
, { "", nullptr, MarkType::kRow, R_Y, E_N, M(Table) | M(List) }
-, { "SeeAlso", nullptr, MarkType::kSeeAlso, R_Y, E_N,
+, { "SeeAlso", nullptr, MarkType::kSeeAlso, R_C, E_N,
M_CSST | M_E | M(Method) | M(Typedef) }
, { "Set", nullptr, MarkType::kSet, R_N, E_N, M(Example) | M(NoExample) }
, { "StdOut", nullptr, MarkType::kStdOut, R_N, E_N, M(Example) | M(NoExample) }
@@ -1250,7 +1302,7 @@ public:
, { "Subtopic", nullptr, MarkType::kSubtopic, R_Y, E_Y, M_CSST }
, { "Table", nullptr, MarkType::kTable, R_Y, E_N, M(Method) | M_CSST | M_E }
, { "Template", nullptr, MarkType::kTemplate, R_Y, E_N, 0 }
-, { "", nullptr, MarkType::kText, R_Y, E_N, 0 }
+, { "", nullptr, MarkType::kText, R_N, E_N, 0 }
, { "Time", nullptr, MarkType::kTime, R_Y, E_N, M(Track) }
, { "ToDo", nullptr, MarkType::kToDo, R_N, E_N, 0 }
, { "Topic", nullptr, MarkType::kTopic, R_Y, E_Y, M_CS | M(Root) | M(Topic) }
@@ -1278,7 +1330,8 @@ public:
~BmhParser() override {}
bool addDefinition(const char* defStart, bool hasEnd, MarkType markType,
- const vector<string>& typeNameBuilder);
+ const vector<string>& typeNameBuilder, HasTag hasTag);
+ bool checkEndMarker(MarkType markType, string name) const;
bool checkExamples() const;
bool checkParamReturn(const Definition* definition) const;
bool dumpExamples(const char* fiddleJsonFileName) const;
@@ -1288,7 +1341,7 @@ public:
int endHashCount() const;
bool endTableColumn(const char* end, const char* terminator);
- RootDefinition* findBmhObject(MarkType markType, const string& typeName) {
+ RootDefinition* findBmhObject(MarkType markType, const string& typeName) const {
auto map = fMaps[(int) markType].fBmh;
if (!map) {
return nullptr;
@@ -1297,6 +1350,7 @@ public:
}
bool findDefinitions();
+ Definition* findExample(string name) const;
MarkType getMarkType(MarkLookup lookup) const;
bool hasEndToken() const;
string memberName();
@@ -1331,6 +1385,7 @@ public:
bool skipNoName();
bool skipToDefinitionEnd(MarkType markType);
+ bool skipToString();
void spellCheck(const char* match, SkCommandLineFlags::StringArray report) const;
void spellStatus(const char* match, SkCommandLineFlags::StringArray report) const;
vector<string> topicName();
@@ -1409,7 +1464,6 @@ public:
, { nullptr, MarkType::kDuration }
, { &fIEnumMap, MarkType::kEnum }
, { &fIEnumMap, MarkType::kEnumClass }
- , { nullptr, MarkType::kError }
, { nullptr, MarkType::kExample }
, { nullptr, MarkType::kExperimental }
, { nullptr, MarkType::kExternal }
@@ -1417,9 +1471,12 @@ public:
, { nullptr, MarkType::kFormula }
, { nullptr, MarkType::kFunction }
, { nullptr, MarkType::kHeight }
- , { nullptr, MarkType::kImage }
- , { nullptr, MarkType::kLegend }
- , { nullptr, MarkType::kLink }
+ , { nullptr, MarkType::kIllustration }
+ , { nullptr, MarkType::kImage }
+ , { nullptr, MarkType::kIn }
+ , { nullptr, MarkType::kLegend }
+ , { nullptr, MarkType::kLine }
+ , { nullptr, MarkType::kLink }
, { nullptr, MarkType::kList }
, { nullptr, MarkType::kLiteral }
, { nullptr, MarkType::kMarkChar }
@@ -1429,6 +1486,7 @@ public:
, { nullptr, MarkType::kOutdent }
, { nullptr, MarkType::kParam }
, { nullptr, MarkType::kPlatform }
+ , { nullptr, MarkType::kPopulate }
, { nullptr, MarkType::kPrivate }
, { nullptr, MarkType::kReturn }
, { nullptr, MarkType::kRoot }
@@ -1475,7 +1533,7 @@ public:
IClassDefinition* defineClass(const Definition& includeDef, const string& className);
void dumpClassTokens(IClassDefinition& classDef);
void dumpComment(const Definition& );
- void dumpEnum(const Definition& );
+ void dumpEnum(const Definition& , const string& name);
void dumpMethod(const Definition& );
void dumpMember(const Definition& );
bool dumpTokens(const string& directory);
@@ -1523,7 +1581,7 @@ public:
return false;
}
string name(path);
- return parseInclude(name);
+ return this->parseInclude(name);
}
bool parseInclude(const string& name);
@@ -1549,6 +1607,9 @@ public:
this->addDefinition(container);
}
+ static void RemoveFile(const char* docs, const char* includes);
+ static void RemoveOneFile(const char* docs, const char* includesFileOrPath);
+
void reset() override {
INHERITED::resetCommon();
fRootTopic = nullptr;
@@ -1679,6 +1740,14 @@ public:
this->lf(1);
}
+ void writeTableRow(size_t pad1, const string& col1, size_t pad2, const string& col2) {
+ this->lf(1);
+ string row = "# " + col1 + string(pad1 - col1.length(), ' ') + " # " +
+ col2 + string(pad2 - col2.length(), ' ') + " ##";
+ this->writeString(row);
+ this->lf(1);
+ }
+
void writeTableTrailer() {
this->lf(1);
this->writeString("#Table ##");
@@ -1765,6 +1834,7 @@ public:
enum class PunctuationState {
kStart,
kDelimiter,
+ kParen, // treated as a delimiter unless following a space, and followed by word
kPeriod,
kSpace,
};
@@ -1775,6 +1845,11 @@ public:
kExternal,
};
+ enum class SkipFirstLine {
+ kNo,
+ kYes,
+ };
+
enum class Wrote {
kNone,
kLF,
@@ -1812,10 +1887,13 @@ public:
return 0 == size;
}
- void descriptionOut(const Definition* def);
+ void constOut(const Definition* memberStart, const Definition& child,
+ const Definition* bmhConst);
+ void descriptionOut(const Definition* def, SkipFirstLine );
void enumHeaderOut(const RootDefinition* root, const Definition& child);
void enumMembersOut(const RootDefinition* root, Definition& child);
void enumSizeItems(const Definition& child);
+ Definition* findMemberCommentBlock(const vector<Definition*>& bmhChildren, const string& name) const;
int lookupMethod(const PunctuationState punctuation, const Word word,
const int start, const int run, int lastWrite,
const char* data, bool hasIndirection);
@@ -1846,6 +1924,7 @@ public:
Definition* structMemberOut(const Definition* memberStart, const Definition& child);
void structOut(const Definition* root, const Definition& child,
const char* commentStart, const char* commentEnd);
+ void structSetMembersShort(const vector<Definition*>& bmhChildren);
void structSizeMembers(const Definition& child);
private:
BmhParser* fBmhParser;
@@ -1886,7 +1965,7 @@ protected:
INHERITED::resetCommon();
}
- Definition* findExample(const string& name) const;
+ Definition* findExample(string name) const { return fBmhParser->findExample(name); }
bool parseFiddles();
virtual bool pngOut(Definition* example) = 0;
virtual bool textOut(Definition* example, const char* stdOutStart,
@@ -1947,10 +2026,15 @@ private:
class HackParser : public ParserCommon {
public:
- HackParser() : ParserCommon() {
+ HackParser(const BmhParser& bmhParser)
+ : ParserCommon()
+ , fBmhParser(bmhParser) {
this->reset();
}
+ void addOneLiner(const Definition* defTable, const Definition* child, bool hasLine,
+ bool lfAfter);
+
bool parseFromFile(const char* path) override {
if (!INHERITED::parseSetup(path)) {
return false;
@@ -1962,7 +2046,19 @@ public:
INHERITED::resetCommon();
}
+ string searchTable(const Definition* tableHolder, const Definition* match);
+
+ void topicIter(const Definition* );
+
private:
+ const BmhParser& fBmhParser;
+ const Definition* fClassesAndStructs;
+ const Definition* fConstants;
+ const Definition* fConstructors;
+ const Definition* fMemberFunctions;
+ const Definition* fMembers;
+ const Definition* fOperators;
+ const Definition* fRelatedFunctions;
bool hackFiles();
typedef ParserCommon INHERITED;
@@ -1977,6 +2073,17 @@ public:
bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
bool buildStatus(const char* docDir, const char* mdOutDir);
+
+ static constexpr const char* kClassesAndStructs = "Class_or_Struct";
+ static constexpr const char* kConstants = "Constant";
+ static constexpr const char* kConstructors = "Constructor";
+ static constexpr const char* kMemberFunctions = "Member_Function";
+ static constexpr const char* kMembers = "Member";
+ static constexpr const char* kOperators = "Operator";
+ static constexpr const char* kOverview = "Overview";
+ static constexpr const char* kRelatedFunctions = "Related_Function";
+ static constexpr const char* kSubtopics = "Overview_Subtopic";
+
private:
enum class TableState {
kNone,
@@ -1984,19 +2091,38 @@ private:
kColumn,
};
+ struct TableContents {
+ TableContents()
+ : fShowClones(false) {
+ }
+
+ string fDescription;
+ vector<const Definition*> fMembers;
+ bool fShowClones;
+ };
+
string addReferences(const char* start, const char* end, BmhParser::Resolvable );
bool buildRefFromFile(const char* fileName, const char* outDir);
bool checkParamReturnBody(const Definition* def) const;
void childrenOut(const Definition* def, const char* contentStart);
+ const Definition* csParent() const;
const Definition* findParamType();
const Definition* isDefined(const TextParser& parser, const string& ref, bool report) const;
string linkName(const Definition* ) const;
- string linkRef(const string& leadingSpaces, const Definition*, const string& ref) const;
+ string linkRef(const string& leadingSpaces, const Definition*, const string& ref,
+ BmhParser::Resolvable ) const;
void markTypeOut(Definition* );
void mdHeaderOut(int depth) { mdHeaderOutLF(depth, 2); }
void mdHeaderOutLF(int depth, int lf);
- bool parseFromFile(const char* path) override {
- return true;
+ void overviewOut();
+ bool parseFromFile(const char* path) override { return true; }
+ void populateTables(const Definition* def);
+
+ TableContents& populator(const char* key) {
+ auto entry = fPopulators.find(key);
+ // FIXME: this should have been detected earlier
+ SkASSERT(fPopulators.end() != entry);
+ return entry->second;
}
void reset() override {
@@ -2029,11 +2155,17 @@ private:
}
void resolveOut(const char* start, const char* end, BmhParser::Resolvable );
+ void rowOut(const char * name, const string& description);
+ void subtopicOut(const TableContents& tableContents);
+ void subtopicsOut();
+
+ unordered_map<string, TableContents> fPopulators;
+ vector<const Definition*> fClassStack;
const BmhParser& fBmhParser;
const Definition* fEnumClass;
Definition* fMethod;
- RootDefinition* fRoot;
+ const RootDefinition* fRoot;
const Definition* fLastParam;
TableState fTableState;
bool fHasFiddle;
diff --git a/chromium/third_party/skia/tools/bookmaker/definition.cpp b/chromium/third_party/skia/tools/bookmaker/definition.cpp
index 74f4d5a7fb0..68e001aebb6 100644
--- a/chromium/third_party/skia/tools/bookmaker/definition.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/definition.cpp
@@ -533,9 +533,6 @@ bool Definition::exampleToScript(string* result, ExampleOptions exampleOptions)
case MarkType::kDuration:
durationStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
break;
- case MarkType::kError:
- result->clear();
- return true;
case MarkType::kHeight:
heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
break;
@@ -563,6 +560,7 @@ bool Definition::exampleToScript(string* result, ExampleOptions exampleOptions)
break;
case MarkType::kToDo:
break;
+ case MarkType::kBug:
case MarkType::kMarkChar:
case MarkType::kPlatform:
// ignore for now
@@ -899,7 +897,7 @@ bool Definition::crossCheckInside(const char* start, const char* end,
return false;
}
-string Definition::formatFunction() const {
+string Definition::formatFunction(Format format) const {
const char* end = fContentStart;
while (end > fStart && ' ' >= end[-1]) {
--end;
@@ -915,6 +913,9 @@ string Definition::formatFunction() const {
const char* nameInParser = methodParser.strnstr(name.c_str(), methodParser.fEnd);
methodParser.skipTo(nameInParser);
const char* lastEnd = methodParser.fChar;
+ if (Format::kOmitReturn == format) {
+ lastStart = lastEnd;
+ }
const char* paren = methodParser.strnchr('(', methodParser.fEnd);
size_t indent;
if (paren) {
@@ -985,8 +986,10 @@ string Definition::formatFunction() const {
if (delimiter) {
if (nextEnd - nextStart >= (ptrdiff_t) (limit - written)) {
written = indent;
- methodStr += '\n';
- methodStr += string(indent, ' ');
+ if (Format::kIncludeReturn == format) {
+ methodStr += '\n';
+ methodStr += string(indent, ' ');
+ }
}
methodParser.skipTo(delimiter);
}
@@ -1017,6 +1020,22 @@ string Definition::fiddleName() const {
return fFiddle.substr(start, end - start);
}
+const Definition* Definition::findClone(string match) const {
+ for (auto child : fChildren) {
+ if (!child->fClone) {
+ continue;
+ }
+ if (match == child->fName) {
+ return child;
+ }
+ auto inner = child->findClone(match);
+ if (inner) {
+ return inner;
+ }
+ }
+ return nullptr;
+}
+
const Definition* Definition::hasChild(MarkType markType) const {
for (auto iter : fChildren) {
if (markType == iter->fMarkType) {
@@ -1052,6 +1071,16 @@ bool Definition::hasMatch(const string& name) const {
return false;
}
+bool Definition::isStructOrClass() const {
+ if (MarkType::kStruct != fMarkType && MarkType::kClass != fMarkType) {
+ return false;
+ }
+ if (string::npos != fFileName.find("undocumented.bmh")) {
+ return false;
+ }
+ return true;
+}
+
bool Definition::methodHasReturn(const string& name, TextParser* methodParser) const {
if (methodParser->skipExact("static")) {
methodParser->skipWhiteSpace();
@@ -1190,7 +1219,73 @@ string Definition::NormalizedName(string name) {
return normalizedName;
}
-bool Definition::paramsMatch(const string& match, const string& name) const {
+static string unpreformat(const string& orig) {
+ string result;
+ int amp = 0;
+ for (auto c : orig) {
+ switch (amp) {
+ case 0:
+ if ('&' == c) {
+ amp = 1;
+ } else {
+ amp = 0;
+ result += c;
+ }
+ break;
+ case 1:
+ if ('l' == c) {
+ amp = 2;
+ } else if ('g' == c) {
+ amp = 3;
+ } else {
+ amp = 0;
+ result += "&";
+ result += c;
+ }
+ break;
+ case 2:
+ if ('t' == c) {
+ amp = 4;
+ } else {
+ amp = 0;
+ result += "&l";
+ result += c;
+ }
+ break;
+ case 3:
+ if ('t' == c) {
+ amp = 5;
+ } else {
+ amp = 0;
+ result += "&g";
+ result += c;
+ }
+ break;
+ case 4:
+ if (';' == c) {
+ result += '<';
+ } else {
+ result += "&lt";
+ result += c;
+ }
+ amp = 0;
+ break;
+ case 5:
+ if (';' == c) {
+ result += '>';
+ } else {
+ result += "&gt";
+ result += c;
+ }
+ amp = 0;
+ break;
+ }
+ }
+ return result;
+}
+
+bool Definition::paramsMatch(const string& matchFormatted, const string& name) const {
+ string match = unpreformat(matchFormatted);
TextParser def(fFileName, fStart, fContentStart, fLineCount);
const char* dName = def.strnstr(name.c_str(), fContentStart);
if (!dName) {
diff --git a/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp b/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
index faf551006f7..682c87c845b 100644
--- a/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
@@ -7,32 +7,6 @@
#include "bookmaker.h"
-static Definition* find_fiddle(Definition* def, const string& name) {
- if (MarkType::kExample == def->fMarkType && name == def->fFiddle) {
- return def;
- }
- for (auto& child : def->fChildren) {
- Definition* result = find_fiddle(child, name);
- if (result) {
- return result;
- }
- }
- return nullptr;
-}
-
-Definition* FiddleBase::findExample(const string& name) const {
- for (const auto& topic : fBmhParser->fTopicMap) {
- if (topic.second->fParent) {
- continue;
- }
- Definition* def = find_fiddle(topic.second, name);
- if (def) {
- return def;
- }
- }
- return nullptr;
-}
-
bool FiddleBase::parseFiddles() {
if (!this->skipExact("{\n")) {
return false;
diff --git a/chromium/third_party/skia/tools/bookmaker/includeParser.cpp b/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
index 26281b61845..385b9c92da7 100644
--- a/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
@@ -6,6 +6,8 @@
*/
#include "bookmaker.h"
+#include "SkOSFile.h"
+#include "SkOSPath.h"
const IncludeKey kKeyWords[] = {
{ "", KeyWord::kNone, KeyProperty::kNone },
@@ -22,6 +24,7 @@ const IncludeKey kKeyWords[] = {
{ "else", KeyWord::kElse, KeyProperty::kPreprocessor },
{ "endif", KeyWord::kEndif, KeyProperty::kPreprocessor },
{ "enum", KeyWord::kEnum, KeyProperty::kObject },
+ { "error", KeyWord::kError, KeyProperty::kPreprocessor },
{ "float", KeyWord::kFloat, KeyProperty::kNumber },
{ "friend", KeyWord::kFriend, KeyProperty::kModifier },
{ "if", KeyWord::kIf, KeyProperty::kPreprocessor },
@@ -156,6 +159,7 @@ bool IncludeParser::checkForWord() {
// these do not link to other # directives
case KeyWord::kDefine:
case KeyWord::kInclude:
+ case KeyWord::kError:
break;
// these start a # directive link
case KeyWord::kIf:
@@ -338,8 +342,10 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
def = root->find(withParens, RootDefinition::AllowParens::kNo);
}
if (!def) {
- SkDebugf("method missing from bmh: %s\n", fullName.c_str());
- fFailed = true;
+ if (!root->fDeprecated) {
+ SkDebugf("method missing from bmh: %s\n", fullName.c_str());
+ fFailed = true;
+ }
break;
}
if (def->crossCheck2(token)) {
@@ -385,8 +391,10 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
def = root->find(anonName, RootDefinition::AllowParens::kYes);
}
if (!def) {
- SkDebugf("enum missing from bmh: %s\n", fullName.c_str());
- fFailed = true;
+ if (!root->fDeprecated) {
+ SkDebugf("enum missing from bmh: %s\n", fullName.c_str());
+ fFailed = true;
+ }
break;
}
}
@@ -398,8 +406,10 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
}
if (MarkType::kCode != def->fMarkType) {
- SkDebugf("enum code missing from bmh: %s\n", fullName.c_str());
- fFailed = true;
+ if (!root->fDeprecated) {
+ SkDebugf("enum code missing from bmh: %s\n", fullName.c_str());
+ fFailed = true;
+ }
break;
}
if (def->crossCheck(token)) {
@@ -419,8 +429,10 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
if (!def) {
if (string::npos == child->fName.find("Legacy_")) {
- SkDebugf("const missing from bmh: %s\n", constName.c_str());
- fFailed = true;
+ if (!root->fDeprecated) {
+ SkDebugf("const missing from bmh: %s\n", constName.c_str());
+ fFailed = true;
+ }
}
} else {
def->fVisited = true;
@@ -430,7 +442,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
case MarkType::kMember:
if (def) {
def->fVisited = true;
- } else {
+ } else if (!root->fDeprecated) {
SkDebugf("member missing from bmh: %s\n", fullName.c_str());
fFailed = true;
}
@@ -438,7 +450,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
case MarkType::kTypedef:
if (def) {
def->fVisited = true;
- } else {
+ } else if (!root->fDeprecated) {
SkDebugf("typedef missing from bmh: %s\n", fullName.c_str());
fFailed = true;
}
@@ -471,7 +483,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
if (crossChecks) {
if (1 == crossChecks) {
- SkDebugf("%s", firstCheck.c_str());
+ SkDebugf(" %s", firstCheck.c_str());
}
SkDebugf("\n");
}
@@ -527,7 +539,7 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
switch (token.fMarkType) {
case MarkType::kEnum:
case MarkType::kEnumClass:
- this->dumpEnum(token);
+ this->dumpEnum(token, token.fName);
break;
case MarkType::kMethod:
this->dumpMethod(token);
@@ -582,8 +594,9 @@ void IncludeParser::dumpComment(const Definition& token) {
Definition methodName;
TextParser methodParser(token.fFileName, token.fContentStart, token.fContentEnd,
token.fLineCount);
+ bool debugCode = methodParser.skipExact("SkDEBUGCODE(");
if (MarkType::kMethod == token.fMarkType) {
- methodName.fName = string(token.fContentStart,
+ methodName.fName = debugCode ? token.fName : string(token.fContentStart,
(int) (token.fContentEnd - token.fContentStart));
methodHasReturn = !methodParser.startsWith("void ")
&& !methodParser.startsWith("static void ")
@@ -731,8 +744,8 @@ void IncludeParser::dumpComment(const Definition& token) {
}
}
-void IncludeParser::dumpEnum(const Definition& token) {
- this->writeTag("Enum", token.fName);
+void IncludeParser::dumpEnum(const Definition& token, const string& name) {
+ this->writeTag("Enum", name);
this->lf(2);
this->writeString("#Code");
this->lfAlways(1);
@@ -896,40 +909,29 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
}
this->lf(2);
string className(skClassName.substr(2));
- vector<string> sortedClasses;
- size_t maxLen = 0;
+ vector<string> classNames;
+ vector<string> constNames;
+ vector<string> constructorNames;
+ vector<string> memberNames;
+ vector<string> operatorNames;
+ size_t classMaxLen = 0;
+ size_t constMaxLen = 0;
+ size_t constructorMaxLen = 0;
+ size_t memberMaxLen = 0;
+ size_t operatorMaxLen = 0;
for (const auto& oneClass : fIClassMap) {
if (skClassName + "::" != oneClass.first.substr(0, skClassName.length() + 2)) {
continue;
}
string structName = oneClass.first.substr(skClassName.length() + 2);
- maxLen = SkTMax(maxLen, structName.length());
- sortedClasses.emplace_back(structName);
+ classMaxLen = SkTMax(classMaxLen, structName.length());
+ classNames.emplace_back(structName);
}
- this->writeTag("Topic", "Overview");
- this->lf(2);
- this->writeTag("Subtopic", "Subtopics");
- this->writeEndTag("ToDo", "manually add subtopics");
- this->writeTableHeader("topics", 0, "description");
- this->writeTableTrailer();
- this->writeEndTag();
- this->lf(2);
- if (maxLen) {
- this->writeTag("Subtopic", "Structs");
- this->writeTableHeader("description", maxLen, "struct");
- for (auto& name : sortedClasses) {
- this->writeTableRow(maxLen, name);
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
- this->lf(2);
+ for (const auto& oneEnum : fIEnumMap) {
+ string enumName = oneEnum.first;
+ constMaxLen = SkTMax(constMaxLen, enumName.length());
+ constNames.emplace_back(enumName);
}
- maxLen = 0;
- size_t constructorMax = 0;
- size_t operatorMax = 0;
- vector<string> sortedNames;
- vector<string> constructorNames;
- vector<string> operatorNames;
for (const auto& token : classMap.fTokens) {
if (Definition::Type::kMark != token.fType || MarkType::kMethod != token.fMarkType) {
continue;
@@ -940,13 +942,13 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
}
if ((name.substr(0, 2) == "Sk" && 2 == name.find(className)) || '~' == name[0]) {
name = string(token.fContentStart, (int) (token.fContentEnd - token.fContentStart));
- constructorMax = SkTMax(constructorMax, name.length());
+ constructorMaxLen = SkTMax(constructorMaxLen, name.length());
constructorNames.emplace_back(name);
continue;
}
if (name.substr(0, 8) == "operator") {
name = string(token.fContentStart, (int) (token.fContentEnd - token.fContentStart));
- operatorMax = SkTMax(operatorMax, name.length());
+ operatorMaxLen = SkTMax(operatorMaxLen, name.length());
operatorNames.emplace_back(name);
continue;
}
@@ -958,45 +960,119 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
}
size_t paren = name.find('(');
size_t funcLen = string::npos == paren ? name.length() : paren;
- maxLen = SkTMax(maxLen, funcLen);
- sortedNames.emplace_back(name);
+ memberMaxLen = SkTMax(memberMaxLen, funcLen);
+ memberNames.emplace_back(name);
+ }
+ this->writeTag("Topic", "Overview");
+ this->lf(2);
+ this->writeTag("Subtopic", "Subtopics");
+ string classesName = classMaxLen ? "Classes_and_Structs" : "";
+ string constsName = constructorMaxLen ? "Constants" : "";
+ string constructorsName = constructorMaxLen ? "Constructors" : "";
+ string membersName = memberMaxLen ? "Member_Functions" : "";
+ string operatorsName = operatorMaxLen ? "Operators" : "";
+ size_t nameLen = SkTMax(classesName.size(), SkTMax(constsName.size(),
+ SkTMax(constructorsName.size(), SkTMax(membersName.size(), operatorsName.size()))));
+ this->writeTableHeader("name", nameLen, "description");
+ string classDesc = classMaxLen ? "embedded struct and class members" : "";
+ string constDesc = constMaxLen ? "enum and enum class, const values" : "";
+ string constructorDesc = constructorMaxLen ? "functions that construct " + className : "";
+ string memberDesc = memberMaxLen ? "static functions and member methods" : "";
+ string operatorDesc = operatorMaxLen ? "operator overloading methods" : "";
+ size_t descLen = SkTMax(classDesc.size(), SkTMax(constDesc.size(), SkTMax(constructorDesc.size(),
+ SkTMax(memberDesc.size(), operatorDesc.size()))));
+ if (classMaxLen) {
+ this->writeTableRow(nameLen, classesName, descLen, classDesc);
+ }
+ if (constMaxLen) {
+ this->writeTableRow(nameLen, constsName, descLen, constDesc);
+ }
+ if (constructorMaxLen) {
+ this->writeTableRow(nameLen, constructorsName, descLen, constructorDesc);
+ }
+ if (memberMaxLen) {
+ this->writeTableRow(nameLen, membersName, descLen, memberDesc);
+ }
+ if (operatorMaxLen) {
+ this->writeTableRow(nameLen, operatorsName, descLen, operatorDesc);
+ }
+ this->writeTableTrailer();
+ this->writeEndTag();
+ this->lf(2);
+ if (classMaxLen) {
+ std::sort(classNames.begin(), classNames.end());
+ this->writeTag("Subtopic", "Classes_and_Structs");
+ this->writeTableHeader("name", classMaxLen, "description");
+ for (auto& name : classNames) {
+ this->writeTableRow(classMaxLen, name);
+ }
+ this->writeTableTrailer();
+ this->writeEndTag("Subtopic");
+ this->lf(2);
+ }
+ if (constMaxLen) {
+ std::sort(constNames.begin(), constNames.end());
+ this->writeTag("Subtopic", "Constants");
+ this->writeTableHeader("name", constMaxLen, "description");
+ for (auto& name : constNames) {
+ this->writeTableRow(constMaxLen, name);
+ }
+ this->writeTableTrailer();
+ this->writeEndTag("Subtopic");
+ this->lf(2);
}
- if (constructorMax) {
+ if (constructorMaxLen) {
std::sort(constructorNames.begin(), constructorNames.end());
this->writeTag("Subtopic", "Constructors");
- this->writeTableHeader("description", constructorMax, "function");
+ this->writeTableHeader("name", constructorMaxLen, "description");
for (auto& name : constructorNames) {
- this->writeTableRow(constructorMax, name);
+ this->writeTableRow(constructorMaxLen, name);
}
this->writeTableTrailer();
this->writeEndTag("Subtopic");
this->lf(2);
}
- if (operatorMax) {
+ if (operatorMaxLen) {
std::sort(operatorNames.begin(), operatorNames.end());
this->writeTag("Subtopic", "Operators");
- this->writeTableHeader("description", operatorMax, "function");
+ this->writeTableHeader("name", operatorMaxLen, "description");
for (auto& name : operatorNames) {
- this->writeTableRow(operatorMax, name);
+ this->writeTableRow(operatorMaxLen, name);
}
this->writeTableTrailer();
this->writeEndTag("Subtopic");
this->lf(2);
}
- std::sort(sortedNames.begin(), sortedNames.end());
- this->writeTag("Subtopic", "Member_Functions");
- this->writeTableHeader("description", maxLen, "function");
- for (auto& name : sortedNames) {
- size_t paren = name.find('(');
- size_t funcLen = string::npos == paren ? name.length() : paren;
- this->writeTableRow(maxLen, name.substr(0, funcLen));
+ if (memberMaxLen) {
+ std::sort(memberNames.begin(), memberNames.end());
+ this->writeTag("Subtopic", "Member_Functions");
+ this->writeTableHeader("name", memberMaxLen, "description");
+ for (auto& name : memberNames) {
+ size_t paren = name.find('(');
+ size_t funcLen = string::npos == paren ? name.length() : paren;
+ this->writeTableRow(memberMaxLen, name.substr(0, funcLen));
+ }
+ this->writeTableTrailer();
+ this->writeEndTag("Subtopic");
+ this->lf(2);
}
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
- this->lf(2);
this->writeEndTag("Topic");
this->lf(2);
-
+ for (auto& oneEnum : fIEnumMap) {
+ this->writeString(
+ "# ------------------------------------------------------------------------------");
+ this->dumpEnum(oneEnum.second, oneEnum.first);
+ this->lf(2);
+ this->writeTag("Example");
+ this->lfcr();
+ this->writeString("// incomplete");
+ this->writeEndTag();
+ this->lf(2);
+ this->writeTag("SeeAlso", "incomplete");
+ this->lf(2);
+ this->writeEndTag("Enum", oneEnum.first);
+ this->lf(2);
+ }
for (auto& oneClass : fIClassMap) {
if (skClassName + "::" != oneClass.first.substr(0, skClassName.length() + 2)) {
continue;
@@ -1231,7 +1307,13 @@ bool IncludeParser::parseDefine() {
}
bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
- string nameStr;
+ TextParser parser(child);
+ parser.skipToEndBracket('{');
+ if (parser.eof()) {
+ return true; // if enum is a forward declaration, do nothing
+ }
+ parser.next();
+ string nameStr;
if (child->fTokens.size() > 0) {
auto token = child->fTokens.begin();
if (Definition::Type::kKeyWord == token->fType && KeyWord::kClass == token->fKeyWord) {
@@ -1241,26 +1323,42 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
nameStr += string(token->fStart, token->fContentEnd - token->fStart);
}
}
- markupDef->fTokens.emplace_back(MarkType::kEnum, child->fContentStart, child->fContentEnd,
- child->fLineCount, markupDef);
- Definition* markupChild = &markupDef->fTokens.back();
+ Definition* markupChild;
+ if (!markupDef) {
+ auto finder = fIEnumMap.find(nameStr);
+ if (fIEnumMap.end() != finder) {
+ return child->reportError<bool>("duplicate global enum name");
+ }
+ markupChild = &fIEnumMap[nameStr];
+ markupChild->fContentStart = child->fContentStart;
+ markupChild->fName = nameStr;
+ markupChild->fFiddle = nameStr;
+ markupChild->fContentEnd = child->fContentEnd;
+ markupChild->fFileName = child->fFileName;
+ markupChild->fLineCount = child->fLineCount;
+ } else {
+ markupDef->fTokens.emplace_back(MarkType::kEnum, child->fContentStart, child->fContentEnd,
+ child->fLineCount, markupDef);
+ markupChild = &markupDef->fTokens.back();
+ }
SkASSERT(KeyWord::kNone == markupChild->fKeyWord);
markupChild->fKeyWord = KeyWord::kEnum;
TextParser enumName(child);
enumName.skipExact("enum ");
+ enumName.skipWhiteSpace();
if (enumName.skipExact("class ")) {
+ enumName.skipWhiteSpace();
markupChild->fMarkType = MarkType::kEnumClass;
}
const char* nameStart = enumName.fChar;
enumName.skipToSpace();
- markupChild->fName = markupDef->fName + "::" +
- string(nameStart, (size_t) (enumName.fChar - nameStart));
+ if (markupDef) {
+ markupChild->fName = markupDef->fName + "::";
+ }
+ markupChild->fName += string(nameStart, (size_t) (enumName.fChar - nameStart));
if (!this->findComments(*child, markupChild)) {
return false;
}
- TextParser parser(child);
- parser.skipToEndBracket('{');
- parser.next();
const char* dataEnd;
do {
parser.skipWhiteSpace();
@@ -1311,6 +1409,10 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
if ('=' == parser.peek()) {
parser.skipToEndBracket(',');
}
+ if (!parser.eof() && '#' == parser.peek()) {
+ // fixme: handle preprecessor, but just skip it for now
+ continue;
+ }
if (parser.eof() || ',' != parser.peek()) {
return this->reportError<bool>("enum member must end with comma 2");
}
@@ -1367,11 +1469,13 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
// FIXME: ? add comment as well ?
markupChild->fChildren.push_back(member);
}
- IClassDefinition& classDef = fIClassMap[markupDef->fName];
- SkASSERT(classDef.fStart);
- string uniqueName = this->uniqueName(classDef.fEnums, nameStr);
- markupChild->fName = uniqueName;
- classDef.fEnums[uniqueName] = markupChild;
+ if (markupDef) {
+ IClassDefinition& classDef = fIClassMap[markupDef->fName];
+ SkASSERT(classDef.fStart);
+ string uniqueName = this->uniqueName(classDef.fEnums, nameStr);
+ markupChild->fName = uniqueName;
+ classDef.fEnums[uniqueName] = markupChild;
+ }
return true;
}
@@ -1697,6 +1801,7 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
if (child->boilerplateEndIf()) {
break;
}
+ case KeyWord::kError:
case KeyWord::kInclude:
// ignored for now
break;
@@ -1809,7 +1914,7 @@ bool IncludeParser::parseChar() {
if (KeyWord::kNone == keyWord) {
return this->reportError<bool>("unhandled preprocessor directive");
}
- if (KeyWord::kInclude == keyWord || KeyWord::kDefine == keyWord) {
+ if (KeyWord::kInclude == keyWord || KeyWord::kDefine == keyWord || KeyWord::kError == keyWord) {
this->popBracket();
}
} else if (Bracket::kSlashSlash == this->topBracket()) {
@@ -2218,3 +2323,36 @@ void IncludeParser::validate() const {
}
IncludeParser::ValidateKeyWords();
}
+
+void IncludeParser::RemoveFile(const char* docs, const char* includes) {
+ if (!sk_isdir(includes)) {
+ IncludeParser::RemoveOneFile(docs, includes);
+ } else {
+ SkOSFile::Iter it(includes, ".h");
+ for (SkString file; it.next(&file); ) {
+ SkString p = SkOSPath::Join(includes, file.c_str());
+ const char* hunk = p.c_str();
+ if (!SkStrEndsWith(hunk, ".h")) {
+ continue;
+ }
+ IncludeParser::RemoveOneFile(docs, hunk);
+ }
+ }
+}
+
+void IncludeParser::RemoveOneFile(const char* docs, const char* includesFile) {
+ const char* lastForward = strrchr(includesFile, '/');
+ const char* lastBackward = strrchr(includesFile, '\\');
+ const char* last = lastForward > lastBackward ? lastForward : lastBackward;
+ if (!last) {
+ last = includesFile;
+ } else {
+ last += 1;
+ }
+ SkString baseName(last);
+ SkASSERT(baseName.endsWith(".h"));
+ baseName.remove(baseName.size() - 2, 2);
+ baseName.append("_Reference.bmh");
+ SkString fullName = SkOSPath::Join(docs, baseName.c_str());
+ remove(fullName.c_str());
+}
diff --git a/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp b/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
index 230e524703e..328e9412cbc 100644
--- a/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
@@ -7,11 +7,34 @@
#include "bookmaker.h"
-void IncludeWriter::descriptionOut(const Definition* def) {
+void IncludeWriter::constOut(const Definition* memberStart, const Definition& child,
+ const Definition* bmhConst) {
+ const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
+ memberStart->fContentStart;
+ this->writeBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
+ this->lf(2);
+ this->writeCommentHeader();
+ fIndent += 4;
+ this->descriptionOut(bmhConst, SkipFirstLine::kYes);
+ fIndent -= 4;
+ this->writeCommentTrailer();
+ fStart = memberStart->fContentStart;
+}
+
+void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine) {
const char* commentStart = def->fContentStart;
+ if (SkipFirstLine::kYes == skipFirstLine) {
+ TextParser parser(def);
+ SkAssertResult(parser.skipLine());
+ commentStart = parser.fChar;
+ }
int commentLen = (int) (def->fContentEnd - commentStart);
bool breakOut = false;
SkDEBUGCODE(bool wroteCode = false);
+ if (def->fDeprecated) {
+ this->writeString(def->fToBeDeprecated ? "To be deprecated soon." : "Deprecated.");
+ this->lfcr();
+ }
for (auto prop : def->fChildren) {
switch (prop->fMarkType) {
case MarkType::kCode: {
@@ -52,6 +75,12 @@ void IncludeWriter::descriptionOut(const Definition* def) {
case MarkType::kDefinedBy:
commentStart = prop->fTerminator;
break;
+ case MarkType::kBug: {
+ string bugstr("(see skbug.com/" + string(prop->fContentStart,
+ prop->fContentEnd - prop->fContentStart) + ')');
+ this->writeString(bugstr);
+ this->lfcr();
+ }
case MarkType::kDeprecated:
case MarkType::kPrivate:
commentLen = (int) (prop->fStart - commentStart);
@@ -62,6 +91,11 @@ void IncludeWriter::descriptionOut(const Definition* def) {
}
}
commentStart = prop->fContentStart;
+ if (def->fToBeDeprecated) {
+ commentStart += 4; // skip over "soon" // FIXME: this is awkward
+ } else if (MarkType::kBug == prop->fMarkType) {
+ commentStart = prop->fContentEnd;
+ }
commentLen = (int) (prop->fContentEnd - commentStart);
if (commentLen > 0) {
this->writeBlockIndent(commentLen, commentStart);
@@ -114,6 +148,8 @@ void IncludeWriter::descriptionOut(const Definition* def) {
}
}
} break;
+ case MarkType::kIn:
+ case MarkType::kLine:
case MarkType::kToDo:
commentLen = (int) (prop->fStart - commentStart);
if (commentLen > 0) {
@@ -139,7 +175,7 @@ void IncludeWriter::descriptionOut(const Definition* def) {
SkASSERT(MarkType::kColumn == column->fMarkType);
this->writeString("-");
this->writeSpace();
- this->descriptionOut(column);
+ this->descriptionOut(column, SkipFirstLine::kNo);
this->lf(1);
}
}
@@ -157,7 +193,7 @@ void IncludeWriter::descriptionOut(const Definition* def) {
break;
}
}
- SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500));
+ SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500) || def->fDeprecated);
if (commentLen > 0) {
this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
}
@@ -384,9 +420,16 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
SkASSERT(currentEnumItem);
if (currentEnumItem->fShort) {
this->indentToColumn(fEnumItemCommentTab);
- this->writeString("//!<");
- this->writeSpace();
- this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ if (commentLen || currentEnumItem->fDeprecated) {
+ this->writeString("//!<");
+ this->writeSpace();
+ if (currentEnumItem->fDeprecated) {
+ this->writeString(child.fToBeDeprecated ? "to be deprecated soon"
+ : "deprecated");
+ } else {
+ this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ }
+ }
}
if (onePast) {
fIndent -= 4;
@@ -438,23 +481,35 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
commentEnd = currentEnumItem->fContentEnd;
}
TextParser enumComment(fFileName, commentStart, commentEnd, currentEnumItem->fLineCount);
+ bool isDeprecated = false;
if (enumComment.skipToLineStart()) { // skip const value
commentStart = enumComment.fChar;
commentLen = (int) (commentEnd - commentStart);
} else {
- const Definition* privateDef = currentEnumItem->fChildren[0];
- SkASSERT(MarkType::kPrivate == privateDef->fMarkType);
- commentStart = privateDef->fContentStart;
- commentLen = (int) (privateDef->fContentEnd - privateDef->fContentStart);
+ const Definition* childDef = currentEnumItem->fChildren[0];
+ isDeprecated = MarkType::kDeprecated == childDef->fMarkType;
+ if (MarkType::kPrivate == childDef->fMarkType || isDeprecated) {
+ commentStart = childDef->fContentStart;
+ if (currentEnumItem->fToBeDeprecated) {
+ SkASSERT(isDeprecated);
+ commentStart += 4; // skip over "soon" // FIXME: this is awkward
+ }
+ commentLen = (int) (childDef->fContentEnd - commentStart);
+ }
}
// FIXME: may assert here if there's no const value
// should have detected and errored on that earlier when enum fContentStart was set
- SkASSERT(commentLen > 0 && commentLen < 1000);
+ SkASSERT((commentLen > 0 && commentLen < 1000) || isDeprecated);
if (!currentEnumItem->fShort) {
this->writeCommentHeader();
fIndent += 4;
- bool wroteLineFeed = Wrote::kLF ==
- this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ bool wroteLineFeed = false;
+ if (isDeprecated) {
+ this->writeString(currentEnumItem->fToBeDeprecated
+ ? "To be deprecated soon." : "Deprecated.");
+ }
+ wroteLineFeed = Wrote::kLF ==
+ this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
fIndent -= 4;
if (wroteLineFeed || fColumn > 100 - 3 /* space * / */ ) {
this->lfcr();
@@ -599,7 +654,7 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child)
}
this->writeCommentHeader();
fIndent += 4;
- this->descriptionOut(method);
+ this->descriptionOut(method, SkipFirstLine::kNo);
// compute indention column
size_t column = 0;
bool hasParmReturn = false;
@@ -650,6 +705,7 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child)
this->writeCommentTrailer();
fBmhMethod = nullptr;
fMethodDef = nullptr;
+ fEnumDef = nullptr;
fWroteMethod = true;
}
@@ -663,12 +719,41 @@ void IncludeWriter::structOut(const Definition* root, const Definition& child,
this->writeString(child.fName.c_str());
fIndent += 4;
this->lfcr();
- this->rewriteBlock((int) (commentEnd - commentStart), commentStart, Phrase::kNo);
+ if (child.fDeprecated) {
+ this->writeString(child.fToBeDeprecated ? "to be deprecated soon" : "deprecated");
+ } else {
+ this->rewriteBlock((int)(commentEnd - commentStart), commentStart, Phrase::kNo);
+ }
fIndent -= 4;
this->lfcr();
this->writeCommentTrailer();
}
+Definition* IncludeWriter::findMemberCommentBlock(const vector<Definition*>& bmhChildren,
+ const string& name) const {
+ for (auto memberDef : bmhChildren) {
+ if (MarkType::kMember != memberDef->fMarkType) {
+ continue;
+ }
+ string match = memberDef->fName;
+ // if match.endsWith(name) ...
+ if (match.length() >= name.length() &&
+ 0 == match.compare(match.length() - name.length(), name.length(), name)) {
+ return memberDef;
+ }
+ }
+ for (auto memberDef : bmhChildren) {
+ if (MarkType::kSubtopic != memberDef->fMarkType && MarkType::kTopic != memberDef->fMarkType) {
+ continue;
+ }
+ Definition* result = this->findMemberCommentBlock(memberDef->fChildren, name);
+ if (result) {
+ return result;
+ }
+ }
+ return nullptr;
+}
+
Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const Definition& child) {
const char* blockStart = !fWroteMethod && fDeferComment ? fLastComment->fContentEnd : fStart;
const char* blockEnd = fWroteMethod && fDeferComment ? fDeferComment->fStart - 1 :
@@ -679,22 +764,14 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
fIndentNext = false;
}
fWroteMethod = false;
- const char* commentStart = nullptr;
- ptrdiff_t commentLen = 0;
string name(child.fContentStart, (int) (child.fContentEnd - child.fContentStart));
- bool isShort = false;
- Definition* commentBlock = nullptr;
- for (auto memberDef : fBmhStructDef->fChildren) {
- if (memberDef->fName.length() - name.length() == memberDef->fName.find(name)) {
- commentStart = memberDef->fContentStart;
- commentLen = memberDef->fContentEnd - commentStart;
- isShort = memberDef->fShort;
- commentBlock = memberDef;
- SkASSERT(!isShort || memberDef->fChildren.size() == 0);
- break;
- }
+ Definition* commentBlock = this->findMemberCommentBlock(fBmhStructDef->fChildren, name);
+ if (!commentBlock) {
+ return memberStart->reportError<Definition*>("member missing comment block");
}
- if (!isShort) {
+ if (!commentBlock->fShort) {
+ const char* commentStart = commentBlock->fContentStart;
+ ptrdiff_t commentLen = commentBlock->fContentEnd - commentStart;
this->writeCommentHeader();
bool wroteLineFeed = false;
fIndent += 4;
@@ -739,16 +816,40 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
valueStart->fContentStart);
}
this->writeString(";");
- if (isShort) {
+ if (commentBlock->fShort) {
this->indentToColumn(fStructCommentTab);
this->writeString("//!<");
this->writeSpace();
- this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ string extract = commentBlock->extractText(Definition::TrimExtract::kYes);
+ this->rewriteBlock(extract.length(), &extract.front(), Phrase::kNo);
}
this->lf(2);
return valueEnd;
}
+// iterate through bmh children and see which comments fit on include lines
+void IncludeWriter::structSetMembersShort(const vector<Definition*>& bmhChildren) {
+ for (auto memberDef : bmhChildren) {
+ if (MarkType::kMember != memberDef->fMarkType) {
+ continue;
+ }
+ string extract = memberDef->extractText(Definition::TrimExtract::kYes);
+ bool multiline = string::npos != extract.find('\n');
+ if (multiline) {
+ memberDef->fShort = false;
+ } else {
+ ptrdiff_t lineLen = extract.length() + 5 /* //!< space */ ;
+ memberDef->fShort = fStructCommentTab + lineLen < 100;
+ }
+ }
+ for (auto memberDef : bmhChildren) {
+ if (MarkType::kSubtopic != memberDef->fMarkType && MarkType::kTopic != memberDef->fMarkType) {
+ continue;
+ }
+ this->structSetMembersShort(memberDef->fChildren);
+ }
+}
+
void IncludeWriter::structSizeMembers(const Definition& child) {
int longestType = 0;
Definition* typeStart = nullptr;
@@ -860,20 +961,7 @@ void IncludeWriter::structSizeMembers(const Definition& child) {
fStructValueTab -= 1 /* ; */ ;
}
// iterate through bmh children and see which comments fit on include lines
- for (auto& member : fBmhStructDef->fChildren) {
- if (MarkType::kMember != member->fMarkType) {
- continue;
- }
- TextParser memberLine(member);
- memberLine.trimEnd();
- const char* commentStart = memberLine.fChar;
- memberLine.skipLine();
- ptrdiff_t lineLen = memberLine.fChar - commentStart + 5 /* //!< space */ ;
- if (!memberLine.eof()) {
- memberLine.skipWhiteSpace();
- }
- member->fShort = memberLine.eof() && fStructCommentTab + lineLen < 100;
- }
+ this->structSetMembersShort(fBmhStructDef->fChildren);
}
static bool find_start(const Definition* startDef, const char* start) {
@@ -892,6 +980,9 @@ static bool find_start(const Definition* startDef, const char* start) {
}
bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefinition* root) {
+ if (!def->fTokens.size()) {
+ return true;
+ }
ParentPair pair = { def, prevPair };
// write bulk of original include up to class, method, enum, etc., excepting preceding comment
// find associated bmh object
@@ -908,6 +999,8 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
bool inConstructor = false;
bool inInline = false;
bool eatOperator = false;
+ bool sawConst = false;
+ bool staticOnly = false;
const Definition* requireDense = nullptr;
const Definition* startDef = nullptr;
for (auto& child : def->fTokens) {
@@ -1033,6 +1126,10 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
methodName += string(fContinuation, continueEnd - fContinuation);
method = root->find(methodName, RootDefinition::AllowParens::kNo);
if (!method) {
+ if (fBmhStructDef && fBmhStructDef->fDeprecated) {
+ fContinuation = nullptr;
+ continue;
+ }
fLineCount = child.fLineCount;
return this->reportError<bool>("method not found");
}
@@ -1058,6 +1155,9 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
this->methodOut(method, child);
continue;
+ } else if (fBmhStructDef && fBmhStructDef->fDeprecated) {
+ fContinuation = nullptr;
+ continue;
}
fLineCount = child.fLineCount;
return this->reportError<bool>("method not found");
@@ -1130,10 +1230,10 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
#endif
}
- const Definition* cIncludeStructDef = nullptr;
switch (child.fKeyWord) {
case KeyWord::kStruct:
case KeyWord::kClass:
+ fStructMemberTab = 0;
// if struct contains members, compute their name and comment tabs
if (child.fChildren.size() > 0) {
const ParentPair* testPair = &pair;
@@ -1233,14 +1333,14 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
}
// FIXME: trigger error earlier if inner #Struct or #Class is missing #Code
- SkASSERT(nextBlock); // FIXME: check enum for correct order earlier
- const char* commentStart = codeBlock->fTerminator;
- const char* commentEnd = nextBlock->fStart;
- if (fIndentNext) {
-// fIndent += 4;
+ if (!fBmhStructDef->fDeprecated) {
+ SkASSERT(codeBlock);
+ SkASSERT(nextBlock); // FIXME: check enum for correct order earlier
+ const char* commentStart = codeBlock->fTerminator;
+ const char* commentEnd = nextBlock->fStart;
+ fIndentNext = true;
+ this->structOut(root, *fBmhStructDef, commentStart, commentEnd);
}
- fIndentNext = true;
- this->structOut(root, *fBmhStructDef, commentStart, commentEnd);
}
fDeferComment = nullptr;
} else {
@@ -1254,7 +1354,18 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
} break;
case KeyWord::kConst:
case KeyWord::kConstExpr:
+ sawConst = !memberStart || staticOnly;
+ if (!memberStart) {
+ memberStart = &child;
+ staticOnly = true;
+ }
+ break;
case KeyWord::kStatic:
+ if (!memberStart) {
+ memberStart = &child;
+ staticOnly = true;
+ }
+ break;
case KeyWord::kInt:
case KeyWord::kUint8_t:
case KeyWord::kUint16_t:
@@ -1264,7 +1375,9 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
case KeyWord::kSize_t:
case KeyWord::kFloat:
case KeyWord::kBool:
+ case KeyWord::kChar:
case KeyWord::kVoid:
+ staticOnly = false;
if (!memberStart) {
memberStart = &child;
}
@@ -1283,28 +1396,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
default:
SkASSERT(0);
}
- if (cIncludeStructDef) {
- TextParser structName(&child);
- SkAssertResult(structName.skipToEndBracket('{'));
- startDef = &child;
- fStart = structName.fChar + 1;
- this->writeBlock((int) (fStart - child.fStart), child.fStart);
- this->lf(2);
- fIndent += 4;
- if (!this->populate(&child, &pair, const_cast<Definition*>(cIncludeStructDef)->asRoot())) {
- return false;
- }
- // output any remaining definitions at current indent level
- const char* structEnd = child.fContentEnd;
- SkAssertResult('}' == structEnd[-1]);
- --structEnd;
- this->writeBlockTrim((int) (structEnd - fStart), fStart);
- this->lf(2);
- fStart = structEnd;
- fIndent -= 4;
- fContinuation = nullptr;
- fDeferComment = nullptr;
- } else if (KeyWord::kUint8_t == child.fKeyWord) {
+ if (KeyWord::kUint8_t == child.fKeyWord) {
continue;
} else {
if (fInEnum && KeyWord::kClass == child.fChildren[0]->fKeyWord) {
@@ -1316,7 +1408,6 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
return false;
}
if (KeyWord::kClass == child.fKeyWord || KeyWord::kStruct == child.fKeyWord) {
- fStructMemberTab = 0;
if (fInStruct) {
fInStruct = false;
do {
@@ -1375,6 +1466,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
auto iter = def->fTokens.begin();
std::advance(iter, child.fParentIndex - 1);
memberStart = &*iter;
+ staticOnly = false;
if (!fStructMemberTab) {
SkASSERT(KeyWord::kStruct == def->fParent->fKeyWord);
fIndent += 4;
@@ -1384,13 +1476,36 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
fIndentNext = true;
}
}
- memberEnd = this->structMemberOut(memberStart, child);
- startDef = &child;
- fStart = child.fContentEnd + 1;
- fDeferComment = nullptr;
+ SkASSERT(fBmhStructDef);
+ if (!fBmhStructDef->fDeprecated) {
+ memberEnd = this->structMemberOut(memberStart, child);
+ startDef = &child;
+ fStart = child.fContentEnd + 1;
+ fDeferComment = nullptr;
+ }
+ } else if (MarkType::kNone == child.fMarkType && sawConst
+ && fEnumDef && !fEnumDef->fDeprecated) {
+ const Definition* bmhConst = nullptr;
+ string match;
+ if (root) {
+ match = root->fName + "::";
+ }
+ match += string(child.fContentStart, child.fContentEnd - child.fContentStart);
+ for (auto enumChild : fEnumDef->fChildren) {
+ if (MarkType::kConst == enumChild->fMarkType && enumChild->fName == match) {
+ bmhConst = enumChild;
+ break;
+ }
+ }
+ if (bmhConst) {
+ this->constOut(memberStart, child, bmhConst);
+ fDeferComment = nullptr;
+ sawConst = false;
+ }
}
if (child.fMemberStart) {
memberStart = &child;
+ staticOnly = false;
}
const char attrDeprecated[] = "SK_ATTR_DEPRECATED";
const size_t attrDeprecatedLen = sizeof(attrDeprecated) - 1;
@@ -1403,6 +1518,8 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (Definition::Type::kPunctuation == child.fType) {
if (Punctuation::kSemicolon == child.fPunctuation) {
memberStart = nullptr;
+ sawConst = false;
+ staticOnly = false;
if (inStruct) {
fInStruct = false;
}
@@ -1546,6 +1663,7 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
*refType = RefType::kNormal;
SkASSERT(string::npos == undername.find(' '));
const Definition* rootDef = nullptr;
+ string substitute;
{
auto rootDefIter = fBmhParser->fTopicMap.find(undername);
if (fBmhParser->fTopicMap.end() != rootDefIter) {
@@ -1561,10 +1679,18 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
if (fBmhParser->fTopicMap.end() != rootDefIter) {
rootDef = rootDefIter->second;
}
- } else {
+ if (!rootDef) {
+ size_t doubleColon = fBmhStructDef->fName.rfind("::");
+ if (string::npos != doubleColon && undername
+ == fBmhStructDef->fName.substr(doubleColon + 2)) {
+ substitute = fBmhStructDef->fName;
+ }
+ }
+ }
+ if (!rootDef && !substitute.length()) {
auto aliasIter = fBmhParser->fAliasMap.find(undername);
if (fBmhParser->fAliasMap.end() != aliasIter) {
- rootDef = aliasIter->second->fParent;
+ rootDef = aliasIter->second;
} else if (!first) {
SkDebugf("unfound: %s\n", undername.c_str());
this->reportError("reference unfound");
@@ -1573,33 +1699,71 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
}
}
}
- string substitute;
if (rootDef) {
- for (auto child : rootDef->fChildren) {
- if (MarkType::kSubstitute == child->fMarkType) {
- substitute = string(child->fContentStart,
- (int) (child->fContentEnd - child->fContentStart));
- break;
+ MarkType rootType = rootDef->fMarkType;
+ bool isTopic = MarkType::kSubtopic == rootType || MarkType::kTopic == rootType;
+ auto substituteParent = MarkType::kAlias == rootType ? rootDef->fParent :
+ isTopic ? rootDef : nullptr;
+ if (substituteParent) {
+ for (auto child : substituteParent->fChildren) {
+ if (MarkType::kSubstitute == child->fMarkType) {
+ substitute = string(child->fContentStart,
+ (int) (child->fContentEnd - child->fContentStart));
+ break;
+ }
+ }
+ }
+ if (!substitute.length()) {
+ string match = rootDef->fName;
+ size_t index;
+ while (string::npos != (index = match.find('_'))) {
+ match.erase(index, 1);
+ }
+ string skmatch = "Sk" + match;
+ auto parent = substituteParent ? substituteParent : rootDef;
+ for (auto child : parent->fChildren) {
+ // there may be more than one
+ // prefer the one mostly closely matching in text
+ if ((MarkType::kClass == child->fMarkType ||
+ MarkType::kStruct == child->fMarkType ||
+ (MarkType::kEnum == child->fMarkType && !child->fAnonymous) ||
+ MarkType::kEnumClass == child->fMarkType) && (match == child->fName ||
+ skmatch == child->fName)) {
+ substitute = child->fName;
+ break;
+ }
}
}
if (!substitute.length()) {
for (auto child : rootDef->fChildren) {
+ // there may be more than one
+ // if so, it's a bug since it's unknown which is the right one
if (MarkType::kClass == child->fMarkType ||
MarkType::kStruct == child->fMarkType ||
(MarkType::kEnum == child->fMarkType && !child->fAnonymous) ||
MarkType::kEnumClass == child->fMarkType) {
+ SkASSERT("" == substitute);
substitute = child->fName;
- if (MarkType::kEnum == child->fMarkType && fInEnum) {
+ if (MarkType::kEnum == child->fMarkType) {
size_t parentClassEnd = substitute.find("::");
SkASSERT(string::npos != parentClassEnd);
- substitute = substitute.substr(parentClassEnd + 2);
+ string subEnd = substitute.substr(parentClassEnd + 2);
+ if (fInEnum) {
+ substitute = subEnd;
+ }
+ if (subEnd == undername) {
+ break;
+ }
}
- break;
}
}
}
if (!substitute.length()) {
- auto parent = rootDef->fParent;
+ const Definition* parent = rootDef;
+ do {
+ parent = parent->fParent;
+ } while (parent && (MarkType::kSubtopic == parent->fMarkType
+ || MarkType::kTopic == parent->fMarkType));
if (parent) {
if (MarkType::kClass == parent->fMarkType ||
MarkType::kStruct == parent->fMarkType ||
@@ -1607,10 +1771,8 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
MarkType::kEnumClass == parent->fMarkType) {
if (parent->fParent != fRootTopic) {
substitute = parent->fName;
- size_t under = undername.find('_');
- SkASSERT(string::npos != under);
- string secondHalf(&undername[under], (size_t) (undername.length() - under));
- substitute += ConvertRef(secondHalf, false);
+ substitute += ' ';
+ substitute += ConvertRef(rootDef->fName, false);
} else {
substitute += ConvertRef(undername, first);
}
@@ -1633,6 +1795,7 @@ int IncludeWriter::lookupMethod(const PunctuationState punctuation, const Word w
++wordStart;
}
const int wordEnd = PunctuationState::kDelimiter == punctuation ||
+ PunctuationState::kParen == punctuation ||
PunctuationState::kPeriod == punctuation ? run - 1 : run;
string temp;
if (hasIndirection && '(' != data[wordEnd - 1] && ')' != data[wordEnd - 1]) {
@@ -1668,6 +1831,7 @@ int IncludeWriter::lookupMethod(const PunctuationState punctuation, const Word w
int IncludeWriter::lookupReference(const PunctuationState punctuation, const Word word,
const int start, const int run, int lastWrite, const char last, const char* data) {
const int end = PunctuationState::kDelimiter == punctuation ||
+ PunctuationState::kParen == punctuation ||
PunctuationState::kPeriod == punctuation ? run - 1 : run;
RefType refType = RefType::kUndefined;
string resolved = string(&data[start], (size_t) (end - start));
@@ -1767,7 +1931,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
case Word::kMixed:
if (hasUpper && hasLower && !hasSymbol && lastSpace > 0) {
lastWrite = this->lookupMethod(punctuation, word, lastSpace, run,
- lastWrite, data, hasIndirection && !hasSymbol);
+ lastWrite, data, hasIndirection);
}
break;
default:
@@ -1785,26 +1949,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
hasSymbol = false;
lastSpace = run;
break;
- case '.':
- switch (word) {
- case Word::kStart:
- punctuation = PunctuationState::kDelimiter;
- case Word::kCap:
- case Word::kFirst:
- case Word::kUnderline:
- case Word::kMixed:
- if (PunctuationState::kDelimiter == punctuation ||
- PunctuationState::kPeriod == punctuation) {
- word = Word::kMixed;
- }
- punctuation = PunctuationState::kPeriod;
- break;
- default:
- SkASSERT(0);
- }
- embeddedIndirection = true;
- break;
- case ',': case ';': case ':':
+ case '.': case ',': case ';': case ':': case ')':
switch (word) {
case Word::kStart:
punctuation = PunctuationState::kDelimiter;
@@ -1816,12 +1961,13 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
PunctuationState::kPeriod == punctuation) {
word = Word::kMixed;
}
- punctuation = PunctuationState::kDelimiter;
+ punctuation = '.' == c ? PunctuationState::kPeriod :
+ PunctuationState::kDelimiter;
break;
default:
SkASSERT(0);
}
- embeddedSymbol = true;
+ ('.' == c ? embeddedIndirection : embeddedSymbol) = true;
break;
case '>':
if ('-' == last) {
@@ -1838,16 +1984,12 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
break;
case '(':
if (' ' == last) {
- punctuation = PunctuationState::kDelimiter;
+ punctuation = PunctuationState::kParen;
} else {
word = Word::kMixed;
}
embeddedSymbol = true;
break;
- case ')': // assume word type has already been set
- punctuation = PunctuationState::kDelimiter;
- embeddedSymbol = true;
- break;
case '_':
switch (word) {
case Word::kStart:
diff --git a/chromium/third_party/skia/tools/bookmaker/mdOut.cpp b/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
index 24009d02f8c..f74853b470a 100644
--- a/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
@@ -34,6 +34,15 @@ static string preformat(const string& orig) {
return result;
}
+static bool all_lower(const string& ref) {
+ for (auto ch : ref) {
+ if (!islower(ch)) {
+ return false;
+ }
+ }
+ return true;
+}
+
// FIXME: preserve inter-line spaces and don't add new ones
string MdOut::addReferences(const char* refStart, const char* refEnd,
BmhParser::Resolvable resolvable) {
@@ -128,8 +137,12 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
ref = fullRef;
}
- }
- result += linkRef(leadingSpaces, def, ref);
+ } else if (BmhParser::Resolvable::kClone != resolvable &&
+ all_lower(ref) && (t.eof() || '(' != t.peek())) {
+ add_ref(leadingSpaces, ref, &result);
+ continue;
+ }
+ result += linkRef(leadingSpaces, def, ref, resolvable);
continue;
}
if (!t.eof() && '(' == t.peek()) {
@@ -141,7 +154,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
ref = string(start, t.fChar - start);
if (const Definition* def = this->isDefined(t, ref, true)) {
SkASSERT(def->fFiddle.length());
- result += linkRef(leadingSpaces, def, ref);
+ result += linkRef(leadingSpaces, def, ref, resolvable);
continue;
}
}
@@ -168,7 +181,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
// will also need to see if Example Description matches var in example
const Definition* def;
if (fMethod && (def = fMethod->hasParam(ref))) {
- result += linkRef(leadingSpaces, def, ref);
+ result += linkRef(leadingSpaces, def, ref, resolvable);
fLastParam = def;
distFromParam = 0;
continue;
@@ -183,7 +196,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
if (paramType) {
string fullName = paramType->fName + "::" + ref;
if (paramType->hasMatch(fullName)) {
- result += linkRef(leadingSpaces, paramType, ref);
+ result += linkRef(leadingSpaces, paramType, ref, resolvable);
continue;
}
}
@@ -199,37 +212,37 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
auto topicIter = fBmhParser.fTopicMap.find(ref);
if (topicIter != fBmhParser.fTopicMap.end()) {
- result += linkRef(leadingSpaces, topicIter->second, ref);
+ result += linkRef(leadingSpaces, topicIter->second, ref, resolvable);
continue;
}
bool startsSentence = t.sentenceEnd(start);
if (!t.eof() && ' ' != t.peek()) {
- add_ref(leadingSpaces, ref, &result);
+ add_ref(leadingSpaces, ref, &result);
continue;
}
if (t.fChar + 1 >= t.fEnd || (!isupper(t.fChar[1]) && startsSentence)) {
- add_ref(leadingSpaces, ref, &result);
+ add_ref(leadingSpaces, ref, &result);
continue;
}
if (isupper(t.fChar[1]) && startsSentence) {
TextParser next(t.fFileName, &t.fChar[1], t.fEnd, t.fLineCount);
string nextWord(next.fChar, next.wordEnd() - next.fChar);
if (this->isDefined(t, nextWord, true)) {
- add_ref(leadingSpaces, ref, &result);
+ add_ref(leadingSpaces, ref, &result);
continue;
}
}
- Definition* test = fRoot;
+ const Definition* test = fRoot;
do {
if (!test->isRoot()) {
continue;
}
for (string prefix : { "_", "::" } ) {
- RootDefinition* root = test->asRoot();
+ const RootDefinition* root = test->asRoot();
string prefixed = root->fName + prefix + ref;
if (const Definition* def = root->find(prefixed,
RootDefinition::AllowParens::kYes)) {
- result += linkRef(leadingSpaces, def, ref);
+ result += linkRef(leadingSpaces, def, ref, resolvable);
goto found;
}
}
@@ -244,6 +257,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
return result;
}
+
+
bool MdOut::buildReferences(const char* docDir, const char* mdFileOrPath) {
if (!sk_isdir(mdFileOrPath)) {
SkString mdFile = SkOSPath::Basename(mdFileOrPath);
@@ -259,15 +274,8 @@ bool MdOut::buildReferences(const char* docDir, const char* mdFileOrPath) {
SkOSFile::Iter it(docDir, ".bmh");
for (SkString file; it.next(&file); ) {
SkString p = SkOSPath::Join(docDir, file.c_str());
- const char* hunk = p.c_str();
- if (!SkStrEndsWith(hunk, ".bmh")) {
- continue;
- }
- if (SkStrEndsWith(hunk, "markup.bmh")) { // don't look inside this for now
- continue;
- }
- if (!this->buildRefFromFile(hunk, mdFileOrPath)) {
- SkDebugf("failed to parse %s\n", hunk);
+ if (!this->buildRefFromFile(p.c_str(), mdFileOrPath)) {
+ SkDebugf("failed to parse %s\n", p.c_str());
return false;
}
}
@@ -289,6 +297,15 @@ bool MdOut::buildStatus(const char* statusFile, const char* outDir) {
}
bool MdOut::buildRefFromFile(const char* name, const char* outDir) {
+ if (!SkStrEndsWith(name, ".bmh")) {
+ return true;
+ }
+ if (SkStrEndsWith(name, "markup.bmh")) { // don't look inside this for now
+ return true;
+ }
+ if (SkStrEndsWith(name, "illustrations.bmh")) { // don't look inside this for now
+ return true;
+ }
fFileName = string(name);
string filename(name);
if (filename.substr(filename.length() - 4) == ".bmh") {
@@ -344,6 +361,16 @@ bool MdOut::buildRefFromFile(const char* name, const char* outDir) {
this->lfAlways(1);
FPRINTF("===");
}
+ fPopulators.clear();
+ fPopulators[kClassesAndStructs].fDescription = "embedded struct and class members";
+ fPopulators[kConstants].fDescription = "enum and enum class, const values";
+ fPopulators[kConstructors].fDescription = "functions that construct";
+ fPopulators[kMemberFunctions].fDescription = "static functions and member methods";
+ fPopulators[kMembers].fDescription = "member values";
+ fPopulators[kOperators].fDescription = "operator overloading methods";
+ fPopulators[kRelatedFunctions].fDescription = "similar methods grouped together";
+ fPopulators[kSubtopics].fDescription = "";
+ this->populateTables(fRoot);
this->markTypeOut(topicDef);
}
if (fOut) {
@@ -411,6 +438,24 @@ void MdOut::childrenOut(const Definition* def, const char* start) {
}
}
+const Definition* MdOut::csParent() const {
+ const Definition* csParent = fRoot->csParent();
+ if (!csParent) {
+ const Definition* topic = fRoot;
+ while (topic && MarkType::kTopic != topic->fMarkType) {
+ topic = topic->fParent;
+ }
+ for (auto child : topic->fChildren) {
+ if (child->isStructOrClass() || MarkType::kTypedef == child->fMarkType) {
+ csParent = child;
+ break;
+ }
+ }
+ SkASSERT(csParent || string::npos == fRoot->fFileName.find("Sk"));
+ }
+ return csParent;
+}
+
const Definition* MdOut::findParamType() {
SkASSERT(fMethod);
TextParser parser(fMethod->fFileName, fMethod->fStart, fMethod->fContentStart,
@@ -473,12 +518,12 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
if (const Definition* definition = fRoot->find(ref, RootDefinition::AllowParens::kYes)) {
return definition;
}
- Definition* test = fRoot;
+ const Definition* test = fRoot;
do {
if (!test->isRoot()) {
continue;
}
- RootDefinition* root = test->asRoot();
+ const RootDefinition* root = test->asRoot();
for (auto& leaf : root->fBranches) {
if (ref == leaf.first) {
return leaf.second;
@@ -502,6 +547,11 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
}
}
}
+ string fiddlePrefixed = root->fFiddle + "_" + ref;
+ auto topicIter = fBmhParser.fTopicMap.find(fiddlePrefixed);
+ if (topicIter != fBmhParser.fTopicMap.end()) {
+ return topicIter->second;
+ }
} while ((test = test->fParent));
}
size_t doubleColon = ref.find("::");
@@ -523,8 +573,9 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
// try with a prefix
if ('k' == ref[0]) {
for (auto const& iter : fBmhParser.fEnumMap) {
- if (iter.second.find(ref, RootDefinition::AllowParens::kYes)) {
- return &iter.second;
+ auto def = iter.second.find(ref, RootDefinition::AllowParens::kYes);
+ if (def) {
+ return def;
}
}
if (fEnumClass) {
@@ -603,38 +654,42 @@ string MdOut::linkName(const Definition* ref) const {
// for now, hard-code to html links
// def should not include SkXXX_
string MdOut::linkRef(const string& leadingSpaces, const Definition* def,
- const string& ref) const {
+ const string& ref, BmhParser::Resolvable resolvable) const {
string buildup;
+ string refName;
const string* str = &def->fFiddle;
SkASSERT(str->length() > 0);
- size_t under = str->find('_');
- Definition* curRoot = fRoot;
- string classPart = string::npos != under ? str->substr(0, under) : *str;
- bool classMatch = curRoot->fName == classPart;
- while (curRoot->fParent) {
- curRoot = curRoot->fParent;
- classMatch |= curRoot->fName == classPart;
+ string classPart = *str;
+ bool globalEnumMember = false;
+ if (MarkType::kAlias == def->fMarkType) {
+ def = def->fParent;
+ SkASSERT(def);
+ SkASSERT(MarkType::kSubtopic == def->fMarkType ||MarkType::kTopic == def->fMarkType);
}
- const Definition* defRoot;
- const Definition* temp = def;
- do {
- defRoot = temp;
- if (!(temp = temp->fParent)) {
- break;
+ if (MarkType::kSubtopic == def->fMarkType) {
+ const Definition* topic = def->topicParent();
+ SkASSERT(topic);
+ classPart = topic->fName;
+ refName = def->fName;
+ } else if (MarkType::kTopic == def->fMarkType) {
+ refName = def->fName;
+ } else {
+ if ('k' == (*str)[0] && string::npos != str->find("_Sk")) {
+ globalEnumMember = true;
+ } else {
+ SkASSERT("Sk" == str->substr(0, 2) || "SK" == str->substr(0, 2)
+ // FIXME: kitchen sink catch below, need to do better
+ || string::npos != def->fFileName.find("undocumented"));
+ size_t under = str->find('_');
+ classPart = string::npos != under ? str->substr(0, under) : *str;
}
- classMatch |= temp != defRoot && temp->fName == classPart;
- } while (true);
- string namePart = string::npos != under ? str->substr(under + 1, str->length()) : *str;
+ refName = def->fFiddle;
+ }
+ bool classMatch = fRoot->fFileName == def->fFileName;
SkASSERT(fRoot);
SkASSERT(fRoot->fFileName.length());
- if (classMatch) {
- buildup = "#";
- if (*str != classPart && "Sk" == classPart.substr(0, 2)) {
- buildup += classPart + "_";
- }
- buildup += namePart;
- } else {
- string filename = defRoot->asRoot()->fFileName;
+ if (!classMatch) {
+ string filename = def->fFileName;
if (filename.substr(filename.length() - 4) == ".bmh") {
filename = filename.substr(0, filename.length() - 4);
}
@@ -642,19 +697,46 @@ string MdOut::linkRef(const string& leadingSpaces, const Definition* def,
while (start > 0 && (isalnum(filename[start - 1]) || '_' == filename[start - 1])) {
--start;
}
- buildup = filename.substr(start) + "#" + (classMatch ? namePart : *str);
+ buildup = filename.substr(start);
}
+ buildup += "#" + refName;
if (MarkType::kParam == def->fMarkType) {
const Definition* parent = def->fParent;
SkASSERT(MarkType::kMethod == parent->fMarkType);
buildup = '#' + parent->fFiddle + '_' + ref;
}
string refOut(ref);
- std::replace(refOut.begin(), refOut.end(), '_', ' ');
+ if (!globalEnumMember) {
+ std::replace(refOut.begin(), refOut.end(), '_', ' ');
+ }
if (ref.length() > 2 && islower(ref[0]) && "()" == ref.substr(ref.length() - 2)) {
refOut = refOut.substr(0, refOut.length() - 2);
}
- return leadingSpaces + "<a href=\"" + buildup + "\">" + refOut + "</a>";
+ string result = leadingSpaces + "<a href=\"" + buildup + "\">" + refOut + "</a>";
+ if (BmhParser::Resolvable::kClone == resolvable && MarkType::kMethod == def->fMarkType &&
+ def->fCloned && !def->fClone) {
+ bool found = false;
+ string match = def->fName;
+ if ("()" == match.substr(match.length() - 2)) {
+ match = match.substr(0, match.length() - 2);
+ }
+ match += '_';
+ auto classIter = fBmhParser.fClassMap.find(classPart);
+ if (fBmhParser.fClassMap.end() != classIter) {
+ for (char num = '2'; num <= '9'; ++num) {
+ string clone = match + num;
+ const auto& leafIter = classIter->second.fLeaves.find(clone);
+ if (leafIter != classIter->second.fLeaves.end()) {
+ result += "<sup><a href=\"" + buildup + "_" + num + "\">[" + num + "]</a></sup>";
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ SkDebugf(""); // convenient place to set a breakpoint
+ }
+ }
+ return result;
}
void MdOut::markTypeOut(Definition* def) {
@@ -755,8 +837,6 @@ void MdOut::markTypeOut(Definition* def) {
FPRINTF("<a name=\"%s\"></a> Enum %s", def->fFiddle.c_str(), def->fName.c_str());
this->lf(2);
break;
- case MarkType::kError:
- break;
case MarkType::kExample: {
this->mdHeaderOut(3);
FPRINTF("Example\n"
@@ -773,7 +853,7 @@ void MdOut::markTypeOut(Definition* def) {
gpuAndCpu = platParse.strnstr("cpu", platParse.fEnd);
}
}
- if (fHasFiddle && !def->hasChild(MarkType::kError)) {
+ if (fHasFiddle) {
SkASSERT(def->fHash.length() > 0);
FPRINTF("<div><fiddle-embed name=\"%s\"", def->fHash.c_str());
if (showGpu) {
@@ -806,10 +886,31 @@ void MdOut::markTypeOut(Definition* def) {
break;
case MarkType::kHeight:
break;
+ case MarkType::kIllustration: {
+ string illustName = "Illustrations_" + def->fParent->fFiddle;
+ auto illustIter = fBmhParser.fTopicMap.find(illustName);
+ SkASSERT(fBmhParser.fTopicMap.end() != illustIter);
+ Definition* illustDef = illustIter->second;
+ SkASSERT(MarkType::kSubtopic == illustDef->fMarkType);
+ SkASSERT(1 == illustDef->fChildren.size());
+ Definition* illustExample = illustDef->fChildren[0];
+ SkASSERT(MarkType::kExample == illustExample->fMarkType);
+ string hash = illustExample->fHash;
+ SkASSERT("" != hash);
+ string title;
+ this->writePending();
+ FPRINTF("![%s](https://fiddle.skia.org/i/%s_raster.png \"%s\")",
+ def->fName.c_str(), hash.c_str(), title.c_str());
+ this->lf(2);
+ } break;
case MarkType::kImage:
break;
+ case MarkType::kIn:
+ break;
case MarkType::kLegend:
break;
+ case MarkType::kLine:
+ break;
case MarkType::kLink:
break;
case MarkType::kList:
@@ -835,15 +936,15 @@ void MdOut::markTypeOut(Definition* def) {
} break;
case MarkType::kMethod: {
string method_name = def->methodName();
- string formattedStr = def->formatFunction();
+ string formattedStr = def->formatFunction(Definition::Format::kIncludeReturn);
- if (!def->isClone()) {
- this->lfAlways(2);
- FPRINTF("<a name=\"%s\"></a>", def->fFiddle.c_str());
+ this->lfAlways(2);
+ FPRINTF("<a name=\"%s\"></a>", def->fFiddle.c_str());
+ if (!def->isClone()) {
this->mdHeaderOutLF(2, 1);
FPRINTF("%s", method_name.c_str());
- this->lf(2);
- }
+ }
+ this->lf(2);
// TODO: put in css spec that we can define somewhere else (if markup supports that)
// TODO: 50em below should match limit = 80 in formatFunction()
@@ -897,6 +998,15 @@ void MdOut::markTypeOut(Definition* def) {
} break;
case MarkType::kPlatform:
break;
+ case MarkType::kPopulate: {
+ SkASSERT(MarkType::kSubtopic == def->fParent->fMarkType);
+ string name = def->fParent->fName;
+ if (kSubtopics == name) {
+ this->subtopicsOut();
+ } else {
+ this->subtopicOut(this->populator(name.c_str()));
+ }
+ } break;
case MarkType::kPrivate:
break;
case MarkType::kReturn:
@@ -1100,6 +1210,73 @@ void MdOut::mdHeaderOutLF(int depth, int lf) {
FPRINTF(" ");
}
+void MdOut::populateTables(const Definition* def) {
+ const Definition* csParent = this->csParent();
+ if (!csParent) {
+ return;
+ }
+ for (auto child : def->fChildren) {
+ if (MarkType::kTopic == child->fMarkType || MarkType::kSubtopic == child->fMarkType) {
+ string name = child->fName;
+ bool builtInTopic = name == kClassesAndStructs || name == kConstants
+ || name == kConstructors || name == kMemberFunctions || name == kMembers
+ || name == kOperators || name == kOverview || name == kRelatedFunctions
+ || name == kSubtopics;
+ if (!builtInTopic && child->fName != kOverview) {
+ this->populator(kRelatedFunctions).fMembers.push_back(child);
+ }
+ this->populateTables(child);
+ continue;
+ }
+ if (child->isStructOrClass()) {
+ if (fClassStack.size() > 0) {
+ this->populator(kClassesAndStructs).fMembers.push_back(child);
+ }
+ fClassStack.push_back(child);
+ this->populateTables(child);
+ fClassStack.pop_back();
+ continue;
+ }
+ if (MarkType::kEnum == child->fMarkType || MarkType::kEnumClass == child->fMarkType) {
+ this->populator(kConstants).fMembers.push_back(child);
+ continue;
+ }
+ if (MarkType::kMember == child->fMarkType) {
+ this->populator(kMembers).fMembers.push_back(child);
+ continue;
+ }
+ if (MarkType::kMethod != child->fMarkType) {
+ continue;
+ }
+ if (child->fClone) {
+ continue;
+ }
+ if (Definition::MethodType::kConstructor == child->fMethodType
+ || Definition::MethodType::kDestructor == child->fMethodType) {
+ this->populator(kConstructors).fMembers.push_back(child);
+ continue;
+ }
+ if (Definition::MethodType::kOperator == child->fMethodType) {
+ this->populator(kOperators).fMembers.push_back(child);
+ continue;
+ }
+ this->populator(kMemberFunctions).fMembers.push_back(child);
+ if (csParent && (0 == child->fName.find(csParent->fName + "::Make")
+ || 0 == child->fName.find(csParent->fName + "::make"))) {
+ this->populator(kConstructors).fMembers.push_back(child);
+ continue;
+ }
+ for (auto item : child->fChildren) {
+ if (MarkType::kIn == item->fMarkType) {
+ string name(item->fContentStart, item->fContentEnd - item->fContentStart);
+ fPopulators[name].fMembers.push_back(child);
+ fPopulators[name].fShowClones = true;
+ break;
+ }
+ }
+ }
+}
+
void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) {
if ((BmhParser::Resolvable::kLiteral == resolvable || fRespectLeadingSpace) && end > start) {
while ('\n' == *start) {
@@ -1178,3 +1355,88 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
#endif
}
}
+
+void MdOut::rowOut(const char* name, const string& description) {
+ this->lfAlways(1);
+ FPRINTF("| ");
+ this->resolveOut(name, name + strlen(name), BmhParser::Resolvable::kYes);
+ FPRINTF(" | ");
+ this->resolveOut(&description.front(), &description.back() + 1, BmhParser::Resolvable::kYes);
+ FPRINTF(" |");
+ this->lf(1);
+}
+
+void MdOut::subtopicsOut() {
+ const Definition* csParent = this->csParent();
+ SkASSERT(csParent);
+ this->rowOut("name", "description");
+ this->rowOut("---", "---");
+ for (auto item : { kClassesAndStructs, kConstants, kConstructors, kMemberFunctions,
+ kMembers, kOperators, kRelatedFunctions } ) {
+ for (auto entry : this->populator(item).fMembers) {
+ if (entry->csParent() == csParent) {
+ string description = fPopulators.find(item)->second.fDescription;
+ if (kConstructors == item) {
+ description += " " + csParent->fName;
+ }
+ this->rowOut(item, description);
+ break;
+ }
+ }
+ }
+}
+
+void MdOut::subtopicOut(const TableContents& tableContents) {
+ const auto& data = tableContents.fMembers;
+ const Definition* csParent = this->csParent();
+ SkASSERT(csParent);
+ fRoot = csParent->asRoot();
+ this->rowOut("name", "description");
+ this->rowOut("---", "---");
+ std::map<string, const Definition*> items;
+ for (auto entry : data) {
+ if (entry->csParent() != csParent) {
+ continue;
+ }
+ size_t start = entry->fName.find_last_of("::");
+ string name = entry->fName.substr(string::npos == start ? 0 : start + 1);
+ items[name] = entry;
+ }
+ for (auto entry : items) {
+ if (entry.second->fDeprecated) {
+ continue;
+ }
+ const Definition* oneLiner = nullptr;
+ for (auto child : entry.second->fChildren) {
+ if (MarkType::kLine == child->fMarkType) {
+ oneLiner = child;
+ break;
+ }
+ }
+ if (!oneLiner) {
+ SkDebugf(""); // convenient place to set a breakpoint
+ }
+ // TODO: detect this earlier? throw error here?
+ SkASSERT(oneLiner);
+ this->rowOut(entry.first.c_str(), string(oneLiner->fContentStart,
+ oneLiner->fContentEnd - oneLiner->fContentStart));
+ if (tableContents.fShowClones && entry.second->fCloned) {
+ int cloneNo = 2;
+ string builder = entry.second->fName;
+ if ("()" == builder.substr(builder.length() - 2)) {
+ builder = builder.substr(0, builder.length() - 2);
+ }
+ builder += '_';
+ this->rowOut("",
+ preformat(entry.second->formatFunction(Definition::Format::kOmitReturn)));
+ do {
+ string match = builder + to_string(cloneNo);
+ auto child = csParent->findClone(match);
+ if (!child) {
+ break;
+ }
+ this->rowOut("", preformat(child->formatFunction(Definition::Format::kOmitReturn)));
+ } while (++cloneNo);
+ }
+ }
+}
diff --git a/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp b/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
index cfd42f700fc..2e9ad81e455 100644
--- a/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
@@ -6,7 +6,6 @@
*/
#include "bookmaker.h"
-
#include "SkOSFile.h"
#include "SkOSPath.h"
diff --git a/chromium/third_party/skia/tools/bookmaker/selfCheck.cpp b/chromium/third_party/skia/tools/bookmaker/selfCheck.cpp
index 0b28d16c70d..5f1eb38ece7 100644
--- a/chromium/third_party/skia/tools/bookmaker/selfCheck.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/selfCheck.cpp
@@ -7,14 +7,32 @@
#include "bookmaker.h"
-// Check that summary contains all methods
+#ifdef SK_BUILD_FOR_WIN
+#include <windows.h>
+#endif
-// Check that mutiple like-named methods are under one Subtopic
-// Check that all subtopics are in table of contents
+ /* SkDebugf works in both visual studio and git shell, but
+ in git shell output is not piped to grep.
+ printf does not generate output in visual studio, but
+ does in git shell and can be piped.
+ */
+#ifdef SK_BUILD_FOR_WIN
+#define PRINTF(...) \
+do { \
+ if (IsDebuggerPresent()) { \
+ SkDebugf(__VA_ARGS__); \
+ } else { \
+ printf(__VA_ARGS__); \
+ } \
+} while (false)
+#else
+#define PRINTF(...) \
+ printf(__VA_ARGS__)
+#endif
+
-// Check that all constructors are in a table of contents
-// should be 'creators' instead of constructors?
+// Check that mutiple like-named methods are under one Subtopic
// Check that SeeAlso reference each other
@@ -37,142 +55,95 @@ public:
return fBmhParser.reportError<bool>("expected root topic");
}
fRoot = topicDef->asRoot();
- if (!this->checkMethodSummary()) {
- return false;
- }
- if (!this->checkMethodSubtopic()) {
- return false;
- }
- if (!this->checkSubtopicContents()) {
- return false;
- }
- if (!this->checkConstructors()) {
- return false;
- }
if (!this->checkSeeAlso()) {
return false;
}
- if (!this->checkCreators()) {
- return false;
- }
+ // report functions that are not covered by related hierarchy
+ if (!this->checkRelatedFunctions()) {
+ return false;
+ }
}
return true;
}
protected:
- bool checkConstructors() {
- return true;
- }
-
- bool checkCreators() {
- return true;
- }
-
- bool checkMethodSubtopic() {
- return true;
- }
- bool checkMethodSummary() {
- SkDebugf("");
- // look for struct or class in fChildren
- for (auto& rootChild : fRoot->fChildren) {
- if (MarkType::kStruct == rootChild->fMarkType ||
- MarkType::kClass == rootChild->fMarkType) {
- auto& cs = rootChild;
- // expect Overview as Topic in every main class or struct
- Definition* overview = nullptr;
- for (auto& csChild : cs->fChildren) {
- if ("Overview" == csChild->fName) {
- if (!overview) {
- return cs->reportError<bool>("expected only one Overview");
- }
- overview = csChild;
- }
- }
- if (!overview) {
- return cs->reportError<bool>("missing #Topic Overview");
- }
- Definition* memberFunctions = nullptr;
- for (auto& overChild : overview->fChildren) {
- if ("Member_Functions" == overChild->fName) {
- memberFunctions = overChild;
- break;
- }
- }
- if (!memberFunctions) {
- return overview->reportError<bool>("missing #Subtopic Member_Functions");
- }
- if (MarkType::kSubtopic != memberFunctions->fMarkType) {
- return memberFunctions->reportError<bool>("expected #Subtopic Member_Functions");
- }
- Definition* memberTable = nullptr;
- for (auto& memberChild : memberFunctions->fChildren) {
- if (MarkType::kTable == memberChild->fMarkType &&
- memberChild->fName == memberFunctions->fName) {
- memberTable = memberChild;
- break;
- }
- }
- if (!memberTable) {
- return memberFunctions->reportError<bool>("missing #Table in Member_Functions");
- }
- vector<string> overviewEntries; // build map of overview entries
- bool expectLegend = true;
- string prior = " "; // expect entries to be alphabetical
- for (auto& memberRow : memberTable->fChildren) {
- if (MarkType::kLegend == memberRow->fMarkType) {
- if (!expectLegend) {
- return memberRow->reportError<bool>("expect #Legend only once");
- }
- // todo: check if legend format matches table's rows' format
- expectLegend = false;
- } else if (expectLegend) {
- return memberRow->reportError<bool>("expect #Legend first");
- }
- if (MarkType::kRow != memberRow->fMarkType) {
- continue; // let anything through for now; can tighten up in the future
- }
- // expect column 0 to point to function name
- // todo: content end points past space; could tighten that up
- Definition* column0 = memberRow->fChildren[0];
- string name = string(column0->fContentStart,
- column0->fTerminator - column0->fContentStart);
- if (prior > name) {
- return memberRow->reportError<bool>("expect alphabetical order");
- }
- if (prior == name) {
- return memberRow->reportError<bool>("expect unique names");
- }
- // todo: error if name is all lower case and doesn't end in ()
- overviewEntries.push_back(name);
- prior = name;
- }
- // mark corresponding methods as visited (may be more than one per entry)
- for (auto& csChild : cs->fChildren) {
- if (MarkType::kMethod != csChild->fMarkType) {
- // only check methods for now
- continue;
- }
- auto start = csChild->fName.find_last_of(':');
- start = string::npos == start ? 0 : start + 1;
- string name = csChild->fName.substr(start);
- if (overviewEntries.end() ==
- std::find(overviewEntries.begin(), overviewEntries.end(), name)) {
- return csChild->reportError<bool>("missing in Overview");
+ void checkMethod(string topic, const Definition* csChild, vector<string>* reported) {
+ if (MarkType::kSubtopic == csChild->fMarkType) {
+ for (auto child : csChild->fChildren) {
+ checkMethod(topic, child, reported);
+ }
+ return;
+ } else if (MarkType::kMethod != csChild->fMarkType) {
+ // only check methods for now
+ return;
+ }
+ bool containsMarkTypeIn = csChild->fDeprecated // no markup for deprecated
+ || Definition::MethodType::kConstructor == csChild->fMethodType
+ || Definition::MethodType::kDestructor == csChild->fMethodType
+ || Definition::MethodType::kOperator == csChild->fMethodType
+ || csChild->fClone;
+ for (auto child : csChild->fChildren) {
+ if (MarkType::kIn == child->fMarkType) {
+ containsMarkTypeIn = true;
+ string subtopic(child->fContentStart,
+ child->fContentEnd - child->fContentStart);
+ string fullname = topic + '_' + subtopic;
+ auto topEnd = fBmhParser.fTopicMap.end();
+ auto topFind = fBmhParser.fTopicMap.find(fullname);
+ auto reportEnd = reported->end();
+ auto reportFind = std::find(reported->begin(), reported->end(), subtopic);
+ if (topEnd == topFind) {
+ if (reportEnd == reportFind) {
+ reported->push_back(subtopic);
}
}
}
}
- return true;
+ if (!containsMarkTypeIn) {
+ PRINTF("No #In: %s\n", csChild->fName.c_str());
+ }
}
+ bool checkRelatedFunctions() {
+ const Definition* cs = this->classOrStruct();
+ if (!cs) {
+ return true;
+ }
+ const Definition* topic = cs->fParent;
+ SkASSERT(topic);
+ SkASSERT(MarkType::kTopic == topic->fMarkType);
+ string topicName = topic->fName;
+ vector<string> methodNames;
+ vector<string> reported;
+ string prefix = cs->fName + "::";
+ for (auto& csChild : cs->fChildren) {
+ checkMethod(topicName, csChild, &reported);
+ }
+ for (auto missing : reported) {
+ string fullname = topicName + '_' + missing;
+ PRINTF("No #Subtopic: %s\n", fullname.c_str());
+ }
+ return true;
+ }
+
bool checkSeeAlso() {
return true;
}
- bool checkSubtopicContents() {
- return true;
- }
+ const Definition* classOrStruct() {
+ for (auto& rootChild : fRoot->fChildren) {
+ if (rootChild->isStructOrClass()) {
+ return rootChild;
+ }
+ }
+ return nullptr;
+ }
+
+ enum class Optional {
+ kNo,
+ kYes,
+ };
private:
const BmhParser& fBmhParser;
diff --git a/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp b/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
index 838e44ec6e8..e5ad7463796 100644
--- a/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
@@ -53,7 +53,6 @@ private:
INHERITED::resetCommon();
fMethod = nullptr;
fRoot = nullptr;
- fTableState = TableState::kNone;
fInCode = false;
fInConst = false;
fInFormula = false;
@@ -74,7 +73,7 @@ private:
const BmhParser& fBmhParser;
Definition* fMethod;
RootDefinition* fRoot;
- TableState fTableState;
+ int fLocalLine;
bool fInCode;
bool fInConst;
bool fInDescription;
@@ -136,10 +135,6 @@ bool SpellCheck::check(Definition* def) {
fLineCount = def->fLineCount;
string printable = def->printableName();
const char* textStart = def->fContentStart;
- if (MarkType::kParam != def->fMarkType && MarkType::kConst != def->fMarkType &&
- MarkType::kPrivate != def->fMarkType && TableState::kNone != fTableState) {
- fTableState = TableState::kNone;
- }
switch (def->fMarkType) {
case MarkType::kAlias:
break;
@@ -159,12 +154,6 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kConst: {
fInConst = true;
- if (TableState::kNone == fTableState) {
- fTableState = TableState::kRow;
- }
- if (TableState::kRow == fTableState) {
- fTableState = TableState::kColumn;
- }
this->wordCheck(def->fName);
const char* lineEnd = strchr(textStart, '\n');
this->wordCheck(lineEnd - textStart, textStart);
@@ -187,8 +176,6 @@ bool SpellCheck::check(Definition* def) {
case MarkType::kEnumClass:
this->wordCheck(def->fName);
break;
- case MarkType::kError:
- break;
case MarkType::kExample:
break;
case MarkType::kExperimental:
@@ -204,10 +191,16 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kHeight:
break;
+ case MarkType::kIllustration:
+ break;
case MarkType::kImage:
break;
+ case MarkType::kIn:
+ break;
case MarkType::kLegend:
break;
+ case MarkType::kLine:
+ break;
case MarkType::kLink:
break;
case MarkType::kList:
@@ -223,11 +216,9 @@ bool SpellCheck::check(Definition* def) {
if (all_lower(method_name)) {
method_name += "()";
}
- string formattedStr = def->formatFunction();
if (!def->isClone() && Definition::MethodType::kOperator != def->fMethodType) {
this->wordCheck(method_name);
}
- fTableState = TableState::kNone;
fMethod = def;
} break;
case MarkType::kNoExample:
@@ -235,12 +226,6 @@ bool SpellCheck::check(Definition* def) {
case MarkType::kOutdent:
break;
case MarkType::kParam: {
- if (TableState::kNone == fTableState) {
- fTableState = TableState::kRow;
- }
- if (TableState::kRow == fTableState) {
- fTableState = TableState::kColumn;
- }
TextParser paramParser(def->fFileName, def->fStart, def->fContentStart,
def->fLineCount);
paramParser.skipWhiteSpace();
@@ -256,6 +241,8 @@ bool SpellCheck::check(Definition* def) {
} break;
case MarkType::kPlatform:
break;
+ case MarkType::kPopulate:
+ break;
case MarkType::kPrivate:
break;
case MarkType::kReturn:
@@ -264,6 +251,8 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kSeeAlso:
break;
+ case MarkType::kSet:
+ break;
case MarkType::kStdOut: {
fInStdOut = true;
TextParser code(def);
@@ -338,8 +327,6 @@ bool SpellCheck::check(Definition* def) {
case MarkType::kConst:
fInConst = false;
case MarkType::kParam:
- SkASSERT(TableState::kColumn == fTableState);
- fTableState = TableState::kRow;
break;
case MarkType::kReturn:
case MarkType::kSeeAlso:
@@ -392,6 +379,7 @@ void SpellCheck::leafCheck(const char* start, const char* end) {
const char* wordStart = nullptr;
const char* wordEnd = nullptr;
const char* possibleEnd = nullptr;
+ fLocalLine = 0;
do {
if (wordStart && wordEnd) {
if (!allLower || (!inQuotes && '\"' != lastCh && !inParens
@@ -459,6 +447,9 @@ void SpellCheck::leafCheck(const char* start, const char* end) {
allLower = false;
case '-': // note that dash doesn't clear allLower
break;
+ case '\n':
+ ++fLocalLine;
+ // fall through
default:
wordEnd = chPtr;
break;
@@ -494,7 +485,8 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) {
continue;
}
if (iter.second.fCount == 1) {
- SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine,
+ string fullName = this->ReportFilename(iter.second.fFile);
+ SkDebugf("%s(%d): %s\n", fullName.c_str(), iter.second.fLine,
iter.first.c_str());
}
}
@@ -564,7 +556,8 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) {
break;
}
if (check.compare(mispelled) == 0) {
- SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine,
+ string fullName = this->ReportFilename(iter.second.fFile);
+ SkDebugf("%s(%d): %s\n", fullName.c_str(), iter.second.fLine,
iter.first.c_str());
if (report.count() == ++index) {
break;
@@ -655,7 +648,7 @@ void SpellCheck::wordCheck(const string& str) {
} else {
CheckEntry* entry = &mappy[str];
entry->fFile = fFileName;
- entry->fLine = fLineCount;
+ entry->fLine = fLineCount + fLocalLine;
entry->fCount = 1;
}
}
diff --git a/chromium/third_party/skia/tools/check-headers-self-sufficient b/chromium/third_party/skia/tools/check-headers-self-sufficient
index 9b676c1094c..fe58b63fb4d 100755
--- a/chromium/third_party/skia/tools/check-headers-self-sufficient
+++ b/chromium/third_party/skia/tools/check-headers-self-sufficient
@@ -77,7 +77,6 @@ all_header_args = [
'-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',
diff --git a/chromium/third_party/skia/tools/colorspaceinfo.cpp b/chromium/third_party/skia/tools/colorspaceinfo.cpp
index 390f7cc4cb1..2873e46508d 100644
--- a/chromium/third_party/skia/tools/colorspaceinfo.cpp
+++ b/chromium/third_party/skia/tools/colorspaceinfo.cpp
@@ -518,7 +518,7 @@ int main(int argc, char** argv) {
return ss.str();
};
- if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type()) {
+ if (colorSpace->toXYZD50()) {
SkDebugf("XYZ/TRC color space\n");
// Load a graph of the CIE XYZ color gamut.
diff --git a/chromium/third_party/skia/tools/debugger/SkDrawCommand.cpp b/chromium/third_party/skia/tools/debugger/SkDrawCommand.cpp
index 34189fa6a46..57666891033 100644
--- a/chromium/third_party/skia/tools/debugger/SkDrawCommand.cpp
+++ b/chromium/third_party/skia/tools/debugger/SkDrawCommand.cpp
@@ -15,7 +15,7 @@
#include "SkDashPathEffect.h"
#include "SkImageFilter.h"
#include "SkJsonWriteBuffer.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkObjectParser.h"
#include "SkPaintDefaults.h"
#include "SkPathEffect.h"
@@ -922,7 +922,7 @@ static SkBitmap* load_bitmap(const Json::Value& jsonBitmap, UrlDataManager& urlD
std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
if (nullptr != image) {
- if (!image->asLegacyBitmap(bitmap.get(), SkImage::kRW_LegacyBitmapMode)) {
+ if (!image->asLegacyBitmap(bitmap.get())) {
SkDebugf("image decode failed\n");
return nullptr;
}
@@ -1071,8 +1071,8 @@ 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)) {
+ SkMaskFilterBase::BlurRec blurRec;
+ if (as_MFB(maskFilter)->asABlur(&blurRec)) {
Json::Value blur(Json::objectValue);
blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
switch (blurRec.fStyle) {
diff --git a/chromium/third_party/skia/tools/debugger/SkObjectParser.cpp b/chromium/third_party/skia/tools/debugger/SkObjectParser.cpp
index 352a01da237..dae2cde92e5 100644
--- a/chromium/third_party/skia/tools/debugger/SkObjectParser.cpp
+++ b/chromium/third_party/skia/tools/debugger/SkObjectParser.cpp
@@ -349,9 +349,6 @@ SkString* SkObjectParser::RegionToString(const SkRegion& region) {
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 ");
}
diff --git a/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp b/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
index 4ba84f38ca0..9ade250b0ae 100644
--- a/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
+++ b/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
@@ -133,7 +133,7 @@ static bool setup_backend_objects(GrContext* context,
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;
- backingDesc.fSampleCnt = 0;
+ backingDesc.fSampleCnt = 1;
if (!bm.empty()) {
SkPixmap originalPixmap;
@@ -265,7 +265,7 @@ int main(int argc, char** argv) {
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;
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp b/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
index dd3a855d3fc..4f895058abd 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
@@ -31,13 +31,13 @@ DEFINE_bool(simpleCodec, false, "Runs of a subset of the codec tests. "
"For nanobench, this means always N32, Premul or Opaque.");
DEFINE_string2(match, m, nullptr,
- "[~][^]substring[$] [...] of GM name to run.\n"
+ "[~][^]substring[$] [...] of 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"
+ "~ 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 GM does not match any list entry,\n"
+ "If a name 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.");
@@ -50,9 +50,21 @@ DEFINE_bool(releaseAndAbandonGpuContext, false,
"Test releasing all gpu resources and abandoning the GrContext after running each "
"test");
+DEFINE_bool(disableDriverCorrectnessWorkarounds, false, "Disables all GPU driver correctness "
+ "workarounds");
+
+#ifdef SK_BUILD_FOR_ANDROID
+DEFINE_string(skps, "/data/local/tmp/skps", "Directory to read skps from.");
+DEFINE_string(jpgs, "/data/local/tmp/resources", "Directory to read jpgs from.");
+DEFINE_string(jsons, "/data/local/tmp/jsons", "Directory to read (Bodymovin) jsons from.");
+#else
DEFINE_string(skps, "skps", "Directory to read skps from.");
+DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
+DEFINE_string(jsons, "jsons", "Directory to read (Bodymovin) jsons from.");
+#endif
-DEFINE_string(jsons, "", "Directory to read Bodymovin JSONs from, or a single JSON file.");
+DEFINE_bool(nativeFonts, true, "If true, use native font manager and rendering. "
+ "If false, fonts will draw as portably as possible.");
DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
@@ -87,6 +99,9 @@ DEFINE_bool(deltaAA, kDefaultDeltaAA,
DEFINE_bool(forceDeltaAA, false, "Force delta anti-aliasing for all paths.");
+DEFINE_int32(backendTiles, 3, "Number of tiles in the experimental threaded backend.");
+DEFINE_int32(backendThreads, 2, "Number of threads in the experimental threaded backend.");
+
bool CollectImages(SkCommandLineFlags::StringArray images, SkTArray<SkString>* output) {
SkASSERT(output);
@@ -156,6 +171,7 @@ void SetCtxOptionsFromCommonFlags(GrContextOptions* ctxOptions) {
ctxOptions->fAllowPathMaskCaching = FLAGS_cachePathMasks;
ctxOptions->fSuppressGeometryShaders = FLAGS_noGS;
ctxOptions->fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+ ctxOptions->fDisableDriverCorrectnessWorkarounds = FLAGS_disableDriverCorrectnessWorkarounds;
}
#endif
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlags.h b/chromium/third_party/skia/tools/flags/SkCommonFlags.h
index a3eb0011001..1f0c8d14f81 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlags.h
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlags.h
@@ -25,8 +25,10 @@ DECLARE_bool(abandonGpuContext);
DECLARE_bool(releaseAndAbandonGpuContext);
DECLARE_string(skps);
DECLARE_bool(ddl);
+DECLARE_string(jpgs);
DECLARE_string(jsons);
DECLARE_string(svgs);
+DECLARE_bool(nativeFonts);
DECLARE_int32(threads);
DECLARE_string(resourcePath);
DECLARE_bool(verbose);
@@ -39,6 +41,8 @@ DECLARE_bool(deltaAA);
DECLARE_bool(forceDeltaAA);
DECLARE_string(key);
DECLARE_string(properties);
+DECLARE_int32(backendTiles);
+DECLARE_int32(backendThreads)
/**
* Helper to assist in collecting image paths from |dir| specified through a command line flag.
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp b/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
index 00db61a2406..f9988f8769a 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
@@ -5,7 +5,6 @@
* found in the LICENSE file.
*/
-#include "SkColorSpace_Base.h"
#include "SkCommonFlagsConfig.h"
#include "SkImageInfo.h"
@@ -43,18 +42,7 @@ static const struct {
{ "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" },
@@ -67,6 +55,7 @@ static const struct {
{ "glwide", "gpu", "api=gl,color=f16_wide" },
{ "glnarrow", "gpu", "api=gl,color=f16_narrow" },
{ "glnostencils", "gpu", "api=gl,stencils=false" },
+ { "gles4444", "gpu", "api=gles,color=4444" },
{ "glessrgb", "gpu", "api=gles,color=srgb" },
{ "gleswide", "gpu", "api=gles,color=f16_wide" },
{ "glesnarrow", "gpu", "api=gles,color=f16_narrow" },
@@ -399,7 +388,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
bool seenUseDIText =false;
bool useDIText = false;
bool seenSamples = false;
- int samples = 0;
+ int samples = 1;
bool seenColor = false;
SkColorType colorType = kRGBA_8888_SkColorType;
SkAlphaType alphaType = kPremul_SkAlphaType;
diff --git a/chromium/third_party/skia/tools/SkRandomScalerContext.cpp b/chromium/third_party/skia/tools/fonts/SkRandomScalerContext.cpp
index 49d9ab43ffd..31a85b783ea 100644
--- a/chromium/third_party/skia/tools/SkRandomScalerContext.cpp
+++ b/chromium/third_party/skia/tools/fonts/SkRandomScalerContext.cpp
@@ -12,7 +12,6 @@
#include "SkMakeUnique.h"
#include "SkPath.h"
#include "SkRandomScalerContext.h"
-#include "SkRasterizer.h"
class SkDescriptor;
diff --git a/chromium/third_party/skia/tools/SkRandomScalerContext.h b/chromium/third_party/skia/tools/fonts/SkRandomScalerContext.h
index b71689d9e2d..b71689d9e2d 100644
--- a/chromium/third_party/skia/tools/SkRandomScalerContext.h
+++ b/chromium/third_party/skia/tools/fonts/SkRandomScalerContext.h
diff --git a/chromium/third_party/skia/tools/fonts/SkTestFontMgr.cpp b/chromium/third_party/skia/tools/fonts/SkTestFontMgr.cpp
new file mode 100644
index 00000000000..3b5d1589f2b
--- /dev/null
+++ b/chromium/third_party/skia/tools/fonts/SkTestFontMgr.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "SkFontDescriptor.h"
+#include "SkTestFontMgr.h"
+#include "sk_tool_utils.h"
+
+namespace {
+
+static constexpr const char* kFamilyNames[] = {
+ "Toy Liberation Sans",
+ "Toy Liberation Serif",
+ "Toy Liberation Mono",
+};
+
+class FontStyleSet final : public SkFontStyleSet {
+public:
+ explicit FontStyleSet(int familyIndex) {
+ using sk_tool_utils::create_portable_typeface;
+ const char* familyName = kFamilyNames[familyIndex];
+
+ fTypefaces[0] = create_portable_typeface(familyName, SkFontStyle::Normal());
+ fTypefaces[1] = create_portable_typeface(familyName, SkFontStyle::Bold());
+ fTypefaces[2] = create_portable_typeface(familyName, SkFontStyle::Italic());
+ fTypefaces[3] = create_portable_typeface(familyName, SkFontStyle::BoldItalic());
+ }
+
+ int count() override { return 4; }
+
+ void getStyle(int index, SkFontStyle* style, SkString* name) override {
+ switch (index) {
+ default:
+ case 0: if (style) { *style = SkFontStyle::Normal(); }
+ if (name) { *name = "Normal"; }
+ break;
+ case 1: if (style) { *style = SkFontStyle::Bold(); }
+ if (name) { *name = "Bold"; }
+ break;
+ case 2: if (style) { *style = SkFontStyle::Italic(); }
+ if (name) { *name = "Italic"; }
+ break;
+ case 3: if (style) { *style = SkFontStyle::BoldItalic(); }
+ if (name) { *name = "BoldItalic"; }
+ break;
+ }
+ }
+
+ SkTypeface* createTypeface(int index) override {
+ return SkRef(fTypefaces[index].get());
+ }
+
+ SkTypeface* matchStyle(const SkFontStyle& pattern) override {
+ return this->matchStyleCSS3(pattern);
+ }
+
+private:
+ sk_sp<SkTypeface> fTypefaces[4];
+};
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
+
+class FontMgr final : public SkFontMgr {
+public:
+ FontMgr() {
+ fFamilies[0] = sk_make_sp<FontStyleSet>(0);
+ fFamilies[1] = sk_make_sp<FontStyleSet>(1);
+ fFamilies[2] = sk_make_sp<FontStyleSet>(2);
+ }
+
+ int onCountFamilies() const override { return SK_ARRAY_COUNT(fFamilies); }
+
+ void onGetFamilyName(int index, SkString* familyName) const override {
+ *familyName = kFamilyNames[index];
+ }
+
+ SkFontStyleSet* onCreateStyleSet(int index) const override {
+ return SkRef(fFamilies[index].get());
+ }
+
+ SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
+ if (familyName) {
+ if (strstr(familyName, "ans")) { return this->createStyleSet(0); }
+ if (strstr(familyName, "erif")) { return this->createStyleSet(1); }
+ if (strstr(familyName, "ono")) { return this->createStyleSet(2); }
+ }
+ return this->createStyleSet(0);
+ }
+
+
+ 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 {
+ return sk_sp<SkTypeface>(this->matchFamilyStyle(familyName, style));
+ }
+
+private:
+ sk_sp<FontStyleSet> fFamilies[3];
+};
+}
+
+namespace sk_tool_utils {
+sk_sp<SkFontMgr> MakePortableFontMgr() { return sk_make_sp<FontMgr>(); }
+} // namespace sk_tool_utils
diff --git a/chromium/third_party/skia/tools/fonts/SkTestFontMgr.h b/chromium/third_party/skia/tools/fonts/SkTestFontMgr.h
new file mode 100644
index 00000000000..6f4bb9c3c0c
--- /dev/null
+++ b/chromium/third_party/skia/tools/fonts/SkTestFontMgr.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 SkTestFontMgr_DEFINED
+#define SkTestFontMgr_DEFINED
+
+#include "SkFontMgr.h"
+
+// An SkFontMgr that always uses sk_tool_utils::create_portable_typeface().
+
+namespace sk_tool_utils {
+ sk_sp<SkFontMgr> MakePortableFontMgr();
+} // namespace sk_tool_utils
+
+#endif //SkTestFontMgr_DEFINED
diff --git a/chromium/third_party/skia/tools/SkTestScalerContext.cpp b/chromium/third_party/skia/tools/fonts/SkTestScalerContext.cpp
index f74b1bd57ac..f74b1bd57ac 100644
--- a/chromium/third_party/skia/tools/SkTestScalerContext.cpp
+++ b/chromium/third_party/skia/tools/fonts/SkTestScalerContext.cpp
diff --git a/chromium/third_party/skia/tools/SkTestScalerContext.h b/chromium/third_party/skia/tools/fonts/SkTestScalerContext.h
index e62210b2e30..e62210b2e30 100644
--- a/chromium/third_party/skia/tools/SkTestScalerContext.h
+++ b/chromium/third_party/skia/tools/fonts/SkTestScalerContext.h
diff --git a/chromium/third_party/skia/tools/create_test_font.cpp b/chromium/third_party/skia/tools/fonts/create_test_font.cpp
index 4fd8dbbdbb0..51c56eaee1f 100644
--- a/chromium/third_party/skia/tools/create_test_font.cpp
+++ b/chromium/third_party/skia/tools/fonts/create_test_font.cpp
@@ -5,10 +5,10 @@
* found in the LICENSE file.
*/
-// running create_test_font generates ./tools/test_font_index.inc
-// and ./tools/test_font_<generic name>.inc which are read by ./tools/sk_tool_utils_font.cpp
+// 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/sk_tool_utils_font.cpp
-#include "Resources.h"
#include "SkFontStyle.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
@@ -72,6 +72,7 @@ const char gHeader[] =
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 {
@@ -430,7 +431,7 @@ static void generate_index(const char* defaultName) {
}
int main(int , char * const []) {
- generate_fonts("/Library/Fonts/");
+ generate_fonts("/Library/Fonts/"); // or /usr/share/fonts/truetype/ttf-liberation/
generate_index(DEFAULT_FONT_NAME);
return 0;
}
diff --git a/chromium/third_party/skia/tools/generate_fir_coeff.py b/chromium/third_party/skia/tools/fonts/generate_fir_coeff.py
index 70f521fdafc..f5cc5e55a07 100644
--- a/chromium/third_party/skia/tools/generate_fir_coeff.py
+++ b/chromium/third_party/skia/tools/fonts/generate_fir_coeff.py
@@ -28,18 +28,26 @@ def withinStdDevRange(a, b):
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.
-
-#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.
+# 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.
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 @@ for sample_offset, sample_align in sample_offsets:
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 @@ for sample_offset, sample_align in sample_offsets:
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 @@ for sample_offset, sample_align in sample_offsets:
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/chromium/third_party/skia/tools/fonts/sk_tool_utils_font.cpp b/chromium/third_party/skia/tools/fonts/sk_tool_utils_font.cpp
new file mode 100644
index 00000000000..d2aac851bbb
--- /dev/null
+++ b/chromium/third_party/skia/tools/fonts/sk_tool_utils_font.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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 "SkCommonFlags.h"
+#include "SkFontMgr.h"
+#include "SkFontStyle.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 fm->legacyMakeTypeface(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);
+ fontData->fCachedFont = font;
+ }
+ }
+ return sk_make_sp<SkTestTypeface>(std::move(font), style);
+}
+
+sk_sp<SkTypeface> emoji_typeface() {
+#if defined(SK_BUILD_FOR_WIN)
+ 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());
+
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle());
+
+#else
+ return MakeResourceAsTypeface("fonts/Funkster.ttf");
+
+#endif
+}
+
+const char* emoji_sample_text() {
+#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ 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"; // 🇺🇸🇦
+#else
+ return "Hamburgefons";
+#endif
+}
+
+static 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];
+ }
+ }
+ return "";
+}
+
+static bool extra_config_contains(const char* substring) {
+ for (int index = 0; index < FLAGS_key.count(); index += 2) {
+ if (0 == strcmp("extra_config", FLAGS_key[index])
+ && strstr(FLAGS_key[index + 1], substring)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+const char* platform_font_manager() {
+ if (extra_config_contains("GDI")) {
+ return "GDI";
+ }
+ if (extra_config_contains("NativeFonts")){
+ return platform_os_name();
+ }
+ return "";
+}
+
+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));
+}
+
+}
diff --git a/chromium/third_party/skia/tools/test_font_index.inc b/chromium/third_party/skia/tools/fonts/test_font_index.inc
index aedfcde271a..aedfcde271a 100644
--- a/chromium/third_party/skia/tools/test_font_index.inc
+++ b/chromium/third_party/skia/tools/fonts/test_font_index.inc
diff --git a/chromium/third_party/skia/tools/test_font_monospace.inc b/chromium/third_party/skia/tools/fonts/test_font_monospace.inc
index 60bcd6978ac..a8e2c4ce5bd 100644
--- a/chromium/third_party/skia/tools/test_font_monospace.inc
+++ b/chromium/third_party/skia/tools/fonts/test_font_monospace.inc
@@ -1193,9 +1193,8 @@ const SkFixed LiberationMonoNormalWidths[] = {
const int LiberationMonoNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoNormalCharCodes);
const SkPaint::FontMetrics LiberationMonoNormalMetrics = {
-0x0000000f, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.600098f, 0.00989532f,
--0.0244141f, 0.608887f, 0.52832f, 0.0102921f, 0.0410156f, 0.23291f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -2344,9 +2343,8 @@ const SkFixed LiberationMonoBoldWidths[] = {
const int LiberationMonoBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoBoldCharCodes);
const SkPaint::FontMetrics LiberationMonoBoldMetrics = {
-0x0000000f, -0.833496f, -0.833496f, 0.300293f, 0.300293f, 0, 0.600098f, 0.010025f,
--0.0268555f, 0.614746f, 0.52832f, 0.0102921f, 0.100098f, 0.23291f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -3611,9 +3609,8 @@ const SkFixed LiberationMonoItalicWidths[] = {
const int LiberationMonoItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoItalicCharCodes);
const SkPaint::FontMetrics LiberationMonoItalicMetrics = {
-0x0000000f, -0.833496f, -0.833496f, 0.300293f, 0.300293f, 0, 0.600098f, 0.0124817f,
--0.0942383f, 0.70459f, 0.52832f, 0.0102921f, 0.0410156f, 0.23291f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -4845,8 +4842,7 @@ const SkFixed LiberationMonoBoldItalicWidths[] = {
const int LiberationMonoBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationMonoBoldItalicCharCodes);
const SkPaint::FontMetrics LiberationMonoBoldItalicMetrics = {
-0x0000000f, -0.83252f, -0.83252f, 0.300293f, 0.300293f, 0, 0.600098f, 0.0123749f,
--0.0942383f, 0.697754f, 0.52832f, 0.0102921f, 0.100098f, 0.23291f, 0.000778198f,
--0.00404358f
+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/chromium/third_party/skia/tools/test_font_sans_serif.inc b/chromium/third_party/skia/tools/fonts/test_font_sans_serif.inc
index 2011c5f8102..8bdfb33d2d3 100644
--- a/chromium/third_party/skia/tools/test_font_sans_serif.inc
+++ b/chromium/third_party/skia/tools/fonts/test_font_sans_serif.inc
@@ -1187,9 +1187,8 @@ const SkFixed LiberationSansNormalWidths[] = {
const int LiberationSansNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansNormalCharCodes);
const SkPaint::FontMetrics LiberationSansNormalMetrics = {
-0x0000000f, -0.910156f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.589355f, 0.0195847f,
--0.203125f, 1.05029f, 0.52832f, 0.0107498f, 0.0732422f, 0.105957f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -2352,8 +2351,8 @@ const SkFixed LiberationSansBoldWidths[] = {
const int LiberationSansBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansBoldCharCodes);
const SkPaint::FontMetrics LiberationSansBoldMetrics = {
-0x0000000f, -1.0332f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.612305f, 0.0194702f,
--0.184082f, 1.06201f, 0.52832f, 0.0107498f, 0.10498f, 0.105957f, 0.000778198f, -0.00404358f
+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[] = {
@@ -3593,8 +3592,8 @@ const SkFixed LiberationSansItalicWidths[] = {
const int LiberationSansItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansItalicCharCodes);
const SkPaint::FontMetrics LiberationSansItalicMetrics = {
-0x0000000f, -1.01416f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.590332f, 0.0208511f,
--0.271973f, 1.0625f, 0.52832f, 0.0107498f, 0.0732422f, 0.105957f, 0.000778198f, -0.00404358f
+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[] = {
@@ -4853,7 +4852,7 @@ const SkFixed LiberationSansBoldItalicWidths[] = {
const int LiberationSansBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSansBoldItalicCharCodes);
const SkPaint::FontMetrics LiberationSansBoldItalicMetrics = {
-0x0000000f, -1.02979f, -0.905273f, 0.211914f, 0.303223f, 0.0327148f, 0.61377f, 0.0208969f,
--0.208984f, 1.12842f, 0.52832f, 0.0107498f, 0.10498f, 0.105957f, 0.000778198f, -0.00404358f
+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/chromium/third_party/skia/tools/test_font_serif.inc b/chromium/third_party/skia/tools/fonts/test_font_serif.inc
index 8035fb8f26b..4c7121c72de 100644
--- a/chromium/third_party/skia/tools/test_font_serif.inc
+++ b/chromium/third_party/skia/tools/fonts/test_font_serif.inc
@@ -1264,9 +1264,8 @@ const SkFixed LiberationSerifNormalWidths[] = {
const int LiberationSerifNormalCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifNormalCharCodes);
const SkPaint::FontMetrics LiberationSerifNormalMetrics = {
-0x0000000f, -0.981445f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.567383f, 0.0184937f,
--0.176758f, 1.00684f, 0.458984f, 0.010231f, 0.0488281f, 0.108887f, 0.000762939f,
--0.00320435f
+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[] = {
@@ -2515,9 +2514,8 @@ const SkFixed LiberationSerifBoldWidths[] = {
const int LiberationSerifBoldCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifBoldCharCodes);
const SkPaint::FontMetrics LiberationSerifBoldMetrics = {
-0x0000000f, -1.00781f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.59375f, 0.0197983f,
--0.182129f, 1.08496f, 0.458984f, 0.010231f, 0.0952148f, 0.108887f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -3834,9 +3832,8 @@ const SkFixed LiberationSerifItalicWidths[] = {
const int LiberationSerifItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifItalicCharCodes);
const SkPaint::FontMetrics LiberationSerifItalicMetrics = {
-0x0000000f, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.559082f, 0.0197601f,
--0.176758f, 1.08789f, 0.458984f, 0.010231f, 0.0488281f, 0.108887f, 0.000778198f,
--0.00404358f
+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[] = {
@@ -5147,8 +5144,7 @@ const SkFixed LiberationSerifBoldItalicWidths[] = {
const int LiberationSerifBoldItalicCharCodesCount = (int) SK_ARRAY_COUNT(LiberationSerifBoldItalicCharCodes);
const SkPaint::FontMetrics LiberationSerifBoldItalicMetrics = {
-0x0000000f, -0.980957f, -0.891113f, 0.216309f, 0.303223f, 0.0424805f, 0.578125f, 0.0207596f,
--0.178223f, 1.15039f, 0.458984f, 0.010231f, 0.0952148f, 0.108887f, 0.000778198f,
--0.00404358f
+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/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
index c6cceb48430..36926062475 100644
--- a/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
@@ -25,7 +25,7 @@
#include "mock/MockTestContext.h"
#include "GrCaps.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.
diff --git a/chromium/third_party/skia/tools/gpu/GrTest.cpp b/chromium/third_party/skia/tools/gpu/GrTest.cpp
index f5115747260..c6d3bbe2ef4 100644
--- a/chromium/third_party/skia/tools/gpu/GrTest.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrTest.cpp
@@ -147,17 +147,18 @@ void GrContext::printGpuStats() const {
SkDebugf("%s", out.c_str());
}
-sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format) {
- GrAtlasGlyphCache* cache = this->getAtlasGlyphCache();
+sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format, uint32_t index) {
+ GrAtlasGlyphCache* cache = this->contextPriv().getAtlasGlyphCache();
- const sk_sp<GrTextureProxy>* proxies = cache->getProxies(format);
- if (!proxies[0]) {
+ unsigned int numProxies;
+ const sk_sp<GrTextureProxy>* proxies = cache->getProxies(format, &numProxies);
+ if (index >= numProxies || !proxies[index]) {
return nullptr;
}
- SkASSERT(proxies[0]->priv().isExact());
+ SkASSERT(proxies[index]->priv().isExact());
sk_sp<SkImage> image(new SkImage_Gpu(this, kNeedNewImageUniqueID, kPremul_SkAlphaType,
- std::move(proxies[0]), nullptr, SkBudgeted::kNo));
+ proxies[index], nullptr, SkBudgeted::kNo));
return image;
}
@@ -182,6 +183,16 @@ void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>*
#endif
+GrBackendTexture GrGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
+ SkColorType colorType, bool isRenderTarget,
+ GrMipMapped mipMapped) {
+ GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
+ if (kUnknown_GrPixelConfig == config) {
+ return GrBackendTexture();
+ }
+ return this->createTestingOnlyBackendTexture(pixels, w, h, config, isRenderTarget, mipMapped);
+}
+
#if GR_CACHE_STATS
void GrResourceCache::getStats(Stats* stats) const {
stats->reset();
@@ -298,6 +309,16 @@ void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallback
//////////////////////////////////////////////////////////////////////////////
+GrPixelConfig GrBackendTexture::testingOnly_getPixelConfig() const {
+ return fConfig;
+}
+
+GrPixelConfig GrBackendRenderTarget::testingOnly_getPixelConfig() const {
+ return fConfig;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
#define DRAW_OP_TEST_EXTERN(Op) \
extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType)
#define DRAW_OP_TEST_ENTRY(Op) Op##__Test
diff --git a/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp b/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
index 4152997b4d9..2b056933661 100644
--- a/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
@@ -102,6 +102,12 @@ public:
this->setTexture(texture);
}
+ GrGLboolean isTexture(GrGLuint textureID) override {
+ GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
+
+ return texture ? GR_GL_TRUE : GR_GL_FALSE;
+ }
+
////////////////////////////////////////////////////////////////////////////////
GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
GrGLenum usage) override {
diff --git a/chromium/third_party/skia/tools/gpu/vk/GrVulkanDefines.h b/chromium/third_party/skia/tools/gpu/vk/GrVulkanDefines.h
index 192f1c5abce..2eb49208fa8 100644
--- a/chromium/third_party/skia/tools/gpu/vk/GrVulkanDefines.h
+++ b/chromium/third_party/skia/tools/gpu/vk/GrVulkanDefines.h
@@ -8,7 +8,7 @@
#ifndef GrVulkanDefines_DEFINED
#define GrVulkanDefines_DEFINED
-#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_WIN32)
+#if defined(SK_BUILD_FOR_WIN)
# if !defined(VK_USE_PLATFORM_WIN32_KHR)
# define VK_USE_PLATFORM_WIN32_KHR
# endif
diff --git a/chromium/third_party/skia/tools/install_dependencies.sh b/chromium/third_party/skia/tools/install_dependencies.sh
index 9d1a45fa157..0cf879e43e4 100755
--- a/chromium/third_party/skia/tools/install_dependencies.sh
+++ b/chromium/third_party/skia/tools/install_dependencies.sh
@@ -23,15 +23,16 @@ dpkg_all_installed() {
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
- libpng12-dev
+ libpng-dev
libqt4-dev
EOF
)
diff --git a/chromium/third_party/skia/tools/list_gms.cpp b/chromium/third_party/skia/tools/list_gms.cpp
new file mode 100644
index 00000000000..dde7f471b6f
--- /dev/null
+++ b/chromium/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.h"
+
+int main() {
+ std::vector<std::string> gms;
+ for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
+ std::unique_ptr<skiagm::GM> gm(r->factory()(nullptr));
+ 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/chromium/third_party/skia/tools/list_gpu_unit_tests.cpp b/chromium/third_party/skia/tools/list_gpu_unit_tests.cpp
new file mode 100644
index 00000000000..18127b6950a
--- /dev/null
+++ b/chromium/third_party/skia/tools/list_gpu_unit_tests.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "Test.h"
+
+int main() {
+ std::vector<std::string> tests;
+ for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
+ const skiatest::Test& test = r->factory();
+ 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/chromium/third_party/skia/tools/ok.cpp b/chromium/third_party/skia/tools/ok.cpp
deleted file mode 100644
index 29c2a224f1e..00000000000
--- a/chromium/third_party/skia/tools/ok.cpp
+++ /dev/null
@@ -1,389 +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 <list>
-#include <stdio.h>
-#include <stdlib.h>
-#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>)
- #include <execinfo.h>
-
- #define CAN_BACKTRACE
- static void backtrace(int fd) {
- void* stack[128];
- int frames = backtrace(stack, sizeof(stack)/sizeof(*stack));
- backtrace_symbols_fd(stack, frames, fd);
- }
-
-#elif __has_include(<dlfcn.h>) && __has_include(<unwind.h>)
- #include <cxxabi.h>
- #include <dlfcn.h>
- #include <unwind.h>
-
- #define CAN_BACKTRACE
- static void backtrace(int fd) {
- FILE* file = fdopen(fd, "a");
- _Unwind_Backtrace([](_Unwind_Context* ctx, void* arg) {
- auto file = (FILE*)arg;
- if (auto ip = (void*)_Unwind_GetIP(ctx)) {
- const char* name = "[unknown]";
- void* addr = nullptr;
- Dl_info info;
- if (dladdr(ip, &info) && info.dli_sname && info.dli_saddr) {
- name = info.dli_sname;
- addr = info.dli_saddr;
- }
-
- int ok;
- char* demangled = abi::__cxa_demangle(name, nullptr,0, &ok);
- if (ok == 0 && demangled) {
- name = demangled;
- }
-
- fprintf(file, "\t%p %s+%zu\n", ip, name, (size_t)ip - (size_t)addr);
- free(demangled);
- }
- return _URC_NO_REASON;
- }, file);
- fflush(file);
- }
-#endif
-
-#if defined(CAN_BACKTRACE) && __has_include(<fcntl.h>) && __has_include(<signal.h>)
- #include <fcntl.h>
- #include <signal.h>
-
- // We'd ordinarily just use lockf(), but fcntl() is more portable to older Android NDK APIs.
- static void lock_or_unlock_fd(int fd, short type) {
- struct flock fl{};
- fl.l_type = type;
- fl.l_whence = SEEK_CUR;
- fl.l_start = 0;
- fl.l_len = 0; // 0 == the entire file
- fcntl(fd, F_SETLKW, &fl);
- }
- static void lock_fd(int fd) { lock_or_unlock_fd(fd, F_WRLCK); }
- static void unlock_fd(int fd) { lock_or_unlock_fd(fd, F_UNLCK); }
-
- 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) {
- lock_fd(log_fd);
- 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");
- backtrace(log_fd);
- unlock_fd(log_fd);
-
- 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) {
- lock_fd(log_fd);
- log("[");
- log(tls_currently_running);
- log("]\t");
- log(msg);
- log("\n");
- unlock_fd(log_fd);
- }
-
-#else
- static void setup_crash_handler() {}
- static void defer_logging() {}
-
- void ok_log(const char* msg) {
- fprintf(stderr, "[%s]\t%s\n", tls_currently_running, msg);
- }
-#endif
-
-struct EngineType {
- const char *name, *help;
- std::unique_ptr<Engine> (*factory)(Options);
-};
-static std::vector<EngineType> engine_types;
-
-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();
-
- std::unique_ptr<Engine> engine;
- 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 engine_help = help_for(engine_types),
- stream_help = help_for(stream_types),
- dst_help = help_for( dst_types),
- via_help = help_for( via_types);
-
- printf("%s [engine] src[:k=v,...] dst[:k=v,...] [via[:k=v,...] ...] \n"
- " engine: how to execute tasks%s \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],
- engine_help.c_str(), stream_help.c_str(), dst_help.c_str(), via_help.c_str());
- return 1;
- };
-
- for (int i = 1; i < argc; i++) {
- if (0 == strcmp("-h", argv[i])) { return help(); }
- if (0 == strcmp("--help", argv[i])) { return help(); }
-
- for (auto e : engine_types) {
- size_t len = strlen(e.name);
- if (0 == strncmp(e.name, argv[i], len)) {
- switch (argv[i][len]) {
- case ':': len++;
- case '\0': engine = e.factory(Options{argv[i]+len});
- }
- }
- }
-
- 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(); }
-
- if (!engine) { engine = engine_types.back().factory(Options{}); }
-
- // If we know engine->spawn() will never crash, we can defer logging until we exit.
- if (engine->crashproof()) {
- defer_logging();
- }
-
- 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);
- };
-
- std::list<std::future<Status>> live;
- const auto the_past = std::chrono::steady_clock::now();
-
- auto wait_one = [&] {
- 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::timeout) {
- Status s = it->get();
- live.erase(it);
- return s;
- }
- }
- }
- };
-
- auto spawn = [&](std::function<Status(void)> fn) {
- std::future<Status> status;
- for (;;) {
- status = engine->spawn(fn);
- if (status.valid()) {
- break;
- }
- update_stats(wait_one());
- }
- live.push_back(std::move(status));
- };
-
- 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 = wait_one();
- update_stats(s);
- }
- printf("\n");
- return (failed || crashed) ? 1 : 0;
-}
-
-
-Register::Register(const char* name, const char* help,
- std::unique_ptr<Engine> (*factory)(Options)) {
- engine_types.push_back(EngineType{name, help, factory});
-}
-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/chromium/third_party/skia/tools/ok.h b/chromium/third_party/skia/tools/ok.h
deleted file mode 100644
index 502df23b4aa..00000000000
--- a/chromium/third_party/skia/tools/ok.h
+++ /dev/null
@@ -1,69 +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 <future>
-#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 Engine {
- virtual ~Engine() {}
- virtual bool crashproof() = 0;
- virtual std::future<Status> spawn(std::function<Status(void)>) = 0;
-};
-
-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<Engine> (*factory)(Options));
- 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/chromium/third_party/skia/tools/ok_dsts.cpp b/chromium/third_party/skia/tools/ok_dsts.cpp
deleted file mode 100644
index 1f4fe42a4b6..00000000000
--- a/chromium/third_party/skia/tools/ok_dsts.cpp
+++ /dev/null
@@ -1,70 +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") == "a8") { info = info.makeColorType(kAlpha_8_SkColorType); }
- 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 a8{"a8", "alias for sw:ct=a8", [](Options options) {
- options["ct"] = "a8";
- return SWDst::Create(options);
-}};
-
-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/chromium/third_party/skia/tools/ok_engines.cpp b/chromium/third_party/skia/tools/ok_engines.cpp
deleted file mode 100644
index 3304f3e22ca..00000000000
--- a/chromium/third_party/skia/tools/ok_engines.cpp
+++ /dev/null
@@ -1,100 +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 <stdlib.h>
-
-struct SerialEngine : Engine {
- static std::unique_ptr<Engine> Factory(Options) {
- SerialEngine engine;
- return move_unique(engine);
- }
-
- bool crashproof() override { return false; }
-
- std::future<Status> spawn(std::function<Status(void)> fn) override {
- return std::async(std::launch::deferred, fn);
- }
-};
-static Register serial("serial",
- "Run tasks serially on the main thread of a single process.",
- SerialEngine::Factory);
-
-struct ThreadEngine : Engine {
- static std::unique_ptr<Engine> Factory(Options) {
- ThreadEngine engine;
- return move_unique(engine);
- }
-
- bool crashproof() override { return false; }
-
- std::future<Status> spawn(std::function<Status(void)> fn) override {
- return std::async(std::launch::async, fn);
- }
-};
-static Register thread("thread",
- "Run each task on its own thread of a single process.",
- ThreadEngine::Factory);
-
-#if !defined(_MSC_VER)
- #include <sys/wait.h>
- #include <unistd.h>
-
- struct ForkEngine : Engine {
- int limit; // How many concurrent subprocesses do we allow to run at max?
- int alive = 0; // How many concurrent subprocesses do we have running right now?
-
- static std::unique_ptr<Engine> Factory(Options options) {
- ForkEngine engine;
- engine.limit = atoi(options("limit", "0").c_str());
- if (engine.limit < 1) {
- engine.limit = std::thread::hardware_concurrency();
- }
- return move_unique(engine);
- }
-
- bool crashproof() override { return true; }
-
- std::future<Status> spawn(std::function<Status(void)> fn) override {
- if (alive == limit) {
- // The caller will wait for a child process to finish then try again.
- return std::future<Status>();
- }
-
- switch (fork()) {
- case 0:
- // We are the spawned child process.
- // Run fn() and exit() with its Status as our return code.
- _exit((int)fn());
-
- case -1:
- // The OS won't let us fork() another process right now.
- // We'll need to wait for at least one live task to finish and try again.
- return std::future<Status>();
-
- default:
- // We succesfully spawned a child process!
- // This will wait for any spawned process to finish and return its Status.
- alive++;
- return std::async(std::launch::deferred, [&] {
- do {
- int status;
- if (wait(&status) > 0) {
- alive--;
- return WIFEXITED(status) ? (Status)WEXITSTATUS(status)
- : Status::Crashed;
- }
- } while (errno == EINTR);
- return Status::None;
- });
- }
- }
- };
- static Register _fork("fork",
- "Run each task in an independent process with fork(), limit=ncpus.",
- ForkEngine::Factory);
-#endif
diff --git a/chromium/third_party/skia/tools/ok_srcs.cpp b/chromium/third_party/skia/tools/ok_srcs.cpp
deleted file mode 100644
index b909be8a293..00000000000
--- a/chromium/third_party/skia/tools/ok_srcs.cpp
+++ /dev/null
@@ -1,214 +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 "Benchmark.h"
-#include "SkData.h"
-#include "SkOSFile.h"
-#include "SkPicture.h"
-#include "Timer.h"
-#include "gm.h"
-#include "ok.h"
-#include <algorithm>
-#include <chrono>
-#include <limits>
-#include <stdlib.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);
- 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};
-
-struct BenchStream : Stream {
- const BenchRegistry* registry = BenchRegistry::Head();
- int samples;
-
- static std::unique_ptr<Stream> Create(Options options) {
- BenchStream stream;
- stream.samples = std::max(1, atoi(options("samples", "20").c_str()));
- return move_unique(stream);
- }
-
- struct BenchSrc : Src {
- Benchmark* (*factory)(void*);
- std::unique_ptr<Benchmark> bench;
- int samples;
-
- void init() {
- if (bench) { return; }
- bench.reset(factory(nullptr));
- }
-
- std::string name() override {
- this->init();
- return bench->getName();
- }
-
- SkISize size() override {
- this->init();
- return { bench->getSize().x(), bench->getSize().y() };
- }
-
- Status draw(SkCanvas* canvas) override {
- this->init();
-
- using ms = std::chrono::duration<double, std::milli>;
- std::vector<ms> sample(samples);
-
- bench->delayedSetup();
- if (canvas) {
- bench->perCanvasPreDraw(canvas);
- }
- for (int i = 0; i < samples; i++) {
- using clock = std::chrono::high_resolution_clock;
- for (int loops = 1; loops < 1000000000; loops *= 2) {
- bench->preDraw(canvas);
- auto start = clock::now();
- bench->draw(loops, canvas);
- ms elapsed = clock::now() - start;
- bench->postDraw(canvas);
-
- if (elapsed.count() < 10) {
- continue;
- }
-
- sample[i] = elapsed / loops;
- break;
- }
- }
- if (canvas) {
- bench->perCanvasPostDraw(canvas);
- }
-
- std::sort(sample.begin(), sample.end());
-
- SkString msg = SkStringPrintf("%s\t@0", HumanizeMs(sample[0].count()).c_str());
- if (samples > 2) {
- msg.appendf("\t%s\t@%g", HumanizeMs(sample[samples-2].count()).c_str()
- , 100.0*(samples-1) / samples);
- }
- if (samples > 1) {
- msg.appendf("\t%s\t@100", HumanizeMs(sample[samples-1].count()).c_str());
- }
- ok_log(msg.c_str());
-
- return Status::OK;
- }
- };
-
- std::unique_ptr<Src> next() override {
- if (!registry) {
- return nullptr;
- }
- BenchSrc src;
- src.factory = registry->factory();
- src.samples = samples;
- registry = registry->next();
- return move_unique(src);
- }
-};
-static Register bench{
- "bench",
- "time benchmarks linked into this binary samples=20 times each",
- BenchStream::Create,
-};
diff --git a/chromium/third_party/skia/tools/ok_test.cpp b/chromium/third_party/skia/tools/ok_test.cpp
deleted file mode 100644
index 232904209d4..00000000000
--- a/chromium/third_party/skia/tools/ok_test.cpp
+++ /dev/null
@@ -1,97 +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"
-#else
-struct GrContextOptions {};
-#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;
-
- GrContextOptions options;
- test.run(&reporter, options);
- 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, const GrContextOptions& options) {
- // TODO(bsalomon)
- }
-}
diff --git a/chromium/third_party/skia/tools/ok_vias.cpp b/chromium/third_party/skia/tools/ok_vias.cpp
deleted file mode 100644
index c1f8d9365e7..00000000000
--- a/chromium/third_party/skia/tools/ok_vias.cpp
+++ /dev/null
@@ -1,317 +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 "../dm/DMFontMgr.h"
-#include "../src/core/SkFontMgrPriv.h"
-#include "ProcStats.h"
-#include "SkColorFilter.h"
-#include "SkEventTracingPriv.h"
-#include "SkImage.h"
-#include "SkOSFile.h"
-#include "SkPictureRecorder.h"
-#include "SkPngEncoder.h"
-#include "SkTraceEvent.h"
-#include "SkTypeface.h"
-#include "Timer.h"
-#include "ok.h"
-#include "sk_tool_utils.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 {
- TRACE_EVENT0("ok", TRACE_FUNC);
- SkRTreeFactory factory;
- SkPictureRecorder rec;
- rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
- rtree ? &factory : nullptr);
-
- for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
- return status;
- }
- sk_sp<SkPicture> 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};
-
-// When deserializing, we need to hook this to intercept "Toy Liberation ..."
-// typefaces and return our portable test typeface.
-extern sk_sp<SkTypeface> (*gCreateTypefaceDelegate)(const char[], SkFontStyle);
-
-struct ViaSkp : Dst {
- std::unique_ptr<Dst> target;
- bool rtree = false;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- gCreateTypefaceDelegate = [](const char name[], SkFontStyle style) -> sk_sp<SkTypeface> {
- if (name == strstr(name, "Toy Liberation")) {
- return sk_tool_utils::create_portable_typeface(name, style);
- }
- return nullptr;
- };
-
- ViaSkp via;
- via.target = std::move(dst);
- if (options("bbh") == "rtree") { via.rtree = true; }
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- TRACE_EVENT0("ok", TRACE_FUNC);
- SkRTreeFactory factory;
- SkPictureRecorder rec;
- rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
- rtree ? &factory : nullptr);
-
- for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
- return status;
- }
- sk_sp<SkPicture> pic = rec.finishRecordingAsPicture();
-
- // Serialize and deserialize.
- pic = SkPicture::MakeFromData(pic->serialize().get());
-
- 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_skp{"via_skp", "serialize and deserialize an .skp", ViaSkp::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 {
- TRACE_EVENT0("ok", TRACE_FUNC);
- for (auto status = target->draw(src); status != Status::OK; ) {
- return status;
- }
-
- SkBitmap bm;
- if (!target->image()->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode)) {
- return Status::Failed;
- }
-
- // SkPngEncoder can't encode A8 .pngs, and even if it could, they'd be a pain to look at.
- if (bm.colorType() == kAlpha_8_SkColorType) {
- SkPaint paint;
- SkScalar alpha_to_opaque_gray[20] = {
- 0,0,0,1, 0, // red = alpha
- 0,0,0,1, 0, // green = alpha
- 0,0,0,1, 0, // blue = alpha
- 0,0,0,0,255, // alpha = 255
- };
- paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(alpha_to_opaque_gray));
- paint.setBlendMode(SkBlendMode::kSrc);
-
- SkBitmap dst;
- dst.allocN32Pixels(bm.width(), bm.height(), /*isOpaque=*/true);
- SkCanvas canvas(dst);
- canvas.drawBitmap(bm, 0,0, &paint);
-
- bm = dst;
- }
-
- SkPixmap pm;
- if (!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;
-
- if (status != Status::Skipped) {
- 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);
-
- if (status != Status::Skipped) {
- 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};
-
-struct Trace : Dst {
- std::unique_ptr<Dst> target;
- std::string trace_mode;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- Trace via;
- via.target = std::move(dst);
- via.trace_mode = options("mode", "trace.json");
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- static SkOnce once;
- once([&] { initializeEventTracingForTools(trace_mode.c_str()); });
- return target->draw(src);
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register trace{"trace",
- "enable tracing in mode=atrace, mode=debugf, or mode=trace.json",
- Trace::Create};
-
-struct PortableFonts : Dst {
- std::unique_ptr<Dst> target;
-
- static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
- PortableFonts via;
- via.target = std::move(dst);
- return move_unique(via);
- }
-
- Status draw(Src* src) override {
- static SkOnce once;
- once([]{ gSkFontMgr_DefaultFactory = &DM::MakeFontMgr; });
- return target->draw(src);
- }
-
- sk_sp<SkImage> image() override {
- return target->image();
- }
-};
-static Register portable_fonts{"portable_fonts",
- "use DM::FontMgr to make fonts more portable",
- PortableFonts::Create};
diff --git a/chromium/third_party/skia/tools/pathops_sorter.htm b/chromium/third_party/skia/tools/pathops_sorter.htm
index 42708c428c3..22054955125 100644
--- a/chromium/third_party/skia/tools/pathops_sorter.htm
+++ b/chromium/third_party/skia/tools/pathops_sorter.htm
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
@@ -6,16 +6,10 @@
<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">
+ {{{0.00000000000000000, 0.00000000000000000 }, {0.00022939755581319332, 0.00022927834652364254 },{0.00022930106206331402, 0.00022929999977350235 }, {0.00022930069826543331, 0.00022913678549230099}}},
+ {{{0.00022930069826543331, 0.00022930069826543331 }, {0.00011465034913271666, 0.00011465034913271666 },{0.00011465061106719077, 0.00011460937093943357 }, {0.00014331332931760699, 0.00014325146912597120}}},
+ </div>
</div>
diff --git a/chromium/third_party/skia/tools/remote_demo.cpp b/chromium/third_party/skia/tools/remote_demo.cpp
new file mode 100644
index 00000000000..53aa6917eb0
--- /dev/null
+++ b/chromium/third_party/skia/tools/remote_demo.cpp
@@ -0,0 +1,396 @@
+/*
+ * 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 "SkCanvas.h"
+#include "SkPathEffect.h"
+#include "SkMaskFilter.h"
+#include "SkData.h"
+#include "SkDescriptor.h"
+#include "SkGraphics.h"
+#include "SkSemaphore.h"
+#include "SkPictureRecorder.h"
+#include "SkSerialProcs.h"
+#include "SkSurface.h"
+#include "SkTypeface.h"
+#include "SkWriteBuffer.h"
+
+#include <chrono>
+#include <ctype.h>
+#include <err.h>
+#include <memory>
+#include <stdio.h>
+#include <thread>
+#include <iostream>
+#include <unordered_map>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "SkTypeface_remote.h"
+#include "SkRemoteGlyphCache.h"
+#include "SkMakeUnique.h"
+
+static const size_t kPageSize = 4096;
+
+static bool gUseGpu = true;
+static bool gPurgeFontCaches = true;
+static bool gUseProcess = true;
+
+enum class OpCode : int32_t {
+ kFontMetrics = 0,
+ kGlyphMetrics = 1,
+ kGlyphImage = 2,
+ kGlyphPath = 3,
+ kGlyphMetricsAndImage = 4,
+};
+
+class Op {
+public:
+ Op(OpCode opCode, SkFontID typefaceId, const SkScalerContextRec& rec)
+ : opCode{opCode}
+ , typefaceId{typefaceId}
+ , descriptor{rec} { }
+ const OpCode opCode;
+ const SkFontID typefaceId;
+ const SkScalerContextRecDescriptor descriptor;
+ union {
+ // op 0
+ SkPaint::FontMetrics fontMetrics;
+ // op 1 and 2
+ SkGlyph glyph;
+ // op 3
+ struct {
+ SkGlyphID glyphId;
+ size_t pathSize;
+ };
+ };
+};
+
+class RemoteScalerContextFIFO : public SkRemoteScalerContext {
+public:
+ explicit RemoteScalerContextFIFO(int readFd, int writeFd)
+ : fReadFd{readFd}
+ , fWriteFd{writeFd} { }
+ void generateFontMetrics(const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec,
+ SkPaint::FontMetrics* metrics) override {
+ Op* op = this->createOp(OpCode::kFontMetrics, tf, rec);
+ write(fWriteFd, fBuffer, sizeof(*op));
+ read(fReadFd, fBuffer, sizeof(fBuffer));
+ memcpy(metrics, &op->fontMetrics, sizeof(op->fontMetrics));
+ op->~Op();
+ }
+
+ void generateMetrics(const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec,
+ SkGlyph* glyph) override {
+ Op* op = this->createOp(OpCode::kGlyphMetrics, tf, rec);
+ memcpy(&op->glyph, glyph, sizeof(*glyph));
+ write(fWriteFd, fBuffer, sizeof(*op));
+ read(fReadFd, fBuffer, sizeof(fBuffer));
+ memcpy(glyph, &op->glyph, sizeof(op->glyph));
+ op->~Op();
+ }
+
+ void generateImage(const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec,
+ const SkGlyph& glyph) override {
+ SK_ABORT("generateImage should not be called.");
+ Op* op = this->createOp(OpCode::kGlyphImage, tf, rec);
+ memcpy(&op->glyph, &glyph, sizeof(glyph));
+ write(fWriteFd, fBuffer, sizeof(*op));
+ read(fReadFd, fBuffer, sizeof(fBuffer));
+ memcpy(glyph.fImage, fBuffer + sizeof(Op), glyph.rowBytes() * glyph.fHeight);
+ op->~Op();
+ }
+
+ void generateMetricsAndImage(const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec,
+ SkArenaAlloc* alloc,
+ SkGlyph* glyph) override {
+ Op* op = this->createOp(OpCode::kGlyphMetricsAndImage, tf, rec);
+ memcpy(&op->glyph, glyph, sizeof(op->glyph));
+ write(fWriteFd, fBuffer, sizeof(*op));
+ read(fReadFd, fBuffer, sizeof(fBuffer));
+ memcpy(glyph, &op->glyph, sizeof(*glyph));
+ glyph->allocImage(alloc);
+ memcpy(glyph->fImage, fBuffer + sizeof(Op), glyph->rowBytes() * glyph->fHeight);
+ op->~Op();
+ }
+
+ void generatePath(const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec,
+ SkGlyphID glyph, SkPath* path) override {
+ Op* op = this->createOp(OpCode::kGlyphPath, tf, rec);
+ op->glyphId = glyph;
+ write(fWriteFd, fBuffer, sizeof(*op));
+ read(fReadFd, fBuffer, sizeof(fBuffer));
+ path->readFromMemory(fBuffer + sizeof(Op), op->pathSize);
+ op->~Op();
+ }
+
+private:
+ Op* createOp(OpCode opCode, const SkTypefaceProxy& tf,
+ const SkScalerContextRec& rec) {
+ Op* op = new (fBuffer) Op(opCode, tf.fontID(), rec);
+
+ return op;
+ }
+
+ const int fReadFd,
+ fWriteFd;
+ uint8_t fBuffer[1024 * kPageSize];
+};
+
+static void final_draw(std::string outFilename,
+ SkDeserialProcs* procs,
+ uint8_t* picData,
+ size_t picSize) {
+
+ auto pic = SkPicture::MakeFromData(picData, picSize, 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, picSize, procs);
+
+
+ std::chrono::duration<double> total_seconds{0.0};
+ for (int i = 0; i < 20; i++) {
+ if (gPurgeFontCaches) {
+ SkGraphics::PurgeFontCache();
+ }
+ auto start = std::chrono::high_resolution_clock::now();
+ c->drawPicture(picUnderTest);
+ auto end = std::chrono::high_resolution_clock::now();
+ std::chrono::duration<double> elapsed_seconds = end-start;
+ total_seconds += elapsed_seconds;
+
+ }
+
+ std::cout << "useProcess: " << gUseProcess
+ << " useGPU: " << gUseGpu
+ << " purgeCache: " << gPurgeFontCaches << std::endl;
+ std::cerr << "elapsed time: " << total_seconds.count() << "s\n";
+
+ 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) {
+
+ size_t picSize = 0;
+ ssize_t r = read(readFd, &picSize, sizeof(picSize));
+ if (r > 0) {
+
+ static constexpr size_t kBufferSize = 10 * 1024 * kPageSize;
+ std::unique_ptr<uint8_t[]> picBuffer{new uint8_t[kBufferSize]};
+
+ size_t readSoFar = 0;
+ while (readSoFar < picSize) {
+ ssize_t readSize;
+ if ((readSize = read(readFd, &picBuffer[readSoFar], kBufferSize - readSoFar)) <= 0) {
+ if (readSize == 0) return;
+ err(1, "gpu pic read error %d", errno);
+ }
+ readSoFar += readSize;
+ }
+
+ SkRemoteGlyphCacheGPU rc{
+ skstd::make_unique<RemoteScalerContextFIFO>(readFd, writeFd)
+ };
+
+ SkDeserialProcs procs;
+ rc.prepareDeserializeProcs(&procs);
+
+ final_draw("test.png", &procs, picBuffer.get(), picSize);
+
+ }
+
+ close(writeFd);
+ close(readFd);
+}
+
+static int renderer(
+ const std::string& skpName, int readFd, int writeFd)
+{
+ std::string prefix{"skps/"};
+ std::string fileName{prefix + skpName + ".skp"};
+
+ auto skp = SkData::MakeFromFileName(fileName.c_str());
+ std::cout << "skp stream is " << skp->size() << " bytes long " << std::endl;
+
+ SkRemoteGlyphCacheRenderer rc;
+ SkSerialProcs procs;
+ sk_sp<SkData> stream;
+ if (gUseGpu) {
+ auto pic = SkPicture::MakeFromData(skp.get());
+ rc.prepareSerializeProcs(&procs);
+ stream = pic->serialize(&procs);
+ } else {
+ stream = skp;
+ }
+
+ std::cout << "stream is " << stream->size() << " bytes long" << std::endl;
+
+ size_t picSize = stream->size();
+ uint8_t* picBuffer = (uint8_t*) stream->data();
+
+ if (!gUseGpu) {
+ final_draw("test-direct.png", nullptr, picBuffer, picSize);
+ close(writeFd);
+ close(readFd);
+ return 0;
+ }
+
+ write(writeFd, &picSize, sizeof(picSize));
+
+ size_t writeSoFar = 0;
+ while (writeSoFar < picSize) {
+ ssize_t writeSize = write(writeFd, &picBuffer[writeSoFar], picSize - writeSoFar);
+ if (writeSize <= 0) {
+ if (writeSize == 0) {
+ std::cout << "Exit" << std::endl;
+ return 1;
+ }
+ perror("Can't write picture from render to GPU ");
+ return 1;
+ }
+ writeSoFar += writeSize;
+ }
+ std::cout << "Waiting for scaler context ops." << std::endl;
+
+ static constexpr size_t kBufferSize = 1024 * kPageSize;
+ std::unique_ptr<uint8_t[]> glyphBuffer{new uint8_t[kBufferSize]};
+
+ Op* op = (Op*)glyphBuffer.get();
+ while (true) {
+ ssize_t size = read(readFd, glyphBuffer.get(), sizeof(*op));
+ if (size <= 0) { std::cout << "Exit op loop" << std::endl; break;}
+ size_t writeSize = sizeof(*op);
+
+ auto sc = rc.generateScalerContext(op->descriptor, op->typefaceId);
+ switch (op->opCode) {
+ case OpCode::kFontMetrics : {
+ sc->getFontMetrics(&op->fontMetrics);
+ break;
+ }
+ case OpCode::kGlyphMetrics : {
+ sc->getMetrics(&op->glyph);
+ break;
+ }
+ case OpCode::kGlyphImage : {
+ // TODO: check for buffer overflow.
+ op->glyph.fImage = &glyphBuffer[sizeof(Op)];
+ sc->getImage(op->glyph);
+ writeSize += op->glyph.rowBytes() * op->glyph.fHeight;
+ break;
+ }
+ case OpCode::kGlyphPath : {
+ // TODO: check for buffer overflow.
+ SkPath path;
+ sc->getPath(op->glyphId, &path);
+ op->pathSize = path.writeToMemory(&glyphBuffer[sizeof(Op)]);
+ writeSize += op->pathSize;
+ break;
+ }
+ case OpCode::kGlyphMetricsAndImage : {
+ // TODO: check for buffer overflow.
+ sc->getMetrics(&op->glyph);
+ if (op->glyph.fWidth <= 0 || op->glyph.fWidth >= kMaxGlyphWidth) {
+ op->glyph.fImage = nullptr;
+ break;
+ }
+ op->glyph.fImage = &glyphBuffer[sizeof(Op)];
+ sc->getImage(op->glyph);
+ writeSize += op->glyph.rowBytes() * op->glyph.fHeight;
+ break;
+ }
+ default:
+ SK_ABORT("Bad op");
+ }
+
+ write(writeFd, glyphBuffer.get(), writeSize);
+ }
+
+ close(readFd);
+ close(writeFd);
+
+ std::cout << "Returning from render" << std::endl;
+
+ return 0;
+}
+
+enum direction : int {kRead = 0, kWrite = 1};
+
+static void start_gpu(int render_to_gpu[2], int gpu_to_render[2]) {
+ std::cout << "gpu - Starting GPU" << std::endl;
+ close(gpu_to_render[kRead]);
+ close(render_to_gpu[kWrite]);
+ gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
+}
+
+static void start_render(std::string& skpName, int render_to_gpu[2], int gpu_to_render[2]) {
+ std::cout << "renderer - Starting Renderer" << std::endl;
+ close(render_to_gpu[kRead]);
+ close(gpu_to_render[kWrite]);
+ renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
+}
+
+int main(int argc, char** argv) {
+ std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"desk_nytimes"};
+ int mode = argc > 2 ? atoi(argv[2]) : -1;
+ printf("skp: %s\n", skpName.c_str());
+
+ 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) {
+ start_gpu(render_to_gpu, gpu_to_render);
+ } else {
+ start_render(skpName, render_to_gpu, gpu_to_render);
+ 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/chromium/third_party/skia/tools/shape/SkShaper.h b/chromium/third_party/skia/tools/shape/SkShaper.h
index a2a301e792e..190a4d834e1 100644
--- a/chromium/third_party/skia/tools/shape/SkShaper.h
+++ b/chromium/third_party/skia/tools/shape/SkShaper.h
@@ -28,12 +28,13 @@ public:
~SkShaper();
bool good() const;
- SkScalar shape(SkTextBlobBuilder* dest,
+ SkPoint shape(SkTextBlobBuilder* dest,
const SkPaint& srcPaint,
const char* utf8text,
size_t textBytes,
bool leftToRight,
- SkPoint point) const;
+ SkPoint point,
+ SkScalar width) const;
private:
SkShaper(const SkShaper&) = delete;
diff --git a/chromium/third_party/skia/tools/shape/SkShaper_harfbuzz.cpp b/chromium/third_party/skia/tools/shape/SkShaper_harfbuzz.cpp
index 36fe0a247c9..40414d9a79d 100644
--- a/chromium/third_party/skia/tools/shape/SkShaper_harfbuzz.cpp
+++ b/chromium/third_party/skia/tools/shape/SkShaper_harfbuzz.cpp
@@ -6,20 +6,26 @@
*/
#include <hb-ot.h>
+#include <unicode/brkiter.h>
+#include <unicode/locid.h>
#include <unicode/stringpiece.h>
#include <unicode/ubidi.h>
+#include <unicode/uchriter.h>
#include <unicode/unistr.h>
+#include <unicode/uscript.h>
#include "SkFontMgr.h"
+#include "SkLoadICU.h"
+#include "SkOnce.h"
#include "SkShaper.h"
#include "SkStream.h"
+#include "SkTDPQueue.h"
+#include "SkTLazy.h"
#include "SkTemplates.h"
#include "SkTextBlob.h"
#include "SkTypeface.h"
#include "SkUtils.h"
-static const int FONT_SIZE_SCALE = 512;
-
namespace {
template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
@@ -46,15 +52,8 @@ HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
hb_blob_make_immutable(blob.get());
return blob;
}
-} // namespace
-struct SkShaper::Impl {
- HBFont fHarfBuzzFont;
- HBBuffer fBuffer;
- sk_sp<SkTypeface> fTypeface;
-};
-
-static HBFont create_hb_font(SkTypeface* tf) {
+HBFont create_hb_font(SkTypeface* tf) {
int index;
HBBlob blob(stream_to_blob(std::unique_ptr<SkStreamAsset>(tf->openStream(&index))));
HBFace face(hb_face_create(blob.get(), (unsigned)index));
@@ -70,7 +69,6 @@ static HBFont create_hb_font(SkTypeface* tf) {
if (!font) {
return nullptr;
}
- hb_font_set_scale(font.get(), FONT_SIZE_SCALE, FONT_SIZE_SCALE);
hb_ot_font_set_funcs(font.get());
int axis_count = tf->getVariationDesignPosition(nullptr, 0);
if (axis_count > 0) {
@@ -84,181 +82,647 @@ static HBFont create_hb_font(SkTypeface* tf) {
return font;
}
+class RunIterator {
+public:
+ virtual ~RunIterator() {}
+ virtual void consume() = 0;
+ // Pointer one past the last (utf8) element in the current run.
+ virtual const char* endOfCurrentRun() const = 0;
+ virtual bool atEnd() const = 0;
+ bool operator<(const RunIterator& that) const {
+ return this->endOfCurrentRun() < that.endOfCurrentRun();
+ }
+};
+
+class BiDiRunIterator : public RunIterator {
+public:
+ static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
+ SkTLazy<BiDiRunIterator> ret;
+
+ // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
+ // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
+ if (!SkTFitsIn<int32_t>(utf8Bytes)) {
+ SkDebugf("Bidi error: text too long");
+ return ret;
+ }
+ icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, utf8Bytes));
+
+ UErrorCode status = U_ZERO_ERROR;
+ ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
+ if (U_FAILURE(status)) {
+ SkDebugf("Bidi error: %s", u_errorName(status));
+ return ret;
+ }
+ SkASSERT(bidi);
+
+ // The required lifetime of utf16 isn't well documented.
+ // It appears it isn't used after ubidi_setPara except through ubidi_getText.
+ ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), level, nullptr, &status);
+ if (U_FAILURE(status)) {
+ SkDebugf("Bidi error: %s", u_errorName(status));
+ return ret;
+ }
+
+ ret.init(utf8, std::move(bidi));
+ return ret;
+ }
+ BiDiRunIterator(const char* utf8, ICUBiDi bidi)
+ : fBidi(std::move(bidi))
+ , fEndOfCurrentRun(utf8)
+ , fUTF16LogicalPosition(0)
+ , fLevel(UBIDI_DEFAULT_LTR)
+ {}
+ void consume() override {
+ SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
+ int32_t endPosition = ubidi_getLength(fBidi.get());
+ fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
+ SkUnichar u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
+ fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
+ UBiDiLevel level;
+ while (fUTF16LogicalPosition < endPosition) {
+ level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
+ if (level != fLevel) {
+ break;
+ }
+ u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
+ fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
+ }
+ }
+ const char* endOfCurrentRun() const override {
+ return fEndOfCurrentRun;
+ }
+ bool atEnd() const override {
+ return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
+ }
+
+ UBiDiLevel currentLevel() const {
+ return fLevel;
+ }
+private:
+ ICUBiDi fBidi;
+ const char* fEndOfCurrentRun;
+ int32_t fUTF16LogicalPosition;
+ UBiDiLevel fLevel;
+};
+
+class ScriptRunIterator : public RunIterator {
+public:
+ static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
+ hb_unicode_funcs_t* hbUnicode)
+ {
+ SkTLazy<ScriptRunIterator> ret;
+ ret.init(utf8, utf8Bytes, hbUnicode);
+ return ret;
+ }
+ ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
+ : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
+ , fHBUnicode(hbUnicode)
+ , fCurrentScript(HB_SCRIPT_UNKNOWN)
+ {}
+ void consume() override {
+ SkASSERT(fCurrent < fEnd);
+ SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
+ fCurrentScript = hb_unicode_script(fHBUnicode, u);
+ while (fCurrent < fEnd) {
+ const char* prev = fCurrent;
+ u = SkUTF8_NextUnichar(&fCurrent);
+ const hb_script_t script = hb_unicode_script(fHBUnicode, u);
+ if (script != fCurrentScript) {
+ if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
+ fCurrentScript = script;
+ } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
+ continue;
+ } else {
+ fCurrent = prev;
+ break;
+ }
+ }
+ }
+ if (fCurrentScript == HB_SCRIPT_INHERITED) {
+ fCurrentScript = HB_SCRIPT_COMMON;
+ }
+ }
+ const char* endOfCurrentRun() const override {
+ return fCurrent;
+ }
+ bool atEnd() const override {
+ return fCurrent == fEnd;
+ }
+
+ hb_script_t currentScript() const {
+ return fCurrentScript;
+ }
+private:
+ const char* fCurrent;
+ const char* fEnd;
+ hb_unicode_funcs_t* fHBUnicode;
+ hb_script_t fCurrentScript;
+};
+
+class FontRunIterator : public RunIterator {
+public:
+ static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
+ sk_sp<SkTypeface> typeface,
+ hb_font_t* hbFace,
+ sk_sp<SkFontMgr> fallbackMgr)
+ {
+ SkTLazy<FontRunIterator> ret;
+ ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
+ return ret;
+ }
+ FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
+ hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
+ : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
+ , fFallbackMgr(std::move(fallbackMgr))
+ , fHBFont(hbFace), fTypeface(std::move(typeface))
+ , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
+ , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
+ {}
+ void consume() override {
+ SkASSERT(fCurrent < fEnd);
+ SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
+ // If the starting typeface can handle this character, use it.
+ if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
+ fFallbackTypeface.reset();
+ // If not, try to find a fallback typeface
+ } else {
+ fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
+ nullptr, fTypeface->fontStyle(), nullptr, 0, u));
+ }
+
+ if (fFallbackTypeface) {
+ fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
+ fCurrentTypeface = fFallbackTypeface.get();
+ fCurrentHBFont = fFallbackHBFont.get();
+ } else {
+ fFallbackHBFont.reset();
+ fCurrentTypeface = fTypeface.get();
+ fCurrentHBFont = fHBFont;
+ }
+
+ while (fCurrent < fEnd) {
+ const char* prev = fCurrent;
+ u = SkUTF8_NextUnichar(&fCurrent);
+
+ // If using a fallback and the initial typeface has this character, stop fallback.
+ if (fFallbackTypeface &&
+ fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
+ {
+ fCurrent = prev;
+ return;
+ }
+ // If the current typeface cannot handle this character, stop using it.
+ if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
+ fCurrent = prev;
+ return;
+ }
+ }
+ }
+ const char* endOfCurrentRun() const override {
+ return fCurrent;
+ }
+ bool atEnd() const override {
+ return fCurrent == fEnd;
+ }
+
+ SkTypeface* currentTypeface() const {
+ return fCurrentTypeface;
+ }
+ hb_font_t* currentHBFont() const {
+ return fCurrentHBFont;
+ }
+private:
+ const char* fCurrent;
+ const char* fEnd;
+ sk_sp<SkFontMgr> fFallbackMgr;
+ hb_font_t* fHBFont;
+ sk_sp<SkTypeface> fTypeface;
+ HBFont fFallbackHBFont;
+ sk_sp<SkTypeface> fFallbackTypeface;
+ hb_font_t* fCurrentHBFont;
+ SkTypeface* fCurrentTypeface;
+};
+
+class RunIteratorQueue {
+public:
+ void insert(RunIterator* runIterator) {
+ fRunIterators.insert(runIterator);
+ }
+
+ bool advanceRuns() {
+ const RunIterator* leastRun = fRunIterators.peek();
+ if (leastRun->atEnd()) {
+ SkASSERT(this->allRunsAreAtEnd());
+ return false;
+ }
+ const char* leastEnd = leastRun->endOfCurrentRun();
+ RunIterator* currentRun = nullptr;
+ SkDEBUGCODE(const char* previousEndOfCurrentRun);
+ while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
+ fRunIterators.pop();
+ SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
+ currentRun->consume();
+ SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
+ fRunIterators.insert(currentRun);
+ }
+ return true;
+ }
+
+ const char* endOfCurrentRun() const {
+ return fRunIterators.peek()->endOfCurrentRun();
+ }
+
+private:
+ bool allRunsAreAtEnd() const {
+ for (int i = 0; i < fRunIterators.count(); ++i) {
+ if (!fRunIterators.at(i)->atEnd()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
+ return *a < *b;
+ }
+ SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
+};
+
+struct ShapedGlyph {
+ SkGlyphID fID;
+ uint32_t fCluster;
+ SkPoint fOffset;
+ SkVector fAdvance;
+ bool fMayLineBreakBefore;
+ bool fMustLineBreakBefore;
+ bool fHasVisual;
+};
+struct ShapedRun {
+ ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkPaint& paint,
+ UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
+ : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fPaint(paint)
+ , fLevel(level), fGlyphs(std::move(glyphs))
+ {}
+
+ const char* fUtf8Start;
+ const char* fUtf8End;
+ int fNumGlyphs;
+ SkPaint fPaint;
+ UBiDiLevel fLevel;
+ std::unique_ptr<ShapedGlyph[]> fGlyphs;
+};
+
+static constexpr bool is_LTR(UBiDiLevel level) {
+ return (level & 1) == 0;
+}
+
+static void append(SkTextBlobBuilder* b, const ShapedRun& run, int start, int end, SkPoint* p) {
+ unsigned len = end - start;
+ auto runBuffer = b->allocRunTextPos(run.fPaint, len, run.fUtf8End - run.fUtf8Start, SkString());
+ memcpy(runBuffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
+
+ for (unsigned i = 0; i < len; i++) {
+ // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
+ const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
+ runBuffer.glyphs[i] = glyph.fID;
+ runBuffer.clusters[i] = glyph.fCluster;
+ reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
+ SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
+ p->fX += glyph.fAdvance.fX;
+ p->fY += glyph.fAdvance.fY;
+ }
+}
+
+struct ShapedRunGlyphIterator {
+ ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
+ : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
+ { }
+
+ ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
+ ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
+ bool operator==(const ShapedRunGlyphIterator& that) const {
+ return fRuns == that.fRuns &&
+ fRunIndex == that.fRunIndex &&
+ fGlyphIndex == that.fGlyphIndex;
+ }
+ bool operator!=(const ShapedRunGlyphIterator& that) const {
+ return fRuns != that.fRuns ||
+ fRunIndex != that.fRunIndex ||
+ fGlyphIndex != that.fGlyphIndex;
+ }
+
+ ShapedGlyph* next() {
+ const SkTArray<ShapedRun>& runs = *fRuns;
+ SkASSERT(fRunIndex < runs.count());
+ SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
+
+ ++fGlyphIndex;
+ if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
+ fGlyphIndex = 0;
+ ++fRunIndex;
+ if (fRunIndex >= runs.count()) {
+ return nullptr;
+ }
+ }
+ return &runs[fRunIndex].fGlyphs[fGlyphIndex];
+ }
+
+ ShapedGlyph* current() {
+ const SkTArray<ShapedRun>& runs = *fRuns;
+ if (fRunIndex >= runs.count()) {
+ return nullptr;
+ }
+ return &runs[fRunIndex].fGlyphs[fGlyphIndex];
+ }
+
+ const SkTArray<ShapedRun>* fRuns;
+ int fRunIndex;
+ int fGlyphIndex;
+};
+
+} // namespace
+
+struct SkShaper::Impl {
+ HBFont fHarfBuzzFont;
+ HBBuffer fBuffer;
+ sk_sp<SkTypeface> fTypeface;
+ std::unique_ptr<icu::BreakIterator> fBreakIterator;
+};
+
SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
+ SkOnce once;
+ once([] { SkLoadICU(); });
+
fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
SkASSERT(fImpl->fHarfBuzzFont);
fImpl->fBuffer.reset(hb_buffer_create());
+ SkASSERT(fImpl->fBuffer);
+
+ icu::Locale thai("th");
+ UErrorCode status = U_ZERO_ERROR;
+ fImpl->fBreakIterator.reset(icu::BreakIterator::createLineInstance(thai, status));
+ if (U_FAILURE(status)) {
+ SkDebugf("Could not create break iterator: %s", u_errorName(status));
+ SK_ABORT("");
+ }
}
SkShaper::~SkShaper() {}
-bool SkShaper::good() const { return fImpl->fHarfBuzzFont != nullptr; }
+bool SkShaper::good() const {
+ return fImpl->fHarfBuzzFont &&
+ fImpl->fBuffer &&
+ fImpl->fTypeface &&
+ fImpl->fBreakIterator;
+}
-SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
- const SkPaint& srcPaint,
- const char* utf8text,
- size_t textBytes,
- bool leftToRight,
- SkPoint point) const {
+SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
+ const SkPaint& srcPaint,
+ const char* utf8,
+ size_t utf8Bytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const {
sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
SkASSERT(builder);
- UBiDiLevel bidiLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
+ UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
//hb_script_t script = ...
- UErrorCode status = U_ZERO_ERROR;
- double x = point.x();
- double y = point.y();
- // This function only accepts utf8.
- // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
- // Internally, harfbuzz is all utf32, but always makes a copy.
+ SkTArray<ShapedRun> runs;
+{
+ RunIteratorQueue runSegmenter;
- if (!SkTFitsIn<int32_t>(textBytes)) {
- SkDebugf("Bidi error: text too long");
- return (SkScalar)x;
+ SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
+ BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
+ if (!bidi) {
+ return point;
}
- icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8text, textBytes));
+ runSegmenter.insert(bidi);
- ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
- if (U_FAILURE(status)) {
- SkDebugf("Bidi error: %s", u_errorName(status));
- return (SkScalar)x;
+ hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
+ SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
+ ScriptRunIterator* script = maybeScript.getMaybeNull();
+ if (!script) {
+ return point;
}
- SkASSERT(bidi);
+ runSegmenter.insert(script);
- ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), bidiLevel, nullptr, &status);
- if (U_FAILURE(status)) {
- SkDebugf("Bidi error: %s", u_errorName(status));
- return (SkScalar)x;
+ SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
+ fImpl->fTypeface,
+ fImpl->fHarfBuzzFont.get(),
+ std::move(fontMgr)));
+ FontRunIterator* font = maybeFont.getMaybeNull();
+ if (!font) {
+ return point;
}
+ runSegmenter.insert(font);
- int32_t runCount = ubidi_countRuns(bidi.get(), &status);
- if (U_FAILURE(status)) {
- SkDebugf("Bidi error: %s", u_errorName(status));
- return (SkScalar)x;
+ icu::BreakIterator& breakIterator = *fImpl->fBreakIterator;
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ UText utf8UText = UTEXT_INITIALIZER;
+ utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
+ std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
+ if (U_FAILURE(status)) {
+ SkDebugf("Could not create utf8UText: %s", u_errorName(status));
+ return point;
+ }
+ breakIterator.setText(&utf8UText, status);
+ //utext_close(&utf8UText);
+ if (U_FAILURE(status)) {
+ SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
+ return point;
+ }
}
- const UChar* utf16End = utf16.getBuffer();
- const char* utf8End = utf8text;
- for (int32_t i = 0; i < runCount; ++i) {
- int32_t start;
- int32_t length;
- UBiDiDirection direction = ubidi_getVisualRun(bidi.get(), i, &start, &length);
+ const char* utf8Start = nullptr;
+ const char* utf8End = utf8;
+ while (runSegmenter.advanceRuns()) {
+ utf8Start = utf8End;
+ utf8End = runSegmenter.endOfCurrentRun();
+
+ hb_buffer_t* buffer = fImpl->fBuffer.get();
+ SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
+ hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
+ hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
+
+ // Populate the hb_buffer directly with utf8 cluster indexes.
+ const char* utf8Current = utf8Start;
+ while (utf8Current < utf8End) {
+ unsigned int cluster = utf8Current - utf8Start;
+ hb_codepoint_t u = SkUTF8_NextUnichar(&utf8Current);
+ hb_buffer_add(buffer, u, cluster);
+ }
+
+ size_t utf8runLength = utf8End - utf8Start;
+ if (!SkTFitsIn<int>(utf8runLength)) {
+ SkDebugf("Shaping error: utf8 too long");
+ return point;
+ }
+ hb_buffer_set_script(buffer, script->currentScript());
+ hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
+ hb_buffer_set_direction(buffer, direction);
+ // TODO: language
+ hb_buffer_guess_segment_properties(buffer);
+ // TODO: features
+ hb_shape(font->currentHBFont(), buffer, nullptr, 0);
+ unsigned len = hb_buffer_get_length(buffer);
+ if (len == 0) {
+ continue;
+ }
+
+ if (direction == HB_DIRECTION_RTL) {
+ // Put the clusters back in logical order.
+ // Note that the advances remain ltr.
+ hb_buffer_reverse(buffer);
+ }
+ hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
+ hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
+
+ if (!SkTFitsIn<int>(len)) {
+ SkDebugf("Shaping error: too many glyphs");
+ return point;
+ }
SkPaint paint(srcPaint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint.setTypeface(fImpl->fTypeface);
- hb_font_t* hbfont = fImpl->fHarfBuzzFont.get();
- HBFont fallbackHBFont;
- sk_sp<SkTypeface> fallback;
- while (utf16End < utf16.getBuffer() + start + length) {
- hb_buffer_t* buffer = fImpl->fBuffer.get();
- SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
-
- // The difficulty here is the cluster mapping.
- // If the hb_buffer is created with utf16, clusters will point to utf16 indexes,
- // but the SkTextBlob can only take utf8 and utf8 cluster indexes.
- // So populate the hb_buffer directly with utf32 and utf8 cluster indexes.
- // Since this steps through the visual runs in order, it is expected that each run will
- // start just after the previous one ended.
- const UChar* utf16Start = utf16.getBuffer() + start;
- const char* utf8Start;
- if (utf16End == utf16Start) {
- utf16Start = utf16End;
- utf8Start = utf8End;
- } else {
- SkDEBUGFAIL("Did not expect to ever get here.");
- utf16Start = utf16.getBuffer();
- utf8Start = utf8text;
- while (utf16Start < utf16.getBuffer() + start) {
- SkUTF16_NextUnichar(&utf16Start);
- SkUTF8_NextUnichar(&utf8Start);
- }
- }
- const char* utf8Current = utf8Start;
- const UChar* utf16Current = utf16Start;
- utf16End = utf16Current + length;
- while (utf16Current < utf16End) {
- const UChar* utf16Prev = utf16Current;
- hb_codepoint_t u = SkUTF16_NextUnichar(&utf16Current);
- bool doPartialRun = false;
-
- // If using a fallback and the initial typeface has this character, stop fallback.
- if (fallbackHBFont &&
- fImpl->fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
- {
- fallback.reset();
- doPartialRun = true;
-
- // If the current typeface does not have this character, try a fallback.
- } else if (!paint.getTypeface()->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding,
- nullptr, 1))
- {
- fallback.reset(fontMgr->matchFamilyStyleCharacter(nullptr,
- fImpl->fTypeface->fontStyle(),
- nullptr, 0,
- u));
- if (fallback) {
- doPartialRun = true;
- }
- }
- if (doPartialRun) {
- utf16End = utf16Prev;
- int32_t oldStart = start;
- start = utf16End - utf16.getBuffer();
- length -= start - oldStart;
- break;
- }
- hb_buffer_add(buffer, u, utf8Current - utf8Start);
- SkUTF8_NextUnichar(&utf8Current);
- }
- hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
- utf8End = utf8Current;
- size_t utf8runLength = utf8End - utf8Start;
- if (!SkTFitsIn<int>(utf8runLength)) {
- SkDebugf("Shaping error: utf8 too long");
- return (SkScalar)x;
- }
- hb_buffer_guess_segment_properties(buffer);
- //hb_buffer_set_script(buffer, script);
- hb_buffer_set_direction(buffer, direction ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
- hb_shape(hbfont, buffer, nullptr, 0);
- unsigned len = hb_buffer_get_length(buffer);
- if (len > 0) {
- hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
- hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
-
- if (!SkTFitsIn<int>(len)) {
- SkDebugf("Shaping error: too many glyphs");
- return (SkScalar)x;
- }
- auto runBuffer = builder->allocRunTextPos(paint, len, utf8runLength, SkString());
- memcpy(runBuffer.utf8text, utf8Start, utf8runLength);
-
- 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;
- }
- }
+ paint.setTypeface(sk_ref_sp(font->currentTypeface()));
+ ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, paint, bidi->currentLevel(),
+ std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
+ int scaleX, scaleY;
+ hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
+ double textSizeY = run.fPaint.getTextSize() / scaleY;
+ double textSizeX = run.fPaint.getTextSize() / scaleX * run.fPaint.getTextScaleX();
+ for (unsigned i = 0; i < len; i++) {
+ ShapedGlyph& glyph = run.fGlyphs[i];
+ glyph.fID = info[i].codepoint;
+ glyph.fCluster = info[i].cluster;
+ glyph.fOffset.fX = pos[i].x_offset * textSizeX;
+ glyph.fOffset.fY = pos[i].y_offset * textSizeY;
+ glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
+ glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
+ glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
+ //info->mask safe_to_break;
+ glyph.fMustLineBreakBefore = false;
+ }
- if (fallback) {
- paint.setTypeface(std::move(fallback));
- fallbackHBFont = create_hb_font(paint.getTypeface());
- hbfont = fallbackHBFont.get();
- } else {
- paint.setTypeface(fImpl->fTypeface);
- fallbackHBFont = nullptr;
- hbfont = fImpl->fHarfBuzzFont.get();
+ int32_t clusterOffset = utf8Start - utf8;
+ uint32_t previousCluster = 0xFFFFFFFF;
+ for (unsigned i = 0; i < len; ++i) {
+ ShapedGlyph& glyph = run.fGlyphs[i];
+ int32_t glyphCluster = glyph.fCluster + clusterOffset;
+ int32_t breakIteratorCurrent = breakIterator.current();
+ while (breakIteratorCurrent != icu::BreakIterator::DONE &&
+ breakIteratorCurrent < glyphCluster)
+ {
+ breakIteratorCurrent = breakIterator.next();
}
+ glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
+ breakIteratorCurrent == glyphCluster;
+ previousCluster = glyph.fCluster;
}
}
- return (SkScalar)x;
+}
+
+// Iterate over the glyphs in logical order to mark line endings.
+{
+ SkScalar widthSoFar = 0;
+ bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
+ bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
+ ShapedRunGlyphIterator previousBreak(runs);
+ ShapedRunGlyphIterator glyphIterator(runs);
+ while (ShapedGlyph* glyph = glyphIterator.current()) {
+ if (canAddBreakNow && glyph->fMayLineBreakBefore) {
+ previousBreakValid = true;
+ previousBreak = glyphIterator;
+ }
+ SkScalar glyphWidth = glyph->fAdvance.fX;
+ if (widthSoFar + glyphWidth < width) {
+ widthSoFar += glyphWidth;
+ glyphIterator.next();
+ canAddBreakNow = true;
+ continue;
+ }
+
+ if (widthSoFar == 0) {
+ // Adding just this glyph is too much, just break with this glyph
+ glyphIterator.next();
+ previousBreak = glyphIterator;
+ } else if (!previousBreakValid) {
+ // No break opprotunity found yet, just break without this glyph
+ previousBreak = glyphIterator;
+ }
+ glyphIterator = previousBreak;
+ glyph = glyphIterator.current();
+ if (glyph) {
+ glyph->fMustLineBreakBefore = true;
+ }
+ widthSoFar = 0;
+ previousBreakValid = false;
+ canAddBreakNow = false;
+ }
+}
+
+// Reorder the runs and glyphs per line and write them out.
+ SkPoint currentPoint = point;
+{
+ ShapedRunGlyphIterator previousBreak(runs);
+ ShapedRunGlyphIterator glyphIterator(runs);
+ SkScalar maxAscent = 0;
+ SkScalar maxDescent = 0;
+ SkScalar maxLeading = 0;
+ int previousRunIndex = -1;
+ while (glyphIterator.current()) {
+ int runIndex = glyphIterator.fRunIndex;
+ int glyphIndex = glyphIterator.fGlyphIndex;
+ ShapedGlyph* nextGlyph = glyphIterator.next();
+
+ if (previousRunIndex != runIndex) {
+ SkPaint::FontMetrics metrics;
+ runs[runIndex].fPaint.getFontMetrics(&metrics);
+ maxAscent = SkTMin(maxAscent, metrics.fAscent);
+ maxDescent = SkTMax(maxDescent, metrics.fDescent);
+ maxLeading = SkTMax(maxLeading, metrics.fLeading);
+ previousRunIndex = runIndex;
+ }
+
+ // Nothing can be written until the baseline is known.
+ if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
+ continue;
+ }
+
+ currentPoint.fY -= maxAscent;
+
+ int numRuns = runIndex - previousBreak.fRunIndex + 1;
+ SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
+ for (int i = 0; i < numRuns; ++i) {
+ runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
+ }
+ SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
+ ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
+
+ for (int i = 0; i < numRuns; ++i) {
+ int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
+
+ int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
+ ? previousBreak.fGlyphIndex
+ : 0;
+ int endGlyphIndex = (logicalIndex == runIndex)
+ ? glyphIndex + 1
+ : runs[logicalIndex].fNumGlyphs;
+ append(builder, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
+ }
+
+ currentPoint.fY += maxDescent + maxLeading;
+ currentPoint.fX = point.fX;
+ maxAscent = 0;
+ maxDescent = 0;
+ maxLeading = 0;
+ previousRunIndex = -1;
+ previousBreak = glyphIterator;
+ }
+}
+
+ return currentPoint;
}
diff --git a/chromium/third_party/skia/tools/shape/SkShaper_primitive.cpp b/chromium/third_party/skia/tools/shape/SkShaper_primitive.cpp
index 750c51621e8..06a8bec41c7 100644
--- a/chromium/third_party/skia/tools/shape/SkShaper_primitive.cpp
+++ b/chromium/third_party/skia/tools/shape/SkShaper_primitive.cpp
@@ -29,12 +29,13 @@ unsigned utf8_lead_byte_to_count(const char* ptr) {
return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
}
-SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
- const SkPaint& srcPaint,
- const char* utf8text,
- size_t textBytes,
- bool leftToRight,
- SkPoint point) const {
+SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
+ const SkPaint& srcPaint,
+ const char* utf8text,
+ size_t textBytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const {
sk_ignore_unused_variable(leftToRight);
SkPaint paint(srcPaint);
@@ -42,9 +43,12 @@ SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
int glyphCount = paint.countText(utf8text, textBytes);
if (glyphCount <= 0) {
- return 0;
+ return point;
}
SkRect bounds;
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ point.fY -= metrics.fAscent;
(void)paint.measureText(utf8text, textBytes, &bounds);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
const SkTextBlobBuilder::RunBuffer& runBuffer =
@@ -66,5 +70,7 @@ SkScalar SkShaper::shape(SkTextBlobBuilder* builder,
runBuffer.pos[i] = x;
x += w;
}
- return (SkScalar)x;
+ point.fY += metrics.fDescent + metrics.fLeading;
+
+ return point;
}
diff --git a/chromium/third_party/skia/tools/shape/using_skia_and_harfbuzz.cpp b/chromium/third_party/skia/tools/shape/using_skia_and_harfbuzz.cpp
index 533fd1e10d0..5a748667949 100644
--- a/chromium/third_party/skia/tools/shape/using_skia_and_harfbuzz.cpp
+++ b/chromium/third_party/skia/tools/shape/using_skia_and_harfbuzz.cpp
@@ -112,7 +112,7 @@ struct Config {
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");
@@ -138,7 +138,16 @@ public:
}
void WriteLine(const SkShaper& shaper, const char *text, size_t textBytes) {
- if (!pageCanvas || current_y > config->page_height.value) {
+ SkTextBlobBuilder textBlobBuilder;
+ SkPoint endPoint = shaper.shape(&textBlobBuilder, glyph_paint, text, textBytes, true,
+ SkPoint{0, 0},
+ config->page_width.value - 2*config->left_margin.value);
+ sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
+ // 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 +158,11 @@ public:
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, true, 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:
@@ -205,6 +211,7 @@ int main(int argc, char **argv) {
SkShaper shaper(typeface);
assert(shaper.good());
//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());
}
diff --git a/chromium/third_party/skia/tools/sk_app/CommandSet.cpp b/chromium/third_party/skia/tools/sk_app/CommandSet.cpp
index d0154d6e617..9684ef26241 100644
--- a/chromium/third_party/skia/tools/sk_app/CommandSet.cpp
+++ b/chromium/third_party/skia/tools/sk_app/CommandSet.cpp
@@ -78,7 +78,7 @@ void CommandSet::addCommand(Window::Key k, const char* keyName, const char* grou
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
diff --git a/chromium/third_party/skia/tools/sk_app/DisplayParams.h b/chromium/third_party/skia/tools/sk_app/DisplayParams.h
index 959735e8ff2..203e8bdeca8 100644
--- a/chromium/third_party/skia/tools/sk_app/DisplayParams.h
+++ b/chromium/third_party/skia/tools/sk_app/DisplayParams.h
@@ -13,10 +13,7 @@
namespace sk_app {
struct DisplayParams {
- DisplayParams()
- : fColorType(kN32_SkColorType)
- , fColorSpace(nullptr)
- , fMSAASampleCount(0) {}
+ DisplayParams() : fColorType(kN32_SkColorType), fColorSpace(nullptr), fMSAASampleCount(1) {}
SkColorType fColorType;
sk_sp<SkColorSpace> fColorSpace;
diff --git a/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp b/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp
index 9ef5141feec..9d042cf19ed 100644
--- a/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp
+++ b/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp
@@ -24,9 +24,7 @@ GLWindowContext::GLWindowContext(const DisplayParams& params)
: WindowContext(params)
, fBackendContext(nullptr)
, fSurface(nullptr) {
- fDisplayParams.fMSAASampleCount = fDisplayParams.fMSAASampleCount ?
- GrNextPow2(fDisplayParams.fMSAASampleCount) :
- 0;
+ fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
}
void GLWindowContext::initializeContext() {
@@ -34,7 +32,7 @@ void GLWindowContext::initializeContext() {
fBackendContext = this->onInitializeContext();
fContext = GrContext::MakeGL(fBackendContext, fDisplayParams.fGrContextOptions);
- if (!fContext && fDisplayParams.fMSAASampleCount) {
+ if (!fContext && fDisplayParams.fMSAASampleCount > 1) {
fDisplayParams.fMSAASampleCount /= 2;
this->initializeContext();
return;
diff --git a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
index 6237ee09aed..d7839bc1894 100644
--- a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
+++ b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
@@ -287,7 +287,7 @@ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType)
GrVkImageInfo info;
info.fImage = fImages[i];
- info.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
+ info.fAlloc = GrVkAlloc();
info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
info.fFormat = format;
diff --git a/chromium/third_party/skia/tools/sk_app/Window.cpp b/chromium/third_party/skia/tools/sk_app/Window.cpp
index 29e4864ba1e..1694beaac84 100644
--- a/chromium/third_party/skia/tools/sk_app/Window.cpp
+++ b/chromium/third_party/skia/tools/sk_app/Window.cpp
@@ -117,7 +117,7 @@ void Window::setRequestedDisplayParams(const DisplayParams& params, bool /* allo
int Window::sampleCount() const {
if (!fWindowContext) {
- return -1;
+ return 0;
}
return fWindowContext->sampleCount();
}
diff --git a/chromium/third_party/skia/tools/sk_app/WindowContext.h b/chromium/third_party/skia/tools/sk_app/WindowContext.h
index 5e7d76d4bad..71c21ac0891 100644
--- a/chromium/third_party/skia/tools/sk_app/WindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/WindowContext.h
@@ -21,11 +21,11 @@ namespace sk_app {
class WindowContext {
public:
WindowContext(const DisplayParams& params)
- : fContext(nullptr)
- , fDisplayParams(params)
- , fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
- , fSampleCount(0)
- , fStencilBits(0) {}
+ : fContext(nullptr)
+ , fDisplayParams(params)
+ , fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
+ , fSampleCount(1)
+ , fStencilBits(0) {}
virtual ~WindowContext() {}
diff --git a/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp b/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
index acdb5872300..51111141158 100644
--- a/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
@@ -70,6 +70,8 @@ sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
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 @@ sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
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
};
@@ -131,6 +133,7 @@ sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
return GrGLMakeNativeInterface();
}
diff --git a/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp
index f4c0d6b3c03..aac7e20fd92 100644
--- a/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp
@@ -27,7 +27,7 @@ public:
void onSwapBuffers() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
- void onDestroyContext() override;
+ void onDestroyContext() override {}
private:
SDL_Window* fWindow;
@@ -39,7 +39,7 @@ private:
GLWindowContext_ios::GLWindowContext_ios(const IOSWindowInfo& info, const DisplayParams& params)
: INHERITED(params)
, fWindow(info.fWindow)
- , fGLContext(nullptr) {
+ , fGLContext(info.fGLContext) {
// any config code here (particularly for msaa)?
@@ -52,12 +52,7 @@ GLWindowContext_ios::~GLWindowContext_ios() {
sk_sp<const GrGLInterface> GLWindowContext_ios::onInitializeContext() {
SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return nullptr;
- }
+ SkASSERT(fGLContext);
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
glClearStencil(0);
@@ -67,6 +62,7 @@ sk_sp<const GrGLInterface> GLWindowContext_ios::onInitializeContext() {
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
SDL_GL_GetDrawableSize(fWindow, &fWidth, &fHeight);
glViewport(0, 0, fWidth, fHeight);
@@ -76,15 +72,6 @@ sk_sp<const GrGLInterface> GLWindowContext_ios::onInitializeContext() {
return GrGLMakeNativeInterface();
}
-void GLWindowContext_ios::onDestroyContext() {
- if (!fWindow || !fGLContext) {
- return;
- }
- SDL_GL_DeleteContext(fGLContext);
- fGLContext = nullptr;
-}
-
-
void GLWindowContext_ios::onSwapBuffers() {
if (fWindow && fGLContext) {
SDL_GL_SwapWindow(fWindow);
diff --git a/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp
index cae5774c28f..18a6c36014e 100644
--- a/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp
@@ -64,12 +64,7 @@ RasterWindowContext_ios::~RasterWindowContext_ios() {
sk_sp<const GrGLInterface> RasterWindowContext_ios::onInitializeContext() {
SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return nullptr;
- }
+ SkASSERT(fGLContext);
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
glClearStencil(0);
@@ -79,6 +74,7 @@ sk_sp<const GrGLInterface> RasterWindowContext_ios::onInitializeContext() {
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
SDL_GL_GetDrawableSize(fWindow, &fWidth, &fHeight);
glViewport(0, 0, fWidth, fHeight);
@@ -94,12 +90,7 @@ sk_sp<const GrGLInterface> RasterWindowContext_ios::onInitializeContext() {
}
void RasterWindowContext_ios::onDestroyContext() {
- if (!fWindow || !fGLContext) {
- return;
- }
fBackbufferSurface.reset(nullptr);
- SDL_GL_DeleteContext(fGLContext);
- fGLContext = nullptr;
}
sk_sp<SkSurface> RasterWindowContext_ios::getBackbufferSurface() { return fBackbufferSurface; }
diff --git a/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h b/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
index 09999c4c83d..93c6fbf4507 100644
--- a/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
+++ b/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
@@ -19,7 +19,8 @@ struct DisplayParams;
namespace window_context_factory {
struct IOSWindowInfo {
- SDL_Window* fWindow;
+ SDL_Window* fWindow;
+ SDL_GLContext fGLContext;
};
inline WindowContext* NewVulkanForIOS(const IOSWindowInfo&, const DisplayParams&) {
diff --git a/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp
index c1bdeae5fc7..9b2339d19e7 100644
--- a/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp
@@ -49,7 +49,7 @@ bool Window_ios::initWindow() {
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
- if (fRequestedDisplayParams.fMSAASampleCount > 0) {
+ if (fRequestedDisplayParams.fMSAASampleCount > 1) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount);
} else {
@@ -71,10 +71,22 @@ bool Window_ios::initWindow() {
fWindowID = SDL_GetWindowID(fWindow);
gWindowMap.add(this);
+ fGLContext = SDL_GL_CreateContext(fWindow);
+ if (!fGLContext) {
+ SkDebugf("%s\n", SDL_GetError());
+ this->closeWindow();
+ return false;
+ }
+
return true;
}
void Window_ios::closeWindow() {
+ if (fGLContext) {
+ SDL_GL_DeleteContext(fGLContext);
+ fGLContext = nullptr;
+ }
+
if (fWindow) {
gWindowMap.remove(fWindowID);
SDL_DestroyWindow(fWindow);
@@ -251,6 +263,7 @@ bool Window_ios::attach(BackendType attachType) {
window_context_factory::IOSWindowInfo info;
info.fWindow = fWindow;
+ info.fGLContext = fGLContext;
switch (attachType) {
case kRaster_BackendType:
fWindowContext = NewRasterForIOS(info, fRequestedDisplayParams);
diff --git a/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h
index 667fa74e825..260b133ff97 100644
--- a/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h
+++ b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h
@@ -19,10 +19,11 @@ namespace sk_app {
class Window_ios : public Window {
public:
Window_ios()
- : INHERITED()
- , fWindow(nullptr)
- , fWindowID(0)
- , fMSAASampleCount(0) {}
+ : INHERITED()
+ , fWindow(nullptr)
+ , fWindowID(0)
+ , fGLContext(nullptr)
+ , fMSAASampleCount(1) {}
~Window_ios() override { this->closeWindow(); }
bool initWindow();
@@ -51,8 +52,9 @@ private:
static SkTDynamicHash<Window_ios, Uint32> gWindowMap;
- SDL_Window* fWindow;
- Uint32 fWindowID;
+ SDL_Window* fWindow;
+ Uint32 fWindowID;
+ SDL_GLContext fGLContext;
int fMSAASampleCount;
diff --git a/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp
index 005fc07df46..f7e56ccb629 100644
--- a/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp
@@ -27,7 +27,7 @@ public:
void onSwapBuffers() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
- void onDestroyContext() override;
+ void onDestroyContext() override {}
private:
SDL_Window* fWindow;
@@ -39,7 +39,7 @@ private:
GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
: INHERITED(params)
, fWindow(info.fWindow)
- , fGLContext(nullptr) {
+ , fGLContext(info.fGLContext) {
// any config code here (particularly for msaa)?
@@ -52,12 +52,7 @@ GLWindowContext_mac::~GLWindowContext_mac() {
sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return nullptr;
- }
+ SkASSERT(fGLContext);
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
glClearStencil(0);
@@ -67,6 +62,7 @@ sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
glViewport(0, 0, fWidth, fHeight);
@@ -76,15 +72,6 @@ sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
return GrGLMakeNativeInterface();
}
-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);
diff --git a/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp
index 67022af7fef..b66ba407fa4 100644
--- a/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp
@@ -51,7 +51,7 @@ RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
const DisplayParams& params)
: INHERITED(params)
, fWindow(info.fWindow)
- , fGLContext(nullptr) {
+ , fGLContext(info.fGLContext) {
// any config code here (particularly for msaa)?
@@ -64,12 +64,7 @@ RasterWindowContext_mac::~RasterWindowContext_mac() {
sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
SkASSERT(fWindow);
-
- fGLContext = SDL_GL_CreateContext(fWindow);
- if (!fGLContext) {
- SkDebugf("%s\n", SDL_GetError());
- return nullptr;
- }
+ SkASSERT(fGLContext);
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
glClearStencil(0);
@@ -79,6 +74,7 @@ sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
glViewport(0, 0, fWidth, fHeight);
@@ -94,12 +90,7 @@ sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
}
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; }
diff --git a/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h b/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
index 3adc68bbc23..c195c24daa0 100644
--- a/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
+++ b/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
@@ -19,7 +19,8 @@ struct DisplayParams;
namespace window_context_factory {
struct MacWindowInfo {
- SDL_Window* fWindow;
+ SDL_Window* fWindow;
+ SDL_GLContext fGLContext;
};
inline WindowContext* NewVulkanForMac(const MacWindowInfo&, const DisplayParams&) {
diff --git a/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp
index 8de5b104500..309c8bbf362 100644
--- a/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp
@@ -49,7 +49,7 @@ bool Window_mac::initWindow() {
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
- if (fRequestedDisplayParams.fMSAASampleCount > 0) {
+ if (fRequestedDisplayParams.fMSAASampleCount > 1) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount);
} else {
@@ -71,10 +71,22 @@ bool Window_mac::initWindow() {
fWindowID = SDL_GetWindowID(fWindow);
gWindowMap.add(this);
+ fGLContext = SDL_GL_CreateContext(fWindow);
+ if (!fGLContext) {
+ SkDebugf("%s\n", SDL_GetError());
+ this->closeWindow();
+ return false;
+ }
+
return true;
}
void Window_mac::closeWindow() {
+ if (fGLContext) {
+ SDL_GL_DeleteContext(fGLContext);
+ fGLContext = nullptr;
+ }
+
if (fWindow) {
gWindowMap.remove(fWindowID);
SDL_DestroyWindow(fWindow);
@@ -251,6 +263,7 @@ bool Window_mac::attach(BackendType attachType) {
window_context_factory::MacWindowInfo info;
info.fWindow = fWindow;
+ info.fGLContext = fGLContext;
switch (attachType) {
case kRaster_BackendType:
fWindowContext = NewRasterForMac(info, fRequestedDisplayParams);
diff --git a/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h
index aa5c8df6962..8b34b7c902e 100644
--- a/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h
+++ b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h
@@ -19,10 +19,11 @@ namespace sk_app {
class Window_mac : public Window {
public:
Window_mac()
- : INHERITED()
- , fWindow(nullptr)
- , fWindowID(0)
- , fMSAASampleCount(0) {}
+ : INHERITED()
+ , fWindow(nullptr)
+ , fWindowID(0)
+ , fGLContext(nullptr)
+ , fMSAASampleCount(1) {}
~Window_mac() override { this->closeWindow(); }
bool initWindow();
@@ -51,8 +52,9 @@ private:
static SkTDynamicHash<Window_mac, Uint32> gWindowMap;
- SDL_Window* fWindow;
- Uint32 fWindowID;
+ SDL_Window* fWindow;
+ Uint32 fWindowID;
+ SDL_GLContext fGLContext;
int fMSAASampleCount;
diff --git a/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
index 25ec95cdd64..3a3a4b16d45 100644
--- a/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
@@ -99,6 +99,7 @@ sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
XWindow root;
int x, y;
diff --git a/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp
index f5ca5ee0736..745b4dd3fb0 100644
--- a/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp
@@ -72,7 +72,7 @@ bool Window_unix::initWindow(Display* display) {
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));
diff --git a/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h
index b59f502eb95..62a27950980 100644
--- a/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h
+++ b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h
@@ -20,13 +20,14 @@ namespace sk_app {
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);
diff --git a/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
index 649528d6cd4..452b462ba9f 100644
--- a/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
@@ -76,7 +76,8 @@ sk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
}
EGLint numConfigs;
fSampleCount = this->getDisplayParams().fMSAASampleCount;
- const int sampleBuffers = fSampleCount > 0 ? 1 : 0;
+ 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,
@@ -91,7 +92,7 @@ sk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
EGL_SAMPLE_BUFFERS,
sampleBuffers,
EGL_SAMPLES,
- fSampleCount,
+ eglSampleCnt,
EGL_NONE};
EGLConfig surfaceConfig;
diff --git a/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
index 7e43d2b544a..1c583cb1ed9 100644
--- a/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
@@ -96,8 +96,9 @@ sk_sp<const GrGLInterface> GLWindowContext_win::onInitializeContext() {
1,
&kSampleCountAttr,
&fSampleCount);
+ fSampleCount = SkTMax(fSampleCount, 1);
} else {
- fSampleCount = 0;
+ fSampleCount = 1;
}
RECT rect;
diff --git a/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
index 10db0ec675c..c442493b215 100644
--- a/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
@@ -303,8 +303,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
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;
@@ -319,8 +319,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
// 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;
}
}
diff --git a/chromium/third_party/skia/tools/sk_pixel_iter.h b/chromium/third_party/skia/tools/sk_pixel_iter.h
new file mode 100644
index 00000000000..8bf5a55647f
--- /dev/null
+++ b/chromium/third_party/skia/tools/sk_pixel_iter.h
@@ -0,0 +1,61 @@
+/*
+ * 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 sk_pixel_iter_DEFINED
+#define sk_pixel_iter_DEFINED
+
+#include "SkPixmap.h"
+#include "SkSurface.h"
+
+namespace sk_tool_utils {
+
+ 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 sk_tool_utils
+
+#endif // sk_tool_utils_DEFINED
diff --git a/chromium/third_party/skia/tools/sk_tool_utils.cpp b/chromium/third_party/skia/tools/sk_tool_utils.cpp
index 9d1b4df56c8..2eb8dba8337 100644
--- a/chromium/third_party/skia/tools/sk_tool_utils.cpp
+++ b/chromium/third_party/skia/tools/sk_tool_utils.cpp
@@ -10,9 +10,6 @@
#include "Resources.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkFontMgr.h"
-#include "SkFontStyle.h"
#include "SkImage.h"
#include "SkPixelRef.h"
#include "SkPM4f.h"
@@ -24,88 +21,33 @@
namespace sk_tool_utils {
-static 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];
- }
- }
- return "";
-}
-
-sk_sp<SkTypeface> emoji_typeface() {
-#if defined(SK_BUILD_FOR_WIN)
- 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());
-
-#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
- return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle());
-
-#else
- return MakeResourceAsTypeface("fonts/Funkster.ttf");
-
-#endif
-}
-
-const char* emoji_sample_text() {
-#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
- 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"; // 🇺🇸🇦
-#else
- return "Hamburgefons";
-#endif
-}
-
-static bool extra_config_contains(const char* substring) {
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (0 == strcmp("extra_config", FLAGS_key[index])
- && strstr(FLAGS_key[index + 1], substring)) {
- return true;
- }
- }
- return false;
-}
-
-const char* platform_font_manager() {
- if (extra_config_contains("GDI")) {
- return "GDI";
+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";
}
- if (extra_config_contains("NativeFonts")){
- return platform_os_name();
- }
- return "";
+ 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 kARGB_4444_SkColorType: return "ARGB_4444";
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_F16_SkColorType: return "RGBA_F16";
- default:
- SkASSERT(false);
- return "unexpected colortype";
}
+ SkASSERT(false);
+ return "unexpected colortype";
}
SkColor color_to_565(SkColor color) {
@@ -114,14 +56,6 @@ SkColor color_to_565(SkColor color) {
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);
@@ -130,6 +64,12 @@ void write_pixels(SkCanvas* canvas, const SkBitmap& bitmap, int x, int y,
canvas->writePixels(info, tmp.getPixels(), tmp.rowBytes(), x, y);
}
+void write_pixels(SkSurface* surface, const SkBitmap& src, int x, int y,
+ SkColorType colorType, SkAlphaType alphaType) {
+ const SkImageInfo info = SkImageInfo::Make(src.width(), src.height(), colorType, alphaType);
+ surface->writePixels({info, src.getPixels(), src.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));
diff --git a/chromium/third_party/skia/tools/sk_tool_utils.h b/chromium/third_party/skia/tools/sk_tool_utils.h
index 9081e3c56f0..6c1adf8e262 100644
--- a/chromium/third_party/skia/tools/sk_tool_utils.h
+++ b/chromium/third_party/skia/tools/sk_tool_utils.h
@@ -12,6 +12,7 @@
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
#include "SkRandom.h"
+#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTDArray.h"
#include "SkTypeface.h"
@@ -31,6 +32,7 @@ class SkTextBlobBuilder;
namespace sk_tool_utils {
+ const char* alphatype_name(SkAlphaType);
const char* colortype_name(SkColorType);
/**
@@ -68,10 +70,11 @@ namespace sk_tool_utils {
void release_portable_typefaces();
/**
- * Call canvas->writePixels() by using the pixels from bitmap, but with an info that claims
+ * Call 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);
+ void write_pixels(SkSurface*, const SkBitmap&, int x, int y, SkColorType, SkAlphaType);
/**
* Returns true iff all of the pixels between the two images differ by <= the maxDiff value
@@ -147,7 +150,7 @@ namespace sk_tool_utils {
SkRect compute_tallest_occluder(const SkRRect& rr);
// A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
- class TopoTestNode {
+ class TopoTestNode : public SkRefCnt {
public:
TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) { }
@@ -194,37 +197,29 @@ namespace sk_tool_utils {
}
// Helper functions for TopoSortBench & TopoSortTest
- static void AllocNodes(SkTDArray<TopoTestNode*>* graph, int num) {
- graph->setReserve(num);
+ static void AllocNodes(SkTArray<sk_sp<sk_tool_utils::TopoTestNode>>* graph, int num) {
+ graph->reserve(num);
for (int i = 0; i < num; ++i) {
- *graph->append() = new TopoTestNode(i);
+ graph->push_back(sk_sp<TopoTestNode>(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) {
+#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
+#endif
// randomize the array
- static void Shuffle(SkTDArray<TopoTestNode*>* graph, SkRandom* rand) {
+ 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);
- TopoTestNode* tmp = (*graph)[i];
- (*graph)[i] = (*graph)[swap];
- (*graph)[swap] = tmp;
+ (*graph)[i].swap((*graph)[swap]);
}
}
diff --git a/chromium/third_party/skia/tools/sk_tool_utils_font.cpp b/chromium/third_party/skia/tools/sk_tool_utils_font.cpp
deleted file mode 100644
index 8b2041ad1e6..00000000000
--- a/chromium/third_party/skia/tools/sk_tool_utils_font.cpp
+++ /dev/null
@@ -1,70 +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 fm->legacyMakeTypeface(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);
- fontData->fCachedFont = font;
- }
- }
- return sk_make_sp<SkTestTypeface>(std::move(font), style);
-}
-
-}
diff --git a/chromium/third_party/skia/tools/skdiff/skdiff.h b/chromium/third_party/skia/tools/skdiff/skdiff.h
index 6bdaadc28d1..1d4e8ace2a4 100644
--- a/chromium/third_party/skia/tools/skdiff/skdiff.h
+++ b/chromium/third_party/skia/tools/skdiff/skdiff.h
@@ -14,7 +14,7 @@
#include "SkString.h"
#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/chromium/third_party/skia/tools/skdiff/skdiff_html.cpp b/chromium/third_party/skia/tools/skdiff/skdiff_html.cpp
index 6f3c3b09e15..e0476bc005e 100644
--- a/chromium/third_party/skia/tools/skdiff/skdiff_html.cpp
+++ b/chromium/third_party/skia/tools/skdiff/skdiff_html.cpp
@@ -245,7 +245,7 @@ void print_diff_page(const int matchCount,
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/chromium/third_party/skia/tools/skdiff/skdiff_main.cpp b/chromium/third_party/skia/tools/skdiff/skdiff_main.cpp
index 93807852802..59e9b0a6b76 100644
--- a/chromium/third_party/skia/tools/skdiff/skdiff_main.cpp
+++ b/chromium/third_party/skia/tools/skdiff/skdiff_main.cpp
@@ -330,16 +330,10 @@ public:
SkASSERT(drp != nullptr);
}
~AutoReleasePixels() {
-#if 0
fDrp->fBase.fBitmap.setPixelRef(nullptr, 0, 0);
fDrp->fComparison.fBitmap.setPixelRef(nullptr, 0, 0);
fDrp->fDifference.fBitmap.setPixelRef(nullptr, 0, 0);
fDrp->fWhite.fBitmap.setPixelRef(nullptr, 0, 0);
-#endif
- fDrp->fBase.fBitmap.reset();
- fDrp->fComparison.fBitmap.reset();
- fDrp->fDifference.fBitmap.reset();
- fDrp->fWhite.fBitmap.reset();
}
private:
diff --git a/chromium/third_party/skia/tools/skp/webpages_playback.py b/chromium/third_party/skia/tools/skp/webpages_playback.py
index dad9a399290..41181607d7a 100644
--- a/chromium/third_party/skia/tools/skp/webpages_playback.py
+++ b/chromium/third_party/skia/tools/skp/webpages_playback.py
@@ -106,7 +106,7 @@ CHROMIUM_PAGE_SETS_TO_PREFIX = {
PAGE_SETS_TO_EXCLUSIONS = {
# See skbug.com/7348
- 'key_mobile_sites_smooth.py': '"(digg|worldjournal)"',
+ 'key_mobile_sites_smooth.py': '"(digg|worldjournal|Twitter)"',
# See skbug.com/7421
'top_25_smooth.py': '"(mail\.google\.com)"',
}
diff --git a/chromium/third_party/skia/tools/skpbench/skpbench.cpp b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
index fcab2d3af8f..562c48165fe 100644
--- a/chromium/third_party/skia/tools/skpbench/skpbench.cpp
+++ b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
@@ -292,7 +292,12 @@ int main(int argc, char** argv) {
GrPixelConfig grPixConfig = SkImageInfo2GrPixelConfig(config->getColorType(),
config->getColorSpace(),
*ctx->caps());
- int supportedSampleCount = ctx->caps()->getSampleCount(config->getSamples(), grPixConfig);
+ if (kUnknown_GrPixelConfig == grPixConfig) {
+ exitf(ExitErr::kUnavailable, "failed to get GrPixelConfig from SkColorType: %d",
+ config->getColorType());
+ }
+ int supportedSampleCount =
+ ctx->caps()->getRenderTargetSampleCount(config->getSamples(), grPixConfig);
if (supportedSampleCount != config->getSamples()) {
exitf(ExitErr::kUnavailable, "sample count %i not supported by platform",
config->getSamples());
diff --git a/chromium/third_party/skia/tools/skqp/README.md b/chromium/third_party/skia/tools/skqp/README.md
index e78e6edc6ed..fe2f54e9313 100644
--- a/chromium/third_party/skia/tools/skqp/README.md
+++ b/chromium/third_party/skia/tools/skqp/README.md
@@ -1,86 +1,104 @@
-
SkQP
====
-**Motivation**: Test an Android device's GPU and OpenGLES & Vulkan drivers with
-Skia and Skia's existing unit & rendering tests.
+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
-How To Use SkQP on your Android device:
+3. Download dependencies and the model:
-1. To build SkQP you need to install the
- [Android NDK](https://developer.android.com/ndk/).
+ python tools/skqp/download_model
+ python tools/skqp/setup_resources
+ python tools/git-sync-deps
-2. [Checkout depot\_tools and Skia](https://skia.org/user/download),
- then go to Skia's source directory:
+4. Configure the build:
- export PATH="${DEPOT_TOOLS_PATH}:$PATH"
- cd $SKIA_SOURCE_DIRECTORY
+ python tools/skqp/generate_gn_args out/skqp-arm "$ANDROID_NDK" \
+ --arch arm \
+ --api_level 26
+ bin/gn gen out/skqp-arm
-3. Configure and build Skia for your device's architecture:
+ If you want to test another architecture, replace `arm` with `x86`, `x64`
+ or `arm64`. Run 'python tools/skqp/generate_gn_args -h' for
+ all options.
- arch='arm64' # Also valid: 'arm', 'x68', 'x64'
- android_ndk="${HOME}/ndk" # Or wherever you installed the NDK.
- mkdir -p out/${arch}-rel
- cat > out/${arch}-rel/args.gn << EOF
- ndk = "$android_ndk"
- ndk_api = 24
- target_cpu = "$arch"
- skia_embed_resources = true
- is_debug = false
- EOF
- tools/git-sync-deps
- bin/gn gen out/${arch}-rel
- ninja -C out/${arch}-rel skqp_lib
+5. Build, install, and run.
-4. Download meta.json from [https://goo.gl/jBw3Dd](https://goo.gl/jBw3Dd) .
- This is the data used to build the validation model.
+ platform_tools/android/bin/android_build_app -C out/skqp-arm skqp
+ adb install -r out/skqp-arm/skqp.apk
+ adb logcat -c
+ adb shell am instrument -w org.skia.skqp
-5. Generate the validation model data:
+6. Monitor the output with:
- go get go.skia.org/infra/golden/go/search
- go run tools/skqp/make_gmkb.go ~/Downloads/meta.json \
- platform_tools/android/apps/skqp/src/main/assets/gmkb
+ adb logcat org.skia.skqp skia "*:S"
-Run as an executable
---------------------
+ Note the test's output path on the device. It will look something like this:
-1. Build the SkQP program, load files on the device, and run skqp:
+ 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"
- ninja -C out/${arch}-rel skqp
- adb shell "cd /data/local/tmp; rm -rf gmkb report"
- adb push platform_tools/android/apps/skqp/src/main/assets/gmkb \
- /data/local/tmp/
- adb push out/${arch}-rel/skqp /data/local/tmp/
- adb shell "cd /data/local/tmp; ./skqp gmkb report"
+7. Retrieve and view the report with:
-2. Get the error report if there are errors:
+ OUTPUT_LOCATION="/storage/emulated/0/Android/data/org.skia.skqp/files/output"
+ adb pull $OUTPUT_LOCATION /tmp/
+ tools/skqp/sysopen.py /tmp/output/skqp_report/report.html
- if adb shell test -d /data/local/tmp/report; then
- adb pull /data/local/tmp/report /tmp/
- tools/skqp/sysopen.py /tmp/report/report.html
- fi
+Running a single test
+---------------------
-Run as an APK
--------------
+To run a single test, for example `gles/aarectmodes`:
-0. Install the [Android SDK](https://developer.android.com/studio/#command-tools).
+ adb shell am instrument -e class 'org.skia.skqp.SkQPRunner#gles/aarectmodes' -w org.skia.skqp
- mkdir ~/android-sdk
- ( cd ~/android-sdk; unzip ~/Downloads/sdk-tools-*.zip )
- yes | ~/android-sdk/tools/bin/sdkmanager --licenses
- export ANDROID_HOME=~/android-sdk
+Unit tests can be run with the `unitTest/` prefix:
-1. Build the skqp.apk, load it on the device, and run the tests
+ adb shell am instrument -e class 'org.skia.skqp.SkQPRunner#unitTest/GrSurface -w org.skia.skqp
- platform_tools/android/bin/android_build_app -C out/${arch}-rel skqp
- adb install -r out/${arch}-rel/skqp.apk
- adb shell am instrument -w \
- org.skia.skqp/android.support.test.runner.AndroidJUnitRunner
+Run as a non-APK executable
+---------------------------
-2. Retrieve the report if there are any errors:
+1. Follow steps 1-3 as above.
- adb backup -f /tmp/skqp.ab org.skia.skqp
- # Must unlock phone and verify backup.
- tools/skqp/extract_report.py /tmp/skqp.ab
+2. Build the SkQP program, load files on the device, and run skqp:
+ ninja -C out/skqp-arm skqp
+ python tools/skqp/run_skqp_exe out/skqp-arm
diff --git a/chromium/third_party/skia/tools/skqp/download_model b/chromium/third_party/skia/tools/skqp/download_model
new file mode 100755
index 00000000000..209f5505905
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/download_model
@@ -0,0 +1,71 @@
+#! /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 0 == len(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:
+ # ignore race condition
+ if not os.path.exists(dirname):
+ raise
+ 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/chromium/third_party/skia/tools/skqp/extract_report.py b/chromium/third_party/skia/tools/skqp/extract_report.py
deleted file mode 100755
index 5fc3bf4ebe4..00000000000
--- a/chromium/third_party/skia/tools/skqp/extract_report.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /usr/bin/env python2
-# 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 StringIO
-import os
-import sys
-import sysopen
-import tarfile
-import tempfile
-import zlib
-
-if __name__ == '__main__':
- if len(sys.argv) != 2:
- print 'usage: %s FILE.ab\n' % sys.argv[0]
- exit (1)
- with open(sys.argv[1], 'rb') as f:
- f.read(24)
- t = tarfile.open(fileobj=StringIO.StringIO(zlib.decompress(f.read())))
- d = tempfile.mkdtemp(prefix='skqp_')
- t.extractall(d)
- p = os.path.join(d, 'apps/org.skia.skqp/f/skqp_report/report.html')
- assert os.path.isfile(p)
- print p
- sysopen.sysopen(p)
-
-
-
diff --git a/chromium/third_party/skia/tools/skqp/generate_gn_args b/chromium/third_party/skia/tools/skqp/generate_gn_args
new file mode 100755
index 00000000000..c9b1891c475
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/generate_gn_args
@@ -0,0 +1,58 @@
+#! /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
+
+fmt = '''
+target_cpu = "{arch}"
+is_debug = {debug}
+ndk = "{android_ndk_dir}"
+ndk_api = {api_level}
+skia_enable_fontmgr_empty = true
+skia_enable_pdf = false
+skia_skqp_global_error_tolerance = 4
+skia_use_dng_sdk = false
+skia_use_expat = false
+skia_use_icu = false
+skia_use_libheif = false
+skia_use_lua = false
+skia_use_piex = false
+skia_use_skcms = false
+skia_skqp_enable_driver_correctness_workarounds = {enable_workarounds}
+'''
+
+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('--enable_workarounds', default=False,
+ action='store_true', help="enable GPU work-arounds, defaults to false")
+ parser.add_argument('--debug', default=False, action='store_true',
+ help='compile native code in debug mode, defaults to false')
+
+ # parse the args and convert bools to strings.
+ args = parser.parse_args()
+ gn_bool = lambda b : 'true' if b else 'false'
+ args.enable_workarounds = gn_bool(args.enable_workarounds)
+ args.debug = gn_bool(args.debug)
+ args.android_ndk_dir = os.path.abspath(args.android_ndk_dir)
+ return args
+
+def make_args_gn(out_dir, args):
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir)
+ with open(os.path.join(out_dir, 'args.gn'), 'w') as o:
+ o.write(fmt.format(**args))
+
+if __name__ == '__main__':
+ args = parse_args()
+ make_args_gn(args.target_build_dir, vars(args))
diff --git a/chromium/third_party/skia/tools/skqp/gm_knowledge.cpp b/chromium/third_party/skia/tools/skqp/gm_knowledge.cpp
index 05a6a5ccd0a..df1ded0660b 100644
--- a/chromium/third_party/skia/tools/skqp/gm_knowledge.cpp
+++ b/chromium/third_party/skia/tools/skqp/gm_knowledge.cpp
@@ -26,11 +26,17 @@
#include "skqp_asset_manager.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_REPORT "report.html"
+#define PATH_CSV "out.csv"
+
+#ifndef SK_SKQP_GLOBAL_ERROR_TOLERANCE
+#define SK_SKQP_GLOBAL_ERROR_TOLERANCE 0
+#endif
////////////////////////////////////////////////////////////////////////////////
@@ -46,6 +52,60 @@ static int get_error(uint32_t value, uint32_t value_max, uint32_t value_min) {
error = std::max(vmin - v, error);
}
}
+ return std::max(0, error - SK_SKQP_GLOBAL_ERROR_TOLERANCE);
+}
+
+static int get_error_with_nearby(int x, int y, const SkPixmap& pm,
+ const SkPixmap& pm_max, const SkPixmap& pm_min) {
+ struct NearbyPixels {
+ const int x, y, w, h;
+ struct Iter {
+ const int x, y, w, h;
+ int8_t curr;
+ SkIPoint operator*() const { return this->get(); }
+ SkIPoint get() const {
+ switch (curr) {
+ case 0: return {x - 1, y - 1};
+ case 1: return {x , y - 1};
+ case 2: return {x + 1, y - 1};
+ case 3: return {x - 1, y };
+ case 4: return {x + 1, y };
+ case 5: return {x - 1, y + 1};
+ case 6: return {x , y + 1};
+ case 7: return {x + 1, y + 1};
+ default: SkASSERT(false); return {0, 0};
+ }
+ }
+ void skipBad() {
+ while (curr < 8) {
+ SkIPoint p = this->get();
+ if (p.x() >= 0 && p.y() >= 0 && p.x() < w && p.y() < h) {
+ return;
+ }
+ ++curr;
+ }
+ curr = -1;
+ }
+ void operator++() {
+ if (-1 == curr) { return; }
+ ++curr;
+ this->skipBad();
+ }
+ bool operator!=(const Iter& other) const { return curr != other.curr; }
+ };
+ Iter begin() const { Iter i{x, y, w, h, 0}; i.skipBad(); return i; }
+ Iter end() const { return Iter{x, y, w, h, -1}; }
+ };
+
+ uint32_t c = *pm.addr32(x, y);
+ int error = get_error(c, *pm_max.addr32(x, y), *pm_min.addr32(x, y));
+ for (SkIPoint p : NearbyPixels{x, y, pm.width(), pm.height()}) {
+ if (error == 0) {
+ return 0;
+ }
+ error = SkTMin(error, get_error(
+ c, *pm_max.addr32(p.x(), p.y()), *pm_min.addr32(p.x(), p.y())));
+ }
return error;
}
@@ -57,13 +117,6 @@ static float set_error_code(gmkb::Error* error_out, gmkb::Error error) {
return FLT_MAX;
}
-static SkPixmap to_pixmap(const SkBitmap& bitmap) {
- SkPixmap pixmap;
- SkAssertResult(bitmap.peekPixels(&pixmap));
- return pixmap;
-}
-
-
static bool WritePixmapToFile(const SkPixmap& pixmap, const char* path) {
SkFILEWStream wStream(path);
SkPngEncoder::Options options;
@@ -79,10 +132,6 @@ static SkPixmap rgba8888_to_pixmap(const uint32_t* pixels, int width, int height
return SkPixmap(info, pixels, width * sizeof(uint32_t));
}
-static bool asset_exists(skqp::AssetManager* mgr, const char* path) {
- return mgr && nullptr != mgr->open(path);
-}
-
static bool copy(skqp::AssetManager* mgr, const char* path, const char* dst) {
if (mgr) {
if (auto stream = mgr->open(path)) {
@@ -101,7 +150,7 @@ static SkBitmap ReadPngRgba8888FromFile(skqp::AssetManager* assetManager, const
SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), kColorType, kAlphaType);
bitmap.allocPixels(info);
SkASSERT(bitmap.rowBytes() == (unsigned)bitmap.width() * sizeof(uint32_t));
- if (SkCodec::kSuccess != codec->getPixels(to_pixmap(bitmap))) {
+ if (SkCodec::kSuccess != codec->getPixels(bitmap.pixmap())) {
bitmap.reset();
}
}
@@ -120,14 +169,16 @@ struct Run {
static std::vector<Run> gErrors;
static std::mutex gMutex;
-namespace gmkb {
-bool IsGoodGM(const char* name, skqp::AssetManager* assetManager) {
- return asset_exists(assetManager, SkOSPath::Join(name, PATH_MAX_PNG).c_str())
- && asset_exists(assetManager, SkOSPath::Join(name, PATH_MIN_PNG).c_str());
+static SkString make_path(const SkString& images_directory,
+ const char* backend,
+ const char* gm_name,
+ const char* thing) {
+ auto path = SkStringPrintf("%s_%s_%s", backend, gm_name, thing);
+ return SkOSPath::Join(images_directory.c_str(), path.c_str());
}
-// Assumes that for each GM foo, asset_manager has files foo/{max,min}.png and
-// that the report_directory_path already exists on disk.
+
+namespace gmkb {
float Check(const uint32_t* pixels,
int width,
int height,
@@ -136,19 +187,24 @@ float Check(const uint32_t* pixels,
skqp::AssetManager* assetManager,
const char* report_directory_path,
Error* error_out) {
+ if (report_directory_path && report_directory_path[0]) {
+ SkASSERT_RELEASE(sk_isdir(report_directory_path));
+ }
if (width <= 0 || height <= 0) {
return set_error_code(error_out, Error::kBadInput);
}
- size_t N = (unsigned)width * (unsigned)height;
- SkString max_path = SkOSPath::Join(name, PATH_MAX_PNG);
- SkString min_path = SkOSPath::Join(name, PATH_MIN_PNG);
+ constexpr char PATH_ROOT[] = "gmkb";
+ SkString img_path = SkOSPath::Join(PATH_ROOT, name);
+ SkString max_path = SkOSPath::Join(img_path.c_str(), PATH_MAX_PNG);
+ SkString min_path = SkOSPath::Join(img_path.c_str(), PATH_MIN_PNG);
SkBitmap max_image = ReadPngRgba8888FromFile(assetManager, max_path.c_str());
- if (max_image.isNull()) {
- return set_error_code(error_out, Error::kBadData);
- }
SkBitmap min_image = ReadPngRgba8888FromFile(assetManager, min_path.c_str());
- if (min_image.isNull()) {
- return set_error_code(error_out, Error::kBadData);
+ if (max_image.isNull() || min_image.isNull()) {
+ // No data.
+ if (error_out) {
+ *error_out = Error::kNone;
+ }
+ return 0;
}
if (max_image.width() != min_image.width() ||
max_image.height() != min_image.height())
@@ -158,18 +214,23 @@ float Check(const uint32_t* pixels,
if (max_image.width() != width || max_image.height() != height) {
return set_error_code(error_out, Error::kBadInput);
}
+
int badness = 0;
int badPixelCount = 0;
- const uint32_t* max_pixels = (uint32_t*)max_image.getPixels();
- const uint32_t* min_pixels = (uint32_t*)min_image.getPixels();
-
- for (size_t i = 0; i < N; ++i) {
- int error = get_error(pixels[i], max_pixels[i], min_pixels[i]);
- if (error > 0) {
- badness = SkTMax(error, badness);
- ++badPixelCount;
+ SkPixmap pm(SkImageInfo::Make(width, height, kColorType, kAlphaType),
+ pixels, width * sizeof(uint32_t));
+ SkPixmap pm_max = max_image.pixmap();
+ SkPixmap pm_min = min_image.pixmap();
+ for (int y = 0; y < pm.height(); ++y) {
+ for (int x = 0; x < pm.width(); ++x) {
+ int error = get_error_with_nearby(x, y, pm, pm_max, pm_min) ;
+ if (error > 0) {
+ badness = SkTMax(error, badness);
+ ++badPixelCount;
+ }
}
}
+
if (badness == 0) {
std::lock_guard<std::mutex> lock(gMutex);
gErrors.push_back(Run{SkString(backend), SkString(name), 0, 0});
@@ -178,27 +239,28 @@ float Check(const uint32_t* pixels,
if (!backend) {
backend = "skia";
}
- SkString report_directory = SkOSPath::Join(report_directory_path, backend);
- sk_mkdir(report_directory.c_str());
- SkString report_subdirectory = SkOSPath::Join(report_directory.c_str(), name);
- sk_mkdir(report_subdirectory.c_str());
- SkString error_path = SkOSPath::Join(report_subdirectory.c_str(), PATH_IMG_PNG);
+ SkString images_directory = SkOSPath::Join(report_directory_path, IMAGES_DIRECTORY_PATH);
+ sk_mkdir(images_directory.c_str());
+
+ SkString image_path = make_path(images_directory, backend, name, PATH_IMG_PNG);
+ SkString error_path = make_path(images_directory, backend, name, PATH_ERR_PNG);
+ SkString max_path_out = make_path(images_directory, backend, name, PATH_MAX_PNG);
+ SkString min_path_out = make_path(images_directory, backend, name, PATH_MIN_PNG);
+
SkAssertResult(WritePixmapToFile(rgba8888_to_pixmap(pixels, width, height),
- error_path.c_str()));
+ image_path.c_str()));
+
SkBitmap errorBitmap;
errorBitmap.allocPixels(SkImageInfo::Make(width, height, kColorType, kAlphaType));
- uint32_t* errors = (uint32_t*)errorBitmap.getPixels();
- for (size_t i = 0; i < N; ++i) {
- int error = get_error(pixels[i], max_pixels[i], min_pixels[i]);
- errors[i] = error > 0 ? 0xFF000000 + (unsigned)error : 0x00000000;
+ for (int y = 0; y < pm.height(); ++y) {
+ for (int x = 0; x < pm.width(); ++x) {
+ int error = get_error_with_nearby(x, y, pm, pm_max, pm_min);
+ *errorBitmap.getAddr32(x, y) =
+ error > 0 ? 0xFF000000 + (unsigned)error : 0xFFFFFFFF;
+ }
}
- error_path = SkOSPath::Join(report_subdirectory.c_str(), PATH_ERR_PNG);
- SkAssertResult(WritePixmapToFile(to_pixmap(errorBitmap), error_path.c_str()));
-
- SkString report_path = SkOSPath::Join(report_subdirectory.c_str(), PATH_REPORT);
+ SkAssertResult(WritePixmapToFile(errorBitmap.pixmap(), error_path.c_str()));
- SkString max_path_out = SkOSPath::Join(report_subdirectory.c_str(), PATH_MAX_PNG);
- SkString min_path_out = SkOSPath::Join(report_subdirectory.c_str(), PATH_MIN_PNG);
(void)copy(assetManager, max_path.c_str(), max_path_out.c_str());
(void)copy(assetManager, min_path.c_str(), min_path_out.c_str());
@@ -211,65 +273,140 @@ float Check(const uint32_t* pixels,
return (float)badness;
}
-bool MakeReport(const char* report_directory_path) {
- std::lock_guard<std::mutex> lock(gMutex);
- {
- SkFILEWStream csvOut(SkOSPath::Join(report_directory_path, "out.csv").c_str());
- if (!csvOut.isValid()) {
- return false;
- }
- for (const Run& run : gErrors) {
- SkString line = SkStringPrintf("\"%s\",\"%s\",%d,%d\n",
- run.fBackend.c_str(), run.fGM.c_str(),
- run.fMaxerror, run.fBadpixels);
- csvOut.write(line.c_str(), line.size());
- }
+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) {\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"
+ " var q = \"" IMAGES_DIRECTORY_PATH "/\" + backend + \"_\" + 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(q + \"" PATH_MAX_PNG "\", ct(\"max\")));\n"
+ " ac(b, ct(\" | \"));\n"
+ " ac(b, ma(q + \"" 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(\"[\" + e1 + \"] \"));\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)</p>\n"
+ "<hr>\n"
+ "</body>\n"
+ "</html>\n";
+
+static void write(SkWStream* wStream, const SkString& text) {
+ wStream->write(text.c_str(), text.size());
+}
+
+enum class Backend {
+ kUnknown,
+ kGLES,
+ kVulkan,
+};
+
+static Backend get_backend(const SkString& s) {
+ if (s.equals("gles")) {
+ return Backend::kGLES;
+ } else if (s.equals("vk")) {
+ return Backend::kVulkan;
}
+ return Backend::kUnknown;
+}
+
- SkFILEWStream out(SkOSPath::Join(report_directory_path, PATH_REPORT).c_str());
- if (!out.isValid()) {
+bool MakeReport(const char* report_directory_path) {
+ int glesErrorCount = 0, vkErrorCount = 0, gles = 0, vk = 0;
+
+ SkASSERT_RELEASE(sk_isdir(report_directory_path));
+ std::lock_guard<std::mutex> lock(gMutex);
+ SkFILEWStream csvOut(SkOSPath::Join(report_directory_path, PATH_CSV).c_str());
+ SkFILEWStream htmOut(SkOSPath::Join(report_directory_path, PATH_REPORT).c_str());
+ SkASSERT_RELEASE(csvOut.isValid());
+ if (!csvOut.isValid() || !htmOut.isValid()) {
return false;
}
- out.writeText(
- "<!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"
- "</style>\n"
- "</head>\n"
- "<body>\n"
- "<h1>SkQP Report</h1>\n"
- "<hr>\n");
+ htmOut.writeText(kDocHead);
for (const Run& run : gErrors) {
- const SkString& backend = run.fBackend;
- const SkString& gm = run.fGM;
- int maxerror = run.fMaxerror;
- int badpixels = run.fBadpixels;
- if (maxerror == 0 && badpixels == 0) {
+ auto backend = get_backend(run.fBackend);
+ switch (backend) {
+ case Backend::kGLES: ++gles; break;
+ case Backend::kVulkan: ++vk; break;
+ default: break;
+ }
+ write(&csvOut, SkStringPrintf("\"%s\",\"%s\",%d,%d\n",
+ run.fBackend.c_str(), run.fGM.c_str(),
+ run.fMaxerror, run.fBadpixels));
+ if (run.fMaxerror == 0 && run.fBadpixels == 0) {
continue;
}
- SkString rdir = SkOSPath::Join(backend.c_str(), gm.c_str());
- SkString text = SkStringPrintf(
- "<h2>%s</h2>\n"
- "backend: %s\n<br>\n"
- "gm name: %s\n<br>\n"
- "maximum error: %d\n<br>\n"
- "bad pixel counts: %d\n<br>\n"
- "<a href=\"%s/" PATH_IMG_PNG "\">"
- "<img src=\"%s/" PATH_IMG_PNG "\" alt='img'></a>\n"
- "<a href=\"%s/" PATH_ERR_PNG "\">"
- "<img src=\"%s/" PATH_ERR_PNG "\" alt='err'></a>\n<br>\n"
- "<a href=\"%s/" PATH_MAX_PNG "\">max</a>\n<br>\n"
- "<a href=\"%s/" PATH_MIN_PNG "\">min</a>\n<hr>\n\n",
- rdir.c_str(), backend.c_str(), gm.c_str(), maxerror, badpixels,
- rdir.c_str(), rdir.c_str(), rdir.c_str(),
- rdir.c_str(), rdir.c_str(), rdir.c_str());
- out.write(text.c_str(), text.size());
+ write(&htmOut, SkStringPrintf(" f(\"%s\", \"%s\", %d, %d);\n",
+ run.fBackend.c_str(), run.fGM.c_str(),
+ run.fMaxerror, run.fBadpixels));
+ switch (backend) {
+ case Backend::kGLES: ++glesErrorCount; break;
+ case Backend::kVulkan: ++vkErrorCount; break;
+ default: break;
+ }
}
- out.writeText("</body>\n</html>\n");
+ 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);
return true;
}
} // namespace gmkb
diff --git a/chromium/third_party/skia/tools/skqp/gm_knowledge.h b/chromium/third_party/skia/tools/skqp/gm_knowledge.h
index 25399c4c0d0..6a19a870346 100644
--- a/chromium/third_party/skia/tools/skqp/gm_knowledge.h
+++ b/chromium/third_party/skia/tools/skqp/gm_knowledge.h
@@ -57,16 +57,6 @@ float Check(const uint32_t* pixels,
Error* error_out);
/**
-Check to see if the given test has expected results.
-
-@param name The name of a rendering test.
-@param assetManager GM KnowledgeBase data files
-
-@return true of expected results are known for the given test.
-*/
-bool IsGoodGM(const char* name, skqp::AssetManager* assetManager);
-
-/**
Call this after running all checks.
@param report_directory_path locatation to write report to.
diff --git a/chromium/third_party/skia/tools/skqp/gm_runner.cpp b/chromium/third_party/skia/tools/skqp/gm_runner.cpp
index 3c3885ef5c3..778c2bc6650 100644
--- a/chromium/third_party/skia/tools/skqp/gm_runner.cpp
+++ b/chromium/third_party/skia/tools/skqp/gm_runner.cpp
@@ -9,12 +9,13 @@
#include <algorithm>
-#include "../dm/DMFontMgr.h"
+#include "../tools/fonts/SkTestFontMgr.h"
#include "GrContext.h"
#include "GrContextOptions.h"
#include "SkFontMgrPriv.h"
#include "SkFontStyle.h"
#include "SkGraphics.h"
+#include "SkImageInfoPriv.h"
#include "SkSurface.h"
#include "Test.h"
#include "gl/GLTestContext.h"
@@ -22,6 +23,47 @@
#include "gm_knowledge.h"
#include "vk/VkTestContext.h"
+static SkTHashSet<SkString> gDoNotScoreInCompatibilityTestMode;
+static SkTHashSet<SkString> gDoNotExecuteInExperimentalMode;
+static SkTHashSet<SkString> gKnownGpuUnitTests;
+static SkTHashSet<SkString> gKnownGMs;
+static gm_runner::Mode gMode = gm_runner::Mode::kCompatibilityTestMode;
+
+static bool is_empty(const SkTHashSet<SkString>& set) {
+ return 0 == set.count();
+}
+static bool in_set(const char* s, const SkTHashSet<SkString>& set) {
+ return !is_empty(set) && nullptr != set.find(SkString(s));
+}
+
+static void readlist(skqp::AssetManager* mgr, const char* path, SkTHashSet<SkString>* dst) {
+ auto asset = mgr->open(path);
+ if (!asset || asset->getLength() == 0) {
+ return; // missing file same as empty file.
+ }
+ std::vector<char> buffer(asset->getLength() + 1);
+ asset->read(buffer.data(), buffer.size());
+ buffer.back() = '\0';
+ const char* ptr = buffer.data();
+ const char* end = &buffer.back();
+ SkASSERT(ptr < end);
+ while (true) {
+ while (*ptr == '\n' && ptr < end) {
+ ++ptr;
+ }
+ if (ptr == end) {
+ return;
+ }
+ const char* find = strchr(ptr, '\n');
+ if (!find) {
+ find = end;
+ }
+ SkASSERT(find > ptr);
+ dst->add(SkString(ptr, find - ptr));
+ ptr = find;
+ }
+}
+
namespace gm_runner {
const char* GetErrorString(Error e) {
@@ -44,6 +86,7 @@ std::vector<std::string> ExecuteTest(UnitTest test) {
}
} r;
GrContextOptions options;
+ // options.fDisableDriverCorrectnessWorkarounds = true;
if (test->fContextOptionsProc) {
test->fContextOptionsProc(&options);
}
@@ -57,10 +100,15 @@ std::vector<UnitTest> GetUnitTests() {
std::vector<UnitTest> tests;
for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
const skiatest::Test& test = r->factory();
- if (test.needsGpu) {
+ if ((is_empty(gKnownGpuUnitTests) || in_set(test.name, gKnownGpuUnitTests))
+ && test.needsGpu) {
tests.push_back(&test);
}
}
+ struct {
+ bool operator()(UnitTest u, UnitTest v) const { return strcmp(u->name, v->name) < 0; }
+ } less;
+ std::sort(tests.begin(), tests.end(), less);
return tests;
}
@@ -94,6 +142,9 @@ static GrContextOptions context_options(skiagm::GM* gm = nullptr) {
GrContextOptions grContextOptions;
grContextOptions.fAllowPathMaskCaching = true;
grContextOptions.fSuppressPathRendering = true;
+ #ifndef SK_SKQP_ENABLE_DRIVER_CORRECTNESS_WORKAROUNDS
+ grContextOptions.fDisableDriverCorrectnessWorkarounds = true;
+ #endif
if (gm) {
gm->modifyGrContextOptions(&grContextOptions);
}
@@ -118,6 +169,7 @@ std::vector<SkiaBackend> GetSupportedBackends() {
}
}
}
+ SkASSERT_RELEASE(result.size() > 0);
return result;
}
@@ -167,14 +219,21 @@ std::tuple<float, Error> EvaluateGM(SkiaBackend backend,
skqp::AssetManager* assetManager,
const char* reportDirectoryPath) {
std::vector<uint32_t> pixels;
+ SkASSERT(gmFact);
std::unique_ptr<skiagm::GM> gm(gmFact(nullptr));
+ SkASSERT(gm);
+ const char* name = gm->getName();
int width = 0, height = 0;
if (!evaluate_gm(backend, gm.get(), &width, &height, &pixels)) {
return std::make_tuple(FLT_MAX, Error::SkiaFailure);
}
+ if (Mode::kCompatibilityTestMode == gMode && in_set(name, gDoNotScoreInCompatibilityTestMode)) {
+ return std::make_tuple(0, Error::None);
+ }
+
gmkb::Error e;
float value = gmkb::Check(pixels.data(), width, height,
- gm->getName(), GetBackendName(backend), assetManager,
+ name, GetBackendName(backend), assetManager,
reportDirectoryPath, &e);
Error error = gmkb::Error::kBadInput == e ? Error::BadSkiaOutput
: gmkb::Error::kBadData == e ? Error::BadGMKBData
@@ -182,19 +241,29 @@ std::tuple<float, Error> EvaluateGM(SkiaBackend backend,
return std::make_tuple(value, error);
}
-void InitSkia() {
+void InitSkia(Mode mode, skqp::AssetManager* mgr) {
SkGraphics::Init();
- gSkFontMgr_DefaultFactory = &DM::MakeFontMgr;
+ gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
+
+ gMode = mode;
+ readlist(mgr, "skqp/DoNotScoreInCompatibilityTestMode.txt",
+ &gDoNotScoreInCompatibilityTestMode);
+ readlist(mgr, "skqp/DoNotExecuteInExperimentalMode.txt", &gDoNotExecuteInExperimentalMode);
+ readlist(mgr, "skqp/KnownGpuUnitTests.txt", &gKnownGpuUnitTests);
+ readlist(mgr, "skqp/KnownGMs.txt", &gKnownGMs);
}
std::vector<GMFactory> GetGMFactories(skqp::AssetManager* assetManager) {
std::vector<GMFactory> result;
for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
GMFactory f = r->factory();
-
- if (gmkb::IsGoodGM(GetGMName(f).c_str(), assetManager)) {
- result.push_back(r->factory());
- SkASSERT(result.back());
+ SkASSERT(f);
+ auto name = GetGMName(f);
+ if ((is_empty(gKnownGMs) || in_set(name.c_str(), gKnownGMs)) &&
+ !(Mode::kExperimentalMode == gMode &&
+ in_set(name.c_str(), gDoNotExecuteInExperimentalMode)))
+ {
+ result.push_back(f);
}
}
struct {
diff --git a/chromium/third_party/skia/tools/skqp/gm_runner.h b/chromium/third_party/skia/tools/skqp/gm_runner.h
index 690b3714e64..2707966c9c5 100644
--- a/chromium/third_party/skia/tools/skqp/gm_runner.h
+++ b/chromium/third_party/skia/tools/skqp/gm_runner.h
@@ -37,10 +37,20 @@ enum class SkiaBackend {
kVulkan,
};
+enum class Mode {
+ /** This mode is set when used by Android CTS. All known tests are executed. */
+ kCompatibilityTestMode,
+ /** This mode is set when used in the test lab. Some tests are skipped, if
+ they are known to cause crashes in older devices. All GMs are evaluated
+ with stricter requirements. */
+ kExperimentalMode,
+
+};
+
/**
Initialize Skia
*/
-void InitSkia();
+void InitSkia(Mode, skqp::AssetManager*);
std::vector<SkiaBackend> GetSupportedBackends();
diff --git a/chromium/third_party/skia/tools/skqp/gn_to_bp.py b/chromium/third_party/skia/tools/skqp/gn_to_bp.py
new file mode 100644
index 00000000000..299b1c979d0
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/gn_to_bp.py
@@ -0,0 +1,216 @@
+#!/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
+
+# 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",
+ tags: ["tests", "optional"],
+
+ cflags: [
+ $cflags
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+
+ cppflags:[
+ $cflags_cc
+ ],
+
+ local_include_dirs: [
+ $local_includes
+ ],
+
+ srcs: [
+ $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
+ ],
+ cflags: [
+ // Clang seems to think new/malloc will only be 4-byte aligned
+ // on x86 Android. We're pretty sure it's actually 8-byte
+ // alignment. tests/OverAlignedTest.cpp has more information,
+ // and should fail if we're wrong.
+ "-Wno-over-aligned"
+ ],
+ },
+
+ x86_64: {
+ srcs: [
+ $x86_srcs
+ ],
+ },
+ },
+
+ shared_libs: [
+ "libandroid",
+ "libEGL",
+ "libGLESv2",
+ "liblog",
+ "libvulkan",
+ "libz",
+ ],
+ static_libs: [
+ "libjpeg_static_ndk",
+ "libjsoncpp",
+ "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',
+ 'skia_skqp_global_error_tolerance': '4',
+
+ # setup vulkan
+ 'skia_use_vulkan': 'true',
+ 'skia_vulkan_header': '"Skia_Vulkan_Android.h"',
+
+ # enable/disable skia subsystems
+ 'skia_enable_fontmgr_empty': 'true',
+ 'skia_enable_pdf': 'false',
+ 'skia_use_expat': 'false',
+ 'skia_use_dng_sdk': 'false',
+ 'skia_use_icu': 'false',
+ 'skia_use_lua': 'false',
+ 'skia_use_piex': 'false',
+ 'skia_use_skcms': 'false',
+
+ # 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_jsoncpp': 'true',
+ 'skia_use_system_libwebp': 'true',
+ 'skia_use_system_libjpeg_turbo': 'true',
+ 'skia_use_system_zlib': 'true',
+}
+
+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']}
+
+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' ]),
+ })
+
diff --git a/chromium/third_party/skia/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp b/chromium/third_party/skia/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
index 7347f28ff9b..b59af6a8d4c 100644
--- a/chromium/third_party/skia/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
+++ b/chromium/third_party/skia/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
@@ -8,18 +8,21 @@
#include <mutex>
#include <vector>
-#include <jni.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
+#include <jni.h>
+#include <sys/stat.h>
-#include "gm_runner.h"
+#include "ResourceFactory.h"
+#include "SkOSPath.h"
+#include "SkStream.h"
#include "gm_knowledge.h"
+#include "gm_runner.h"
#include "skqp_asset_manager.h"
-#include "SkStream.h"
////////////////////////////////////////////////////////////////////////////////
extern "C" {
-JNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nInit(JNIEnv*, jobject, jobject, jstring);
+JNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nInit(JNIEnv*, jobject, jobject, jstring, jboolean);
JNIEXPORT jfloat JNICALL Java_org_skia_skqp_SkQP_nExecuteGM(JNIEnv*, jobject, jint, jint);
JNIEXPORT jobjectArray JNICALL Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv*, jobject,
jint);
@@ -74,13 +77,13 @@ struct AndroidAssetManager : public skqp::AssetManager {
return dup;
}
};
+ // SkDebugf("AndroidAssetManager::open(\"%s\");", path);
AAsset* asset = AndroidAssetManager::OpenAsset(fMgr, path);
return asset ? std::unique_ptr<SkStreamAsset>(new AAStrm(fMgr, std::string(path), asset))
: nullptr;
}
static AAsset* OpenAsset(AAssetManager* mgr, const char* path) {
- std::string fullPath = std::string("gmkb/") + path;
- return mgr ? AAssetManager_open(mgr, fullPath.c_str(), AASSET_MODE_STREAMING) : nullptr;
+ return mgr ? AAssetManager_open(mgr, path, AASSET_MODE_STREAMING) : nullptr;
}
};
}
@@ -107,6 +110,25 @@ static jclass gStringClass = nullptr;
////////////////////////////////////////////////////////////////////////////////
+sk_sp<SkData> get_resource(const char* resource) {
+ AAssetManager* mgr = gAssetManager.fMgr;
+ if (!mgr) {
+ return nullptr;
+ }
+ SkString path = SkOSPath::Join("resources", resource);
+ AAsset* asset = AAssetManager_open(mgr, 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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
template <typename T, typename F>
jobjectArray to_java_string_array(JNIEnv* env,
const std::vector<T>& array,
@@ -119,24 +141,35 @@ jobjectArray to_java_string_array(JNIEnv* env,
}
void Java_org_skia_skqp_SkQP_nInit(JNIEnv* env, jobject object, jobject assetManager,
- jstring dataDir) {
+ jstring dataDir, jboolean experimentalMode) {
jclass clazz = env->GetObjectClass(object);
jassert(env, assetManager);
- gm_runner::InitSkia();
-
std::lock_guard<std::mutex> lock(gMutex);
gAssetManager.fMgr = AAssetManager_fromJava(env, assetManager);
jassert(env, gAssetManager.fMgr);
+ gm_runner::InitSkia(experimentalMode ? gm_runner::Mode::kExperimentalMode
+ : gm_runner::Mode::kCompatibilityTestMode,
+ &gAssetManager);
+ gResourceFactory = &get_resource;
+
const char* dataDirString = env->GetStringUTFChars(dataDir, nullptr);
+ jassert(env, dataDirString && dataDirString[0]);
gReportDirectory = std::string(dataDirString) + "/skqp_report";
+ int mkdirRetval = mkdir(gReportDirectory.c_str(), 0777);
+ SkASSERT_RELEASE(0 == mkdirRetval);
+
env->ReleaseStringUTFChars(dataDir, dataDirString);
gBackends = gm_runner::GetSupportedBackends();
+ jassert(env, gBackends.size() > 0);
gGMs = gm_runner::GetGMFactories(&gAssetManager);
+ jassert(env, gGMs.size() > 0);
gUnitTests = gm_runner::GetUnitTests();
+ jassert(env, gUnitTests.size() > 0);
gStringClass = env->FindClass("java/lang/String");
+ jassert(env, gStringClass);
constexpr char stringArrayType[] = "[Ljava/lang/String;";
env->SetObjectField(object, env->GetFieldID(clazz, "mBackends", stringArrayType),
@@ -186,7 +219,9 @@ jobjectArray Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv* env,
if (errors.size() == 0) {
return nullptr;
}
- jobjectArray array = env->NewObjectArray(errors.size(), gStringClass, nullptr);
+ jclass stringClass = env->FindClass("java/lang/String");
+ jassert(env, stringClass);
+ 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);
}
diff --git a/chromium/third_party/skia/tools/skqp/make_apk.sh b/chromium/third_party/skia/tools/skqp/make_apk.sh
new file mode 100755
index 00000000000..6da2063fe35
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/make_apk.sh
@@ -0,0 +1,49 @@
+#! /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
+
+ANDROID_NDK="$1"
+
+if ! [ -d "$ANDROID_NDK" ] || ! [ -x "${ANDROID_NDK}/ndk-build" ]; then
+ printf "\nUsage:\n %s ANDROID_NDK_PATH\n" "$0" >&2
+ exit 1
+fi
+
+case ":${PATH}:" in
+ */depot_tools:*) ;;
+ *)
+ printf '\ndepot_tools should be in your $PATH.\n' >&2
+ exit 1;;
+esac
+
+if ! [ -d "$ANDROID_HOME" ] || ! [ -x "${ANDROID_HOME}/platform-tools/adb" ]; then
+ printf '\n$ANDROID_HOME not set or is broken.\n' >&2
+ exit 1
+fi
+
+set -x
+
+ARCH=${SKQP_ARCH:-arm}
+
+cd "$(dirname "$0")/../.."
+
+BUILD=out/skqp-${ARCH}
+
+python tools/skqp/generate_gn_args $BUILD "$ANDROID_NDK" $ARCH
+
+GIT_SYNC_DEPS_QUIET=Y tools/git-sync-deps
+
+bin/gn gen $BUILD
+
+rm -rf $BUILD/gen
+
+platform_tools/android/bin/android_build_app -C $BUILD skqp
+
+set +x
+
+printf '\n\nAPK built: "%s/skqp.apk"\n\n' "$(pwd)/$BUILD"
+
diff --git a/chromium/third_party/skia/tools/skqp/make_gmkb.go b/chromium/third_party/skia/tools/skqp/make_gmkb.go
index f839375d837..a445f6df801 100644
--- a/chromium/third_party/skia/tools/skqp/make_gmkb.go
+++ b/chromium/third_party/skia/tools/skqp/make_gmkb.go
@@ -44,38 +44,14 @@ func in(v string, a []string) bool {
return false
}
-// TODO(halcanary): clean up this blacklist.
-var blacklist = []string{
- "circular-clips",
- "colorcomposefilter_wacky",
- "coloremoji_blendmodes",
- "colormatrix",
- "complexclip_bw",
- "complexclip_bw_invert",
- "complexclip_bw_layer",
- "complexclip_bw_layer_invert",
- "convex-lineonly-paths-stroke-and-fill",
- "dftext",
- "downsamplebitmap_image_high_mandrill_512.png",
- "downsamplebitmap_image_medium_mandrill_512.png",
- "filterbitmap_image_mandrill_16.png",
- "filterbitmap_image_mandrill_64.png",
- "filterbitmap_image_mandrill_64.png_g8",
- "gradients_degenerate_2pt",
- "gradients_degenerate_2pt_nodither",
- "gradients_local_perspective",
- "gradients_local_perspective_nodither",
- "imagefilterstransformed",
- "image_scale_aligned",
- "lattice",
- "linear_gradient",
- "mipmap_srgb",
- "mixedtextblobs",
- "OverStroke",
- "simple-offsetimagefilter",
- "strokerect",
- "textblobmixedsizes",
- "textblobmixedsizes_df"}
+func clampU8(v int) uint8 {
+ if v < 0 {
+ return 0
+ } else if v > 255 {
+ return 255
+ }
+ return uint8(v)
+}
func processTest(testName string, imgUrls []string, output string) error {
if strings.ContainsRune(testName, '/') {
@@ -117,6 +93,7 @@ func processTest(testName string, imgUrls []string, output string) error {
if img_max.Rect.Max.X == 0 {
return nil
}
+
if err := os.Mkdir(output_directory, os.ModePerm); err != nil && !os.IsExist(err) {
return err
}
@@ -190,9 +167,6 @@ func main() {
var wg sync.WaitGroup
for _, record := range records {
- if in(record.TestName, blacklist) {
- continue
- }
var goodUrls []string
for _, digest := range record.Digests {
if (in("vk", digest.ParamSet["config"]) ||
diff --git a/chromium/third_party/skia/tools/skqp/make_known_tests.sh b/chromium/third_party/skia/tools/skqp/make_known_tests.sh
new file mode 100755
index 00000000000..7242db625df
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/make_known_tests.sh
@@ -0,0 +1,26 @@
+#! /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 -x
+
+cd "$(dirname "$0")/../.."
+
+BUILD=out/default
+
+python tools/git-sync-deps
+
+bin/gn gen $BUILD
+
+ninja -C $BUILD list_gms list_gpu_unit_tests
+
+DIR=platform_tools/android/apps/skqp/src/main/assets/skqp
+
+mkdir -p $DIR
+
+$BUILD/list_gms > $DIR/KnownGMs.txt
+
+$BUILD/list_gpu_unit_tests > $DIR/KnownGpuUnitTests.txt
+
diff --git a/chromium/third_party/skia/tools/skqp/make_model.sh b/chromium/third_party/skia/tools/skqp/make_model.sh
new file mode 100755
index 00000000000..3946dd9e852
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/make_model.sh
@@ -0,0 +1,20 @@
+#! /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.
+
+if ! [ -f "$1" ]; then
+ printf 'Usage:\n %s META_JSON_FILE_PATH\n\n' "$0" >&2
+ exit 1
+fi
+
+set -e -x
+
+SKIA="$(dirname "$0")/../.."
+
+go get -u go.skia.org/infra/golden/go/search
+
+go run "${SKIA}/tools/skqp/make_gmkb.go" "$1" \
+ "${SKIA}/platform_tools/android/apps/skqp/src/main/assets/gmkb"
+
diff --git a/chromium/third_party/skia/tools/skqp/make_universal_apk b/chromium/third_party/skia/tools/skqp/make_universal_apk
new file mode 100755
index 00000000000..56b725380b3
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/make_universal_apk
@@ -0,0 +1,97 @@
+#! /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.
+
+usage() {
+ cat >&2 <<EOM
+
+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:
+
+ $0 arm x86
+
+The environment variables ANDROID_NDK and ANDROID_HOME must be set to the
+locations of the Android NDK and SDK. Current values:
+
+ ANDROID_NDK="$ANDROID_NDK"
+ ANDROID_HOME="$ANDROID_HOME"
+
+Additionally, \`python\` and \`ninja\` should be in your path.
+
+If SKQP_EXTRA_MODELS is non-empty, assets unneeded by the CTS tests will be
+included for experimental mode.
+
+EOM
+ exit 1
+}
+
+[ -d "$ANDROID_NDK" ] || usage
+[ -d "$ANDROID_HOME" ] || usage
+command -v ninja > /dev/null || usage
+command -v python > /dev/null || usage
+for ARCH in $*; do case $ARCH in arm|arm64|x86|x64);; *) usage;; esac; done
+
+set -x # Verbose
+set -e # Exit immediately
+
+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
+)
+python tools/skqp/download_model
+if [ -z "$SKQP_EXTRA_MODELS" ]; then
+ python tools/skqp/remove_unneeded_assets
+fi
+
+python tools/skqp/setup_resources
+python tools/git-sync-deps
+
+APP=skqp
+LIB=libskqp_app.so
+
+find platform_tools/android/apps/$APP -name $LIB -exec rm {} +
+
+if [ $# -eq 0 ]; then
+ set -- arm arm64 x86 x64
+fi
+
+for ARCH in $*; do
+ if [ "$SKQP_DEBUG" ]; then
+ BUILD=out/skqp-${ARCH}-debug
+ python tools/skqp/generate_gn_args $BUILD "$ANDROID_NDK" --arch "$ARCH" --debug
+ else
+ BUILD=out/skqp-$ARCH
+ python tools/skqp/generate_gn_args $BUILD "$ANDROID_NDK" --arch "$ARCH"
+ fi
+ bin/gn gen $BUILD
+ ninja -C $BUILD $LIB
+ case $ARCH in
+ arm) NATIVE=armeabi-v7a ;;
+ arm64) NATIVE=arm64-v8a ;;
+ x86) NATIVE=x86 ;;
+ x64) NATIVE=x86_64 ;;
+ *) usage ;;
+ esac
+ DST=platform_tools/android/apps/$APP/src/main/libs/$NATIVE
+ mkdir -p $DST
+ cp -a $BUILD/$LIB $DST/$LIB
+done
+
+(
+ cd platform_tools/android
+ apps/gradlew -p apps/$APP -P suppressNativeBuild :$APP:assembleUniversalDebug
+)
+
+mkdir -p out/skqp
+cp platform_tools/android/apps/$APP/build/outputs/apk/$APP-universal-debug.apk out/skqp/
+
diff --git a/chromium/third_party/skia/tools/skqp/remove_unneeded_assets b/chromium/third_party/skia/tools/skqp/remove_unneeded_assets
new file mode 100755
index 00000000000..67bf9cff037
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/remove_unneeded_assets
@@ -0,0 +1,34 @@
+#! /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
+
+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 main():
+ assets = os.path.join('platform_tools', 'android', 'apps', 'skqp', 'src', 'main', 'assets')
+ os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, assets))
+ known = gset('skqp/KnownGMs.txt')
+ nope = gset('skqp/DoNotScoreInCompatibilityTestMode.txt')
+ present = set(os.listdir('gmkb'))
+ to_delete = present & nope
+ if (known):
+ to_delete |= (present - known)
+ for x in to_delete:
+ shutil.rmtree(os.path.join('gmkb', x))
+ sys.stdout.write('%s: %d of %d models removed\n' %(sys.argv[0], len(to_delete), len(present)))
+
+if __name__ == '__main__':
+ main()
+
diff --git a/chromium/third_party/skia/tools/skqp/run_skqp_exe b/chromium/third_party/skia/tools/skqp/run_skqp_exe
new file mode 100755
index 00000000000..7b17425dc31
--- /dev/null
+++ b/chromium/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/chromium/third_party/skia/tools/skqp/setup_resources b/chromium/third_party/skia/tools/skqp/setup_resources
new file mode 100755
index 00000000000..22f27a85dd3
--- /dev/null
+++ b/chromium/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/chromium/third_party/skia/tools/skqp/skqp.cpp b/chromium/third_party/skia/tools/skqp/skqp.cpp
index fbd4c1e0063..cba52de6be4 100644
--- a/chromium/third_party/skia/tools/skqp/skqp.cpp
+++ b/chromium/third_party/skia/tools/skqp/skqp.cpp
@@ -5,6 +5,8 @@
* found in the LICENSE file.
*/
+#include <sys/stat.h>
+
#include "gm_knowledge.h"
#include "gm_runner.h"
@@ -19,6 +21,7 @@
#pragma clang diagnostic pop
#endif
+#include "Resources.h"
#include "SkStream.h"
#include "SkString.h"
@@ -92,7 +95,7 @@ static void reg_test(const char* test, const char* testCase,
void register_skia_tests() {
- gm_runner::InitSkia();
+ gm_runner::InitSkia(gm_runner::Mode::kCompatibilityTestMode, gAssetMgr.get());
// Rendering Tests
std::vector<gm_runner::SkiaBackend> backends = gm_runner::GetSupportedBackends();
@@ -132,9 +135,11 @@ int main(int argc, char** argv) {
<< " [GTEST_ARGUMENTS] GMKB_DIRECTORY_PATH GMKB_REPORT_PATH\n\n";
return 1;
}
+ SetResourcePath((std::string(argv[1]) + "/resources").c_str());
gAssetMgr.reset(new StdAssetManager(argv[1]));
if (argc > 2) {
gReportDirectoryPath = argv[2];
+ (void)mkdir(gReportDirectoryPath.c_str(), 0777);
}
register_skia_tests();
int ret = RUN_ALL_TESTS();
diff --git a/chromium/third_party/skia/tools/skqp/upload_model b/chromium/third_party/skia/tools/skqp/upload_model
new file mode 100755
index 00000000000..cd9554c6712
--- /dev/null
+++ b/chromium/third_party/skia/tools/skqp/upload_model
@@ -0,0 +1,62 @@
+#! /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
+
+BASE_DIR='platform_tools/android/apps/skqp/src/main/assets'
+PATH_LIST='gmkb skqp'
+BUCKET=skia-skqp-assets
+
+EXTANT="$(mktemp "${TMPDIR:-/tmp}/extant.XXXXXXXXXX")"
+gsutil ls gs://$BUCKET/ | sed "s|^gs://$BUCKET/||" > "$EXTANT"
+
+upload() {
+ MD5=$(md5sum < "$1" | head -c 32)
+ if ! grep -q "$MD5" "$EXTANT"; then
+ URL="gs://${BUCKET}/$MD5"
+ gsutil cp "$1" "$URL" > /dev/null 2>&1 &
+ fi
+ echo $MD5
+}
+
+size() { gsutil du -s gs://$BUCKET | awk '{print $1}'; }
+
+cd "$(dirname "$0")/../../$BASE_DIR"
+
+rm -f files.checksum
+
+FILES="$(mktemp "${TMPDIR:-/tmp}/files.XXXXXXXXXX")"
+
+: > "$FILES"
+
+COUNT=$(find $PATH_LIST -type f | wc -l)
+INDEX=1
+SHARD_COUNT=32
+
+SIZE=$(size)
+find $PATH_LIST -type f | sort | while IFS= read -r FILENAME; do
+ printf '\r %d / %d ' "$INDEX" "$COUNT"
+ if ! [ -f "$FILENAME" ]; then
+ echo error [${FILENAME}] >&2;
+ exit 1;
+ fi
+ case "$FILENAME" in *\;*) echo bad filename: $FILENAME >&2; exit 1;; esac
+ MD5=$(upload "$FILENAME")
+ printf '%s;%s\n' "$MD5" "$FILENAME" >> "$FILES"
+
+ if [ $(($INDEX % $SHARD_COUNT)) = 0 ]; then
+ wait
+ fi
+ INDEX=$(( $INDEX + 1))
+done
+printf '\rdone \n'
+upload "$FILES" > files.checksum
+wait
+
+D=$(( $(size) - $SIZE ))
+printf 'Added %d bytes to %s, %d%%\n' $D $BUCKET $(( $D * 100 / $SIZE ))
+
+rm "$EXTANT"
diff --git a/chromium/third_party/skia/tools/test_gpuveto.py b/chromium/third_party/skia/tools/test_gpuveto.py
deleted file mode 100755
index 589b403b591..00000000000
--- a/chromium/third_party/skia/tools/test_gpuveto.py
+++ /dev/null
@@ -1,169 +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 gpuTime - tol_range < 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/chromium/third_party/skia/tools/viewer/BisectSlide.cpp b/chromium/third_party/skia/tools/viewer/BisectSlide.cpp
new file mode 100644
index 00000000000..63e69d278ce
--- /dev/null
+++ b/chromium/third_party/skia/tools/viewer/BisectSlide.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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 "BisectSlide.h"
+
+#include "SkDOM.h"
+#include "SkOSPath.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+#include "../experimental/svg/model/SkSVGDOM.h"
+
+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")) {
+ 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 {
+ 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()) {
+ SkTSwap(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/chromium/third_party/skia/tools/viewer/BisectSlide.h b/chromium/third_party/skia/tools/viewer/BisectSlide.h
new file mode 100644
index 00000000000..c5300c6396a
--- /dev/null
+++ b/chromium/third_party/skia/tools/viewer/BisectSlide.h
@@ -0,0 +1,54 @@
+/*
+ * 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 "SkCanvas.h"
+#include "SkPath.h"
+#include "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/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp b/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
index 8880916a16e..77501d8a9f9 100644
--- a/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
@@ -16,9 +16,10 @@ SkottieSlide::SkottieSlide(const SkString& name, const SkString& path)
fName = name;
}
-void SkottieSlide::load(SkScalar, SkScalar) {
- fAnimation = skottie::Animation::MakeFromFile(fPath.c_str());
- fTimeBase = 0; // force a time reset
+void SkottieSlide::load(SkScalar w, SkScalar h) {
+ fAnimation = skottie::Animation::MakeFromFile(fPath.c_str());
+ fWinSize = SkSize::Make(w, h);
+ fTimeBase = 0; // force a time reset
if (fAnimation) {
fAnimation->setShowInval(fShowAnimationInval);
@@ -37,13 +38,14 @@ void SkottieSlide::unload() {
}
SkISize SkottieSlide::getDimensions() const {
- return fAnimation? fAnimation->size().toCeil() : SkISize::Make(0, 0);
+ // We always scale to fill the window.
+ return fWinSize.toCeil();
}
void SkottieSlide::draw(SkCanvas* canvas) {
if (fAnimation) {
SkAutoCanvasRestore acr(canvas, true);
- const SkRect dstR = SkRect::Make(canvas->imageInfo().bounds());
+ const auto dstR = SkRect::MakeSize(fWinSize);
fAnimation->render(canvas, &dstR);
}
}
@@ -75,3 +77,16 @@ bool SkottieSlide::onChar(SkUnichar c) {
return INHERITED::onChar(c);
}
+
+bool SkottieSlide::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t) {
+ switch (state) {
+ case sk_app::Window::kUp_InputState:
+ fShowAnimationInval = !fShowAnimationInval;
+ fAnimation->setShowInval(fShowAnimationInval);
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
diff --git a/chromium/third_party/skia/tools/viewer/SkottieSlide.h b/chromium/third_party/skia/tools/viewer/SkottieSlide.h
index 6c278d484f1..b5770a0cf84 100644
--- a/chromium/third_party/skia/tools/viewer/SkottieSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SkottieSlide.h
@@ -11,6 +11,7 @@
#include "Slide.h"
namespace skottie { class Animation; }
+namespace sksg { class Scene; }
class SkottieSlide : public Slide {
public:
@@ -26,46 +27,14 @@ public:
bool animate(const SkAnimTimer&) override;
bool onChar(SkUnichar) override;
-
-private:
- SkString fPath;
- std::unique_ptr<skottie::Animation> fAnimation;
- SkMSec fTimeBase = 0;
- bool fShowAnimationInval = false;
-
- typedef Slide INHERITED;
-};
-
-class SkottieSlide2 : public Slide {
-public:
- SkottieSlide2(const SkString& path);
- ~SkottieSlide2() override = default;
-
- void load(SkScalar winWidth, SkScalar winHeight) override;
- void unload() override;
-
- SkISize getDimensions() const override;
-
- void draw(SkCanvas*) override;
- bool animate(const SkAnimTimer&) override;
bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t modifiers) override;
-private:
- struct Rec {
- std::unique_ptr<skottie::Animation> fAnimation;
- SkMSec fTimeBase = 0;
- SkString fName;
- bool fShowAnimationInval = false;
-
- Rec(std::unique_ptr<skottie::Animation> anim);
- Rec(Rec&& o);
- };
-
- int findCell(float x, float y) const;
- SkString fPath;
- SkTArray<Rec> fAnims;
-
- int fTrackingCell = -1;
+private:
+ SkString fPath;
+ sk_sp<skottie::Animation> fAnimation;
+ SkSize fWinSize = SkSize::MakeEmpty();
+ SkMSec fTimeBase = 0;
+ bool fShowAnimationInval = false;
typedef Slide INHERITED;
};
diff --git a/chromium/third_party/skia/tools/viewer/SkottieSlide2.cpp b/chromium/third_party/skia/tools/viewer/SkottieSlide2.cpp
deleted file mode 100644
index 0c643b724e9..00000000000
--- a/chromium/third_party/skia/tools/viewer/SkottieSlide2.cpp
+++ /dev/null
@@ -1,128 +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 "SkottieSlide.h"
-
-#include "SkAnimTimer.h"
-#include "SkCanvas.h"
-#include "Skottie.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkStream.h"
-
-const int CELL_WIDTH = 240;
-const int CELL_HEIGHT = 160;
-const int COL_COUNT = 4;
-const int SPACER_X = 12;
-const int SPACER_Y = 24;
-const int MARGIN = 8;
-
-SkottieSlide2::Rec::Rec(std::unique_ptr<skottie::Animation> anim) : fAnimation(std::move(anim))
-{}
-
-SkottieSlide2::Rec::Rec(Rec&& o)
- : fAnimation(std::move(o.fAnimation))
- , fTimeBase(o.fTimeBase)
- , fName(o.fName)
- , fShowAnimationInval(o.fShowAnimationInval)
-{}
-
-SkottieSlide2::SkottieSlide2(const SkString& path)
- : fPath(path)
-{
- fName.set("skottie-dir");
-}
-
-void SkottieSlide2::load(SkScalar, SkScalar) {
- SkString name;
- SkOSFile::Iter iter(fPath.c_str(), "json");
- while (iter.next(&name)) {
- SkString path = SkOSPath::Join(fPath.c_str(), name.c_str());
- if (auto anim = skottie::Animation::MakeFromFile(path.c_str())) {
- fAnims.push_back(Rec(std::move(anim))).fName = name;
- }
- }
-}
-
-void SkottieSlide2::unload() {
- fAnims.reset();
-}
-
-SkISize SkottieSlide2::getDimensions() const {
- const int rows = (fAnims.count() + COL_COUNT - 1) / COL_COUNT;
- return {
- MARGIN + (COL_COUNT - 1) * SPACER_X + COL_COUNT * CELL_WIDTH + MARGIN,
- MARGIN + (rows - 1) * SPACER_Y + rows * CELL_HEIGHT + MARGIN,
- };
-}
-
-void SkottieSlide2::draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setTextSize(12);
- paint.setAntiAlias(true);
- paint.setTextAlign(SkPaint::kCenter_Align);
-
- const SkRect dst = SkRect::MakeIWH(CELL_WIDTH, CELL_HEIGHT);
- int x = 0, y = 0;
-
- canvas->translate(MARGIN, MARGIN);
- for (const auto& rec : fAnims) {
- SkAutoCanvasRestore acr(canvas, true);
- canvas->translate(x * (CELL_WIDTH + SPACER_X), y * (CELL_HEIGHT + SPACER_Y));
- canvas->drawText(rec.fName.c_str(), rec.fName.size(),
- dst.centerX(), dst.bottom() + paint.getTextSize(), paint);
- rec.fAnimation->render(canvas, &dst);
- if (++x == COL_COUNT) {
- x = 0;
- y += 1;
- }
- }
-}
-
-bool SkottieSlide2::animate(const SkAnimTimer& timer) {
- for (auto& rec : fAnims) {
- if (rec.fTimeBase == 0) {
- // Reset the animation time.
- rec.fTimeBase = timer.msec();
- }
- rec.fAnimation->animationTick(timer.msec() - rec.fTimeBase);
- }
- return true;
-}
-
-bool SkottieSlide2::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
- uint32_t modifiers) {
- if (fTrackingCell < 0 && state == sk_app::Window::kDown_InputState) {
- fTrackingCell = this->findCell(x, y);
- }
- if (fTrackingCell >= 0 && state == sk_app::Window::kUp_InputState) {
- int index = this->findCell(x, y);
- if (fTrackingCell == index) {
- fAnims[index].fShowAnimationInval = !fAnims[index].fShowAnimationInval;
- fAnims[index].fAnimation->setShowInval(fAnims[index].fShowAnimationInval);
- }
- fTrackingCell = -1;
- }
- return fTrackingCell >= 0;
-}
-
-int SkottieSlide2::findCell(float x, float y) const {
- x -= MARGIN;
- y -= MARGIN;
- int index = -1;
- if (x >= 0 && y >= 0) {
- int ix = (int)x;
- int iy = (int)y;
- int col = ix / (CELL_WIDTH + SPACER_X);
- int row = iy / (CELL_HEIGHT + SPACER_Y);
- index = row * COL_COUNT + col;
- if (index >= fAnims.count()) {
- index = -1;
- }
- }
- return index;
-}
diff --git a/chromium/third_party/skia/tools/viewer/SlideDir.cpp b/chromium/third_party/skia/tools/viewer/SlideDir.cpp
new file mode 100644
index 00000000000..ba3bbbae127
--- /dev/null
+++ b/chromium/third_party/skia/tools/viewer/SlideDir.cpp
@@ -0,0 +1,418 @@
+/*
+ * 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 "SlideDir.h"
+
+#include "SkAnimTimer.h"
+#include "SkCanvas.h"
+#include "SkCubicMap.h"
+#include "SkMakeUnique.h"
+#include "SkSGColor.h"
+#include "SkSGDraw.h"
+#include "SkSGGroup.h"
+#include "SkSGPlane.h"
+#include "SkSGRect.h"
+#include "SkSGRenderNode.h"
+#include "SkSGScene.h"
+#include "SkSGText.h"
+#include "SkSGTransform.h"
+#include "SkTypeface.h"
+
+#include <cmath>
+
+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);
+ }
+
+ std::unique_ptr<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 skstd::make_unique<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 override {
+ fSlide->draw(canvas);
+ }
+
+private:
+ void tick(SkMSec t) {
+ fSlide->animate(SkAnimTimer(0, t * 1e6, SkAnimTimer::kRunning_State));
+ 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::Transform> fTransform;
+ SkRect fRect;
+};
+
+class SlideDir::FocusController final : public sksg::Animator {
+public:
+ FocusController(const SlideDir* dir, const SkRect& focusRect)
+ : fDir(dir)
+ , fRect(focusRect)
+ , fTarget(nullptr)
+ , fState(State::kIdle) {
+ fMap.setPts(kFocusCtrl1, kFocusCtrl0);
+
+ 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->fTransform);
+ fDir->fRoot->addChild(fShade);
+ fDir->fRoot->addChild(fTarget->fTransform);
+
+ 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);
+
+ SkTSwap(fM0, fM1);
+ SkTSwap(fOpacity0, fOpacity1);
+
+ fTimeBase = 0;
+ fState = State::kUnfocusing;
+ }
+
+ bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t 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->fTransform->getMatrix()->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>, true>&& 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->setFlags(SkPaint::kAntiAlias_Flag);
+ text->setSize(size);
+ text->setAlign(SkPaint::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 = 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));
+ auto slideTransform = sksg::Transform::Make(std::move(slideGrp), slideMatrix);
+
+ sceneAnimators.push_back(adapter->makeForwardingAnimator());
+
+ fRoot->addChild(slideTransform);
+ fRecs.push_back({ slide, slideTransform, 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(const SkAnimTimer& timer) {
+ if (fTimeBase == 0) {
+ // Reset the animation time.
+ fTimeBase = timer.msec();
+ }
+
+ const auto t = timer.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, sk_app::Window::InputState state,
+ uint32_t modifiers) {
+ if (state == sk_app::Window::kMove_InputState || 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 sk_app::Window::kDown_InputState:
+ fTrackingCell = cell;
+ fTrackingPos = SkPoint::Make(x, y);
+ break;
+ case sk_app::Window::kUp_InputState:
+ 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/chromium/third_party/skia/tools/viewer/SlideDir.h b/chromium/third_party/skia/tools/viewer/SlideDir.h
new file mode 100644
index 00000000000..f391a245993
--- /dev/null
+++ b/chromium/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 "Slide.h"
+
+#include "SkTArray.h"
+
+class SkString;
+
+namespace sksg {
+
+class Group;
+class Scene;
+
+}
+
+class SlideDir final : public Slide {
+public:
+ SlideDir(const SkString& name, SkTArray<sk_sp<Slide>, true>&&,
+ int columns = kDefaultColumnCount);
+
+protected:
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void unload() override;
+
+ SkISize getDimensions() const override;
+
+ void draw(SkCanvas*) override;
+ bool animate(const SkAnimTimer&) override;
+
+ bool onChar(SkUnichar) override;
+ bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t 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>, true> 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/chromium/third_party/skia/tools/viewer/Viewer.cpp b/chromium/third_party/skia/tools/viewer/Viewer.cpp
index f9d1c1b3729..8aff1cedb0d 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.cpp
+++ b/chromium/third_party/skia/tools/viewer/Viewer.cpp
@@ -7,29 +7,35 @@
#include "Viewer.h"
+#include "BisectSlide.h"
#include "GMSlide.h"
#include "ImageSlide.h"
#include "Resources.h"
#include "SampleSlide.h"
#include "SkottieSlide.h"
#include "SKPSlide.h"
+#include "SlideDir.h"
#include "GrContext.h"
#include "SkCanvas.h"
#include "SkColorSpacePriv.h"
#include "SkColorSpaceXformCanvas.h"
+#include "SkCommonFlags.h"
#include "SkCommandLineFlags.h"
#include "SkCommonFlagsGpu.h"
#include "SkEventTracingPriv.h"
+#include "SkFontMgrPriv.h"
#include "SkGraphics.h"
#include "SkImagePriv.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
+#include "SkPaintFilterCanvas.h"
#include "SkPictureRecorder.h"
#include "SkScan.h"
#include "SkStream.h"
#include "SkSurface.h"
#include "SkTaskGroup.h"
+#include "SkTestFontMgr.h"
#include "SkThreadedBMPDevice.h"
#include "imgui.h"
@@ -47,16 +53,6 @@ Application* Application::Create(int argc, char** argv, void* platformData) {
return new Viewer(argc, argv, platformData);
}
-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 ~");
-
static DEFINE_string(slide, "", "Start on this sample.");
static DEFINE_bool(list, false, "List samples?");
@@ -66,19 +62,11 @@ static DEFINE_bool(list, false, "List samples?");
# 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.");
-static DEFINE_string(jsons, "/data/local/tmp/jsons", "Directory to read (Bodymovin) jsons from.");
-#else
-static DEFINE_string(skps, "skps", "Directory to read skps from.");
-static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
-static DEFINE_string(jsons, "jsons", "Directory to read (Bodymovin) jsons from.");
-#endif
-
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
-static DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
+static DEFINE_int32(msaa, 1, "Number of subpixel samples. 0 for no HW antialiasing.");
+
+DEFINE_string(bisect, "", "Path to a .skp or .svg file to bisect.");
DECLARE_int32(threads)
@@ -214,6 +202,10 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
SetResourcePath("/data/local/tmp/resources");
#endif
+ if (!FLAGS_nativeFonts) {
+ gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
+ }
+
initializeEventTracingForTools();
static SkTaskGroup::Enabler kTaskGroupEnabler(FLAGS_threads);
@@ -315,30 +307,6 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
#endif
this->setBackend(newBackend);
});
-
- fCommands.addCommand('A', "AA", "Toggle analytic AA", [this]() {
- if (!gSkUseAnalyticAA) {
- gSkUseAnalyticAA = true;
- } else if (!gSkForceAnalyticAA) {
- gSkForceAnalyticAA = true;
- } else {
- gSkUseAnalyticAA = gSkForceAnalyticAA = false;
- }
- this->updateTitle();
- fWindow->inval();
- });
- fCommands.addCommand('D', "AA", "Toggle delta AA", [this]() {
- if (!gSkUseDeltaAA) {
- gSkUseDeltaAA = true;
- } else if (!gSkForceDeltaAA) {
- gSkForceDeltaAA = true;
- } else {
- gSkUseDeltaAA = gSkForceDeltaAA = false;
- }
- this->updateTitle();
- fWindow->inval();
- });
-
fCommands.addCommand('+', "Threaded Backend", "Increase tile count", [this]() {
fTileCnt++;
if (fThreadCnt == 0) {
@@ -377,10 +345,109 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fSaveToSKP = true;
fWindow->inval();
});
+ fCommands.addCommand('H', "Paint", "Hinting mode", [this]() {
+ if (!fPaintOverrides.fHinting) {
+ fPaintOverrides.fHinting = true;
+ fPaint.setHinting(SkPaint::kNo_Hinting);
+ } else {
+ switch (fPaint.getHinting()) {
+ case SkPaint::kNo_Hinting:
+ fPaint.setHinting(SkPaint::kSlight_Hinting);
+ break;
+ case SkPaint::kSlight_Hinting:
+ fPaint.setHinting(SkPaint::kNormal_Hinting);
+ break;
+ case SkPaint::kNormal_Hinting:
+ fPaint.setHinting(SkPaint::kFull_Hinting);
+ break;
+ case SkPaint::kFull_Hinting:
+ fPaint.setHinting(SkPaint::kNo_Hinting);
+ fPaintOverrides.fHinting = false;
+ break;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('A', "Paint", "Antialias Mode", [this]() {
+ if (!(fPaintOverrides.fFlags & SkPaint::kAntiAlias_Flag)) {
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::Alias;
+ fPaintOverrides.fFlags |= SkPaint::kAntiAlias_Flag;
+ fPaint.setAntiAlias(false);
+ fPaintOverrides.fOriginalSkUseAnalyticAA = gSkUseAnalyticAA;
+ fPaintOverrides.fOriginalSkForceAnalyticAA = gSkForceAnalyticAA;
+ fPaintOverrides.fOriginalSkUseDeltaAA = gSkUseDeltaAA;
+ fPaintOverrides.fOriginalSkForceDeltaAA = gSkForceDeltaAA;
+ gSkUseAnalyticAA = gSkForceAnalyticAA = false;
+ gSkUseDeltaAA = gSkForceDeltaAA = false;
+ } else {
+ fPaint.setAntiAlias(true);
+ switch (fPaintOverrides.fAntiAlias) {
+ case SkPaintFields::AntiAliasState::Alias:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::Normal;
+ break;
+ case SkPaintFields::AntiAliasState::Normal:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::AnalyticAAEnabled;
+ gSkUseDeltaAA = gSkForceDeltaAA = false;
+ gSkUseAnalyticAA = true;
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAEnabled:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::AnalyticAAForced;
+ gSkForceAnalyticAA = true;
+ break;
+ case SkPaintFields::AntiAliasState::AnalyticAAForced:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::DeltaAAEnabled;
+ gSkUseAnalyticAA = gSkForceAnalyticAA = false;
+ gSkUseDeltaAA = true;
+ break;
+ case SkPaintFields::AntiAliasState::DeltaAAEnabled:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::DeltaAAForced;
+ gSkForceDeltaAA = true;
+ break;
+ case SkPaintFields::AntiAliasState::DeltaAAForced:
+ fPaintOverrides.fAntiAlias = SkPaintFields::AntiAliasState::Alias;
+ fPaintOverrides.fFlags &= ~SkPaint::kAntiAlias_Flag;
+ gSkUseAnalyticAA = fPaintOverrides.fOriginalSkUseAnalyticAA;
+ gSkForceAnalyticAA = fPaintOverrides.fOriginalSkForceAnalyticAA;
+ gSkUseDeltaAA = fPaintOverrides.fOriginalSkUseDeltaAA;
+ gSkForceDeltaAA = fPaintOverrides.fOriginalSkForceDeltaAA;
+ break;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('L', "Paint", "Subpixel Antialias Mode", [this]() {
+ if (!(fPaintOverrides.fFlags & SkPaint::kLCDRenderText_Flag)) {
+ fPaintOverrides.fFlags |= SkPaint::kLCDRenderText_Flag;
+ fPaint.setLCDRenderText(false);
+ } else {
+ if (!fPaint.isLCDRenderText()) {
+ fPaint.setLCDRenderText(true);
+ } else {
+ fPaintOverrides.fFlags &= ~SkPaint::kLCDRenderText_Flag;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('S', "Paint", "Subpixel Position Mode", [this]() {
+ if (!(fPaintOverrides.fFlags & SkPaint::kSubpixelText_Flag)) {
+ fPaintOverrides.fFlags |= SkPaint::kSubpixelText_Flag;
+ fPaint.setSubpixelText(false);
+ } else {
+ if (!fPaint.isSubpixelText()) {
+ fPaint.setSubpixelText(true);
+ } else {
+ fPaintOverrides.fFlags &= ~SkPaint::kSubpixelText_Flag;
+ }
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
// set up slides
this->initSlides();
- this->setCurrentSlide(this->startupSlide());
if (FLAGS_list) {
this->listNames();
}
@@ -395,28 +462,42 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fImGuiGamutPaint.setFilterQuality(kLow_SkFilterQuality);
fWindow->attach(backend_type_for_window(fBackendType));
+ this->setCurrentSlide(this->startupSlide());
}
void Viewer::initSlides() {
fAllSlideNames = Json::Value(Json::arrayValue);
+ // Bisect slide.
+ if (!FLAGS_bisect.isEmpty()) {
+ sk_sp<BisectSlide> bisect = BisectSlide::Create(FLAGS_bisect[0]);
+ if (bisect && !SkCommandLineFlags::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();
const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
while (gms) {
std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr));
if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
sk_sp<Slide> slide(new GMSlide(gm.release()));
- fSlides.push_back(slide);
+ fSlides.push_back(std::move(slide));
}
gms = gms->next();
}
-
- // 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;
+ // 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
@@ -477,7 +558,7 @@ void Viewer::initSlides() {
// JSONs
for (const auto& json : FLAGS_jsons) {
- fSlides.push_back(sk_make_sp<SkottieSlide2>(json));
+ SkTArray<sk_sp<Slide>, true> dirSlides;
SkOSFile::Iter it(json.c_str(), ".json");
SkString jsonName;
@@ -485,8 +566,15 @@ void Viewer::initSlides() {
if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jsonName.c_str())) {
continue;
}
- fSlides.push_back(sk_make_sp<SkottieSlide>(jsonName, SkOSPath::Join(json.c_str(),
- jsonName.c_str())));
+ auto slide = sk_make_sp<SkottieSlide>(jsonName, SkOSPath::Join(json.c_str(),
+ jsonName.c_str()));
+ dirSlides.push_back(slide);
+ fSlides.push_back(std::move(slide));
+ }
+
+ if (!dirSlides.empty()) {
+ fSlides.push_back(sk_make_sp<SlideDir>(SkStringPrintf("skottie-dir[%s]", json.c_str()),
+ std::move(dirSlides)));
}
}
}
@@ -497,11 +585,31 @@ Viewer::~Viewer() {
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.
}
@@ -522,6 +630,46 @@ void Viewer::updateTitle() {
}
}
+ SkPaintTitleUpdater paintTitle(&title);
+ if (fPaintOverrides.fFlags & SkPaint::kAntiAlias_Flag) {
+ if (fPaint.isAntiAlias()) {
+ paintTitle.append("Antialias");
+ } else {
+ paintTitle.append("Alias");
+ }
+ }
+ if (fPaintOverrides.fFlags & SkPaint::kLCDRenderText_Flag) {
+ if (fPaint.isLCDRenderText()) {
+ paintTitle.append("LCD");
+ } else {
+ paintTitle.append("lcd");
+ }
+ }
+ if (fPaintOverrides.fFlags & SkPaint::kSubpixelText_Flag) {
+ if (fPaint.isSubpixelText()) {
+ paintTitle.append("Subpixel Glyphs");
+ } else {
+ paintTitle.append("Pixel Glyphs");
+ }
+ }
+ if (fPaintOverrides.fHinting) {
+ switch (fPaint.getHinting()) {
+ case SkPaint::kNo_Hinting:
+ paintTitle.append("No Hinting");
+ break;
+ case SkPaint::kSlight_Hinting:
+ paintTitle.append("Slight Hinting");
+ break;
+ case SkPaint::kNormal_Hinting:
+ paintTitle.append("Normal Hinting");
+ break;
+ case SkPaint::kFull_Hinting:
+ paintTitle.append("Full Hinting");
+ break;
+ }
+ }
+ paintTitle.done();
+
if (fTileCnt > 0) {
title.appendf(" T%d", fTileCnt);
if (fThreadCnt > 0) {
@@ -561,7 +709,8 @@ void Viewer::updateTitle() {
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("]");
@@ -616,30 +765,32 @@ void Viewer::setCurrentSlide(int slide) {
}
void Viewer::setupCurrentSlide() {
- // 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);
+ 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, fDefaultMatrix);
- this->updateTitle();
- this->updateUIState();
+ this->updateTitle();
+ this->updateUIState();
- fStatsLayer.resetMeasurements();
+ fStatsLayer.resetMeasurements();
- fWindow->inval();
+ fWindow->inval();
+ }
}
#define MAX_ZOOM_LEVEL 8
@@ -711,6 +862,30 @@ void Viewer::setColorMode(ColorMode colorMode) {
fWindow->inval();
}
+class OveridePaintFilterCanvas : public SkPaintFilterCanvas {
+public:
+ OveridePaintFilterCanvas(SkCanvas* canvas, SkPaint* paint, Viewer::SkPaintFields* fields)
+ : SkPaintFilterCanvas(canvas), fPaint(paint), fPaintOverrides(fields)
+ { }
+ bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
+ if (fPaintOverrides->fHinting) {
+ paint->writable()->setHinting(fPaint->getHinting());
+ }
+ if (fPaintOverrides->fFlags & SkPaint::kAntiAlias_Flag) {
+ paint->writable()->setAntiAlias(fPaint->isAntiAlias());
+ }
+ if (fPaintOverrides->fFlags & SkPaint::kLCDRenderText_Flag) {
+ paint->writable()->setLCDRenderText(fPaint->isLCDRenderText());
+ }
+ if (fPaintOverrides->fFlags & SkPaint::kSubpixelText_Flag) {
+ paint->writable()->setSubpixelText(fPaint->isSubpixelText());
+ }
+ return true;
+ }
+ SkPaint* fPaint;
+ Viewer::SkPaintFields* fPaintOverrides;
+};
+
void Viewer::drawSlide(SkCanvas* canvas) {
SkAutoCanvasRestore autorestore(canvas, false);
@@ -795,7 +970,8 @@ void Viewer::drawSlide(SkCanvas* canvas) {
slideCanvas->concat(computeMatrix());
// Time the painting logic of the slide
fStatsLayer.beginTiming(fPaintTimer);
- fSlides[fCurrentSlide]->draw(slideCanvas);
+ OveridePaintFilterCanvas filterCanvas(slideCanvas, &fPaint, &fPaintOverrides);
+ fSlides[fCurrentSlide]->draw(&filterCanvas);
fStatsLayer.endTiming(fPaintTimer);
slideCanvas->restoreToCount(count);
@@ -819,12 +995,8 @@ void Viewer::drawSlide(SkCanvas* canvas) {
}
void Viewer::onBackendCreated() {
- this->updateTitle();
- this->updateUIState();
this->setupCurrentSlide();
- fStatsLayer.resetMeasurements();
fWindow->show();
- fWindow->inval();
}
void Viewer::onPaint(SkCanvas* canvas) {
@@ -838,10 +1010,26 @@ void Viewer::onPaint(SkCanvas* canvas) {
this->updateUIState();
}
+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, Window::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, 0)) {
+ fWindow->inval();
+ return true;
+ }
+
void* castedOwner = reinterpret_cast<void*>(owner);
switch (state) {
case Window::kUp_InputState: {
@@ -867,7 +1055,8 @@ bool Viewer::onMouse(int x, int y, Window::InputState state, uint32_t modifiers)
return false;
}
- if (fSlides[fCurrentSlide]->onMouse(x, y, state, modifiers)) {
+ const auto slidePt = this->mapEvent(x, y);
+ if (fSlides[fCurrentSlide]->onMouse(slidePt.x(), slidePt.y(), state, modifiers)) {
fWindow->inval();
return true;
}
@@ -996,7 +1185,7 @@ void Viewer::drawImGui() {
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);
@@ -1020,7 +1209,7 @@ void Viewer::drawImGui() {
if (!ctx) {
ImGui::RadioButton("Software", true);
- } else if (fWindow->sampleCount()) {
+ } else if (fWindow->sampleCount() > 1) {
prButton(GpuPathRenderers::kDefault);
prButton(GpuPathRenderers::kAll);
if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
@@ -1200,7 +1389,7 @@ void Viewer::updateUIState() {
if (!fWindow) {
return;
}
- if (fWindow->sampleCount() < 0) {
+ if (fWindow->sampleCount() < 1) {
return; // Surface hasn't been created yet.
}
@@ -1246,7 +1435,7 @@ void Viewer::updateUIState() {
const GrContext* ctx = fWindow->getGrContext();
if (!ctx) {
prState[kOptions].append("Software");
- } else if (fWindow->sampleCount()) {
+ } else if (fWindow->sampleCount() > 1) {
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kDefault]);
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
diff --git a/chromium/third_party/skia/tools/viewer/Viewer.h b/chromium/third_party/skia/tools/viewer/Viewer.h
index 50679524e05..0443399f9ab 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.h
+++ b/chromium/third_party/skia/tools/viewer/Viewer.h
@@ -37,6 +37,45 @@ public:
bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) override;
bool onChar(SkUnichar c, uint32_t modifiers) override;
+ struct SkPaintFields {
+ bool fTypeface = false;
+ bool fPathEffect = false;
+ bool fShader = false;
+ bool fMaskFilter = false;
+ bool fColorFilter = false;
+ bool fDrawLooper = false;
+ bool fImageFilter = false;
+
+ bool fTextSize = false;
+ bool fTextScaleX = false;
+ bool fTextSkewX = false;
+ bool fColor = false;
+ bool fWidth = false;
+ bool fMiterLimit = false;
+ bool fBlendMode = false;
+
+ uint32_t fFlags = 0;
+ enum class AntiAliasState {
+ Alias,
+ Normal,
+ AnalyticAAEnabled,
+ AnalyticAAForced,
+ DeltaAAEnabled,
+ DeltaAAForced,
+ } fAntiAlias = AntiAliasState::Alias;
+ bool fOriginalSkUseAnalyticAA = false;
+ bool fOriginalSkForceAnalyticAA = false;
+ bool fOriginalSkUseDeltaAA = false;
+ bool fOriginalSkForceDeltaAA = false;
+
+ bool fTextAlign = false;
+ bool fCapType = false;
+ bool fJoinType = false;
+ bool fStyle = false;
+ bool fTextEncoding = false;
+ bool fHinting = false;
+ bool fFilterQuality = false;
+ };
private:
enum class ColorMode {
kLegacy, // N32, no color management
@@ -61,6 +100,7 @@ private:
void changeZoomLevel(float delta);
SkMatrix computeMatrix();
+ SkPoint mapEvent(float x, float y);
void resetExecutor() {
fExecutor = SkExecutor::MakeFIFOThreadPool(fThreadCnt == 0 ? fTileCnt : fThreadCnt);
@@ -121,6 +161,9 @@ private:
int fTileCnt;
int fThreadCnt;
std::unique_ptr<SkExecutor> fExecutor;
+
+ SkPaint fPaint;
+ SkPaintFields fPaintOverrides;
};
diff --git a/chromium/third_party/skia/tools/win_dbghelp.h b/chromium/third_party/skia/tools/win_dbghelp.h
index d334318ad4b..226249f4e64 100644
--- a/chromium/third_party/skia/tools/win_dbghelp.h
+++ b/chromium/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 @@ void setUpDebuggingFromArgs(const char* vargs0);
int GenerateDumpAndPrintCallstack(EXCEPTION_POINTERS* pExceptionPointers);
-#endif // SK_BUILD_FOR_WIN32
+#endif // SK_BUILD_FOR_WIN
#endif // win_dbghelp_DEFINED
diff --git a/chromium/third_party/skia/tools/xsan.blacklist b/chromium/third_party/skia/tools/xsan.blacklist
deleted file mode 100644
index a917e2d3d46..00000000000
--- a/chromium/third_party/skia/tools/xsan.blacklist
+++ /dev/null
@@ -1,2 +0,0 @@
-# Suppress third_party/externals. We mostly care about our own code.
-src:*third_party/externals*