From dae9b7cebf46491555c16ca569b20ba59ed6fa14 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 8 May 2017 12:12:17 -0700 Subject: [PATCH] Add BUILD.gn and make the library build Change-Id: Ie2c3d6f97987e8a9938af8f02b093bb74dd22a18 --- BUILD.gn | 9 + LICENSE | 202 +++++++++++ app/HyphTool.cpp | 1 - libs/minikin/BUILD.gn | 59 ++++ libs/minikin/FontCollection.cpp | 4 +- libs/minikin/FontFamily.cpp | 8 +- libs/minikin/GraphemeBreak.cpp | 32 +- libs/minikin/HbFontCache.cpp | 11 +- libs/minikin/Hyphenator.cpp | 1 - libs/minikin/Layout.cpp | 22 +- libs/minikin/LayoutUtils.h | 1 + libs/minikin/Measurement.cpp | 2 +- libs/minikin/MinikinFont.cpp | 2 +- libs/minikin/MinikinInternal.cpp | 2 +- libs/minikin/MinikinInternal.h | 6 +- libs/minikin/WordBreaker.cpp | 2 +- shims/BUILD.gn | 33 ++ shims/log/log.cc | 25 ++ shims/log/log.h | 57 ++++ shims/utils/JenkinsHash.h | 51 +++ shims/utils/LruCache.h | 298 ++++++++++++++++ shims/utils/TypeHelpers.h | 336 +++++++++++++++++++ tests/perftests/FontCollection.cpp | 2 +- tests/unittest/FontCollectionItemizeTest.cpp | 4 +- tests/unittest/FontFamilyTest.cpp | 12 +- tests/unittest/FontLanguageListCacheTest.cpp | 4 +- tests/unittest/HbFontCacheTest.cpp | 10 +- tests/unittest/WordBreakerTests.cpp | 2 +- 28 files changed, 1134 insertions(+), 64 deletions(-) create mode 100644 BUILD.gn create mode 100644 LICENSE create mode 100644 libs/minikin/BUILD.gn create mode 100644 shims/BUILD.gn create mode 100644 shims/log/log.cc create mode 100644 shims/log/log.h create mode 100644 shims/utils/JenkinsHash.h create mode 100644 shims/utils/LruCache.h create mode 100644 shims/utils/TypeHelpers.h diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000000..8a8166708b --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,9 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +group("txt") { + deps = [ + "libs/minikin", + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/app/HyphTool.cpp b/app/HyphTool.cpp index 403d37439a..3c1d2f96d6 100644 --- a/app/HyphTool.cpp +++ b/app/HyphTool.cpp @@ -3,7 +3,6 @@ #include #include "unicode/locid.h" -#include "utils/Log.h" #include #include diff --git a/libs/minikin/BUILD.gn b/libs/minikin/BUILD.gn new file mode 100644 index 0000000000..d4104e38a5 --- /dev/null +++ b/libs/minikin/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +config("minikin_config") { + include_dirs = [ "../../include" ] +} + +static_library("minikin") { + sources = [ + "CmapCoverage.cpp", + "Emoji.cpp", + "FontCollection.cpp", + "FontFamily.cpp", + "FontLanguage.cpp", + "FontLanguage.h", + "FontLanguageListCache.cpp", + "FontLanguageListCache.h", + "FontUtils.cpp", + "FontUtils.h", + "GraphemeBreak.cpp", + "HbFontCache.cpp", + "HbFontCache.h", + "Hyphenator.cpp", + "Layout.cpp", + "LayoutUtils.cpp", + "LayoutUtils.h", + "LineBreaker.cpp", + "Measurement.cpp", + "MinikinFont.cpp", + "MinikinInternal.cpp", + "MinikinInternal.h", + "SparseBitSet.cpp", + "WordBreaker.cpp", + ] + + public_configs = [ ":minikin_config" ] + + public_deps = [ + "//third_party/freetype2", + "//third_party/harfbuzz", + "//third_party/icu:icuuc", + ] + + deps = [ + "//third_party/zlib", + "//lib/txt/shims", + ] +} diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp index 02ed9dc623..ddb85720de 100644 --- a/libs/minikin/FontCollection.cpp +++ b/libs/minikin/FontCollection.cpp @@ -56,7 +56,7 @@ FontCollection::FontCollection(const vector>& typefa } void FontCollection::init(const vector>& typefaces) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); mId = sNextId++; vector lastChar; size_t nTypefaces = typefaces.size(); @@ -333,7 +333,7 @@ bool FontCollection::hasVariationSelector(uint32_t baseCodepoint, return false; } - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); // Currently mRanges can not be used here since it isn't aware of the variation sequence. for (size_t i = 0; i < mVSFamilyVec.size(); i++) { diff --git a/libs/minikin/FontFamily.cpp b/libs/minikin/FontFamily.cpp index 39d374b99d..1ea47fafcb 100644 --- a/libs/minikin/FontFamily.cpp +++ b/libs/minikin/FontFamily.cpp @@ -56,7 +56,7 @@ android::hash_t FontStyle::hash() const { // static uint32_t FontStyle::registerLanguageList(const std::string& languages) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); return FontLanguageListCache::getId(languages); } @@ -111,7 +111,7 @@ FontFamily::FontFamily(uint32_t langId, int variant, std::vector&& fonts) bool FontFamily::analyzeStyle(const std::shared_ptr& typeface, int* weight, bool* italic) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2'); HbBlob os2Table(getFontTable(typeface.get(), os2Tag)); if (os2Table.get() == nullptr) return false; @@ -166,7 +166,7 @@ bool FontFamily::isColorEmojiFamily() const { } void FontFamily::computeCoverage() { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); const FontStyle defaultStyle; const MinikinFont* typeface = getClosestMatch(defaultStyle).font; const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p'); @@ -220,7 +220,7 @@ std::shared_ptr FontFamily::createFamilyWithVariation( std::vector fonts; for (const Font& font : mFonts) { bool supportedVariations = false; - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); std::unordered_set supportedAxes = font.getSupportedAxesLocked(); if (!supportedAxes.empty()) { for (const FontVariation& variation : variations) { diff --git a/libs/minikin/GraphemeBreak.cpp b/libs/minikin/GraphemeBreak.cpp index 87de4213f9..482621ce69 100644 --- a/libs/minikin/GraphemeBreak.cpp +++ b/libs/minikin/GraphemeBreak.cpp @@ -104,7 +104,8 @@ bool GraphemeBreak::isGraphemeBreak(const float* advances, const uint16_t* buf, return false; } // Rule GB9, x (Extend | ZWJ); Rule GB9a, x SpacingMark; Rule GB9b, Prepend x - if (p2 == U_GCB_EXTEND || p2 == U_GCB_ZWJ || p2 == U_GCB_SPACING_MARK || p1 == U_GCB_PREPEND) { + // TODO(abarth): Add U_GCB_ZWJ once we update ICU. + if (p2 == U_GCB_EXTEND || /* p2 == U_GCB_ZWJ || */ p2 == U_GCB_SPACING_MARK || p1 == U_GCB_PREPEND) { return false; } @@ -142,25 +143,28 @@ bool GraphemeBreak::isGraphemeBreak(const float* advances, const uint16_t* buf, return false; } } + + // TODO(abarth): Enablet his code once we update ICU. // Tailored version of Rule GB11, ZWJ × (Glue_After_Zwj | EBG) // We try to make emoji sequences with ZWJ a single grapheme cluster, but only if they actually // merge to one cluster. So we are more relaxed than the UAX #29 rules in accepting any emoji // character after the ZWJ, but are tighter in that we only treat it as one cluster if a // ligature is actually formed and we also require the character before the ZWJ to also be an // emoji. - if (p1 == U_GCB_ZWJ && isEmoji(c2) && offset_back > start) { - // look at character before ZWJ to see that both can participate in an emoji zwj sequence - uint32_t c0 = 0; - size_t offset_backback = offset_back; - U16_PREV(buf, start, offset_backback, c0); - if (c0 == 0xFE0F && offset_backback > start) { - // skip over emoji variation selector - U16_PREV(buf, start, offset_backback, c0); - } - if (isEmoji(c0)) { - return false; - } - } + // if (p1 == U_GCB_ZWJ && isEmoji(c2) && offset_back > start) { + // // look at character before ZWJ to see that both can participate in an emoji zwj sequence + // uint32_t c0 = 0; + // size_t offset_backback = offset_back; + // U16_PREV(buf, start, offset_backback, c0); + // if (c0 == 0xFE0F && offset_backback > start) { + // // skip over emoji variation selector + // U16_PREV(buf, start, offset_backback, c0); + // } + // if (isEmoji(c0)) { + // return false; + // } + // } + // Tailored version of Rule GB12 and Rule GB13 that look at even-odd cases. // sot (RI RI)* RI x RI // [^RI] (RI RI)* RI x RI diff --git a/libs/minikin/HbFontCache.cpp b/libs/minikin/HbFontCache.cpp index af3d783bc8..a7647c016c 100644 --- a/libs/minikin/HbFontCache.cpp +++ b/libs/minikin/HbFontCache.cpp @@ -117,11 +117,12 @@ hb_font_t* getHbFontLocked(const MinikinFont* minikinFont) { hb_font_set_scale(parent_font, upem, upem); font = hb_font_create_sub_font(parent_font); - std::vector variations; - for (const FontVariation& variation : minikinFont->GetAxes()) { - variations.push_back({variation.axisTag, variation.value}); - } - hb_font_set_variations(font, variations.data(), variations.size()); + // TODO(abarth): Enable this code once we update harfbuzz. + // std::vector variations; + // for (const FontVariation& variation : minikinFont->GetAxes()) { + // variations.push_back({variation.axisTag, variation.value}); + // } + // hb_font_set_variations(font, variations.data(), variations.size()); hb_font_destroy(parent_font); hb_face_destroy(face); fontCache->put(fontId, font); diff --git a/libs/minikin/Hyphenator.cpp b/libs/minikin/Hyphenator.cpp index 0605b27831..0d1c0d7715 100644 --- a/libs/minikin/Hyphenator.cpp +++ b/libs/minikin/Hyphenator.cpp @@ -25,7 +25,6 @@ #include #define LOG_TAG "Minikin" -#include "utils/Log.h" #include "minikin/Hyphenator.h" diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp index 568e03876b..e6c5bc912d 100644 --- a/libs/minikin/Layout.cpp +++ b/libs/minikin/Layout.cpp @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include @@ -164,7 +162,7 @@ static unsigned int disabledDecomposeCompatibility(hb_unicode_funcs_t*, hb_codep return 0; } -class LayoutEngine : public ::android::Singleton { +class LayoutEngine { public: LayoutEngine() { unicodeFunctions = hb_unicode_funcs_create(hb_icu_get_unicode_funcs()); @@ -178,6 +176,11 @@ public: hb_buffer_t* hbBuffer; hb_unicode_funcs_t* unicodeFunctions; LayoutCache layoutCache; + + static LayoutEngine& getInstance() { + static LayoutEngine* instance = new LayoutEngine(); + return *instance; + } }; bool LayoutCacheKey::operator==(const LayoutCacheKey& other) const { @@ -556,7 +559,7 @@ BidiText::BidiText(const uint16_t* buf, size_t start, size_t count, size_t bufSi void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize, int bidiFlags, const FontStyle &style, const MinikinPaint &paint, const std::shared_ptr& collection) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); LayoutContext ctx; ctx.style = style; @@ -575,7 +578,7 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, int bidiFlags, const FontStyle &style, const MinikinPaint &paint, const std::shared_ptr& collection, float* advances) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); LayoutContext ctx; ctx.style = style; @@ -1102,17 +1105,10 @@ void Layout::getBounds(MinikinRect* bounds) const { } void Layout::purgeCaches() { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); LayoutCache& layoutCache = LayoutEngine::getInstance().layoutCache; layoutCache.clear(); purgeHbFontCacheLocked(); } } // namespace minikin - -// Unable to define the static data member outside of android. -// TODO: introduce our own Singleton to drop android namespace. -namespace android { -ANDROID_SINGLETON_STATIC_INSTANCE(minikin::LayoutEngine); -} // namespace android - diff --git a/libs/minikin/LayoutUtils.h b/libs/minikin/LayoutUtils.h index b89004cf19..f13f634eaa 100644 --- a/libs/minikin/LayoutUtils.h +++ b/libs/minikin/LayoutUtils.h @@ -17,6 +17,7 @@ #ifndef MINIKIN_LAYOUT_UTILS_H #define MINIKIN_LAYOUT_UTILS_H +#include #include namespace minikin { diff --git a/libs/minikin/Measurement.cpp b/libs/minikin/Measurement.cpp index f0d15f24e8..89797134c0 100644 --- a/libs/minikin/Measurement.cpp +++ b/libs/minikin/Measurement.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/libs/minikin/MinikinFont.cpp b/libs/minikin/MinikinFont.cpp index 6bf6a4ae3b..d2f9aca171 100644 --- a/libs/minikin/MinikinFont.cpp +++ b/libs/minikin/MinikinFont.cpp @@ -21,7 +21,7 @@ namespace minikin { MinikinFont::~MinikinFont() { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); purgeHbFontLocked(this); } diff --git a/libs/minikin/MinikinInternal.cpp b/libs/minikin/MinikinInternal.cpp index 88acc5061b..9cd7bddab5 100644 --- a/libs/minikin/MinikinInternal.cpp +++ b/libs/minikin/MinikinInternal.cpp @@ -24,7 +24,7 @@ namespace minikin { -android::Mutex gMinikinLock; +std::mutex gMinikinLock; void assertMinikinLocked() { #ifdef ENABLE_RACE_DETECTION diff --git a/libs/minikin/MinikinInternal.h b/libs/minikin/MinikinInternal.h index 1ed0816188..54395221e7 100644 --- a/libs/minikin/MinikinInternal.h +++ b/libs/minikin/MinikinInternal.h @@ -19,9 +19,9 @@ #ifndef MINIKIN_INTERNAL_H #define MINIKIN_INTERNAL_H -#include +#include -#include +#include #include @@ -31,7 +31,7 @@ namespace minikin { // Presently, that's implemented by through a global lock, and having // all external interfaces take that lock. -extern android::Mutex gMinikinLock; +extern std::mutex gMinikinLock; // Aborts if gMinikinLock is not acquired. Do nothing on the release build. void assertMinikinLocked(); diff --git a/libs/minikin/WordBreaker.cpp b/libs/minikin/WordBreaker.cpp index 16edca7d6e..8d0d0fb4b4 100644 --- a/libs/minikin/WordBreaker.cpp +++ b/libs/minikin/WordBreaker.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "Minikin" -#include +#include #include #include diff --git a/shims/BUILD.gn b/shims/BUILD.gn new file mode 100644 index 0000000000..a09a56ab33 --- /dev/null +++ b/shims/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +config("shims_config") { + include_dirs = [ "." ] +} + +source_set("shims") { + sources = [ + "log/log.h", + "log/log.cc", + "utils/JenkinsHash.h", + "utils/LruCache.h", + "utils/TypeHelpers.h", + ] + + public_configs = [ ":shims_config" ] + + public_deps = [ + "//lib/ftl", + ] +} diff --git a/shims/log/log.cc b/shims/log/log.cc new file mode 100644 index 0000000000..ab61fead31 --- /dev/null +++ b/shims/log/log.cc @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +int __android_log_error_write(int tag, + const char* subTag, + int32_t uid, + const char* data, + uint32_t dataLen) { + return 0; +} diff --git a/shims/log/log.h b/shims/log/log.h new file mode 100644 index 0000000000..c3303555ec --- /dev/null +++ b/shims/log/log.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "lib/ftl/logging.h" + +#ifndef LOG_ALWAYS_FATAL_IF +#define LOG_ALWAYS_FATAL_IF(cond, ...) \ + ((cond) ? (FTL_LOG(FATAL) << #cond) : (void)0) +#endif + +#ifndef LOG_ALWAYS_FATAL +#define LOG_ALWAYS_FATAL(...) FTL_LOG(FATAL) +#endif + +#ifndef LOG_ASSERT +#define LOG_ASSERT(cond, ...) FTL_CHECK(cond) +#define ALOG_ASSERT LOG_ASSERT +#endif + +#ifndef ALOGD +#define ALOGD(message, ...) FTL_DLOG(INFO) << (message) +#endif + +#ifndef ALOGW +#define ALOGW(message, ...) FTL_LOG(WARNING) << (message) +#endif + +#ifndef ALOGE +#define ALOGE(message, ...) FTL_LOG(ERROR) << (message) +#endif + +#define android_errorWriteLog(tag, subTag) \ + __android_log_error_write(tag, subTag, -1, NULL, 0) +#define android_errorWriteWithInfoLog(tag, subTag, uid, data, dataLen) \ + __android_log_error_write(tag, subTag, uid, data, dataLen) +int __android_log_error_write(int tag, + const char* subTag, + int32_t uid, + const char* data, + uint32_t dataLen); diff --git a/shims/utils/JenkinsHash.h b/shims/utils/JenkinsHash.h new file mode 100644 index 0000000000..027c10c7e0 --- /dev/null +++ b/shims/utils/JenkinsHash.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Implementation of Jenkins one-at-a-time hash function. These choices are + * optimized for code size and portability, rather than raw speed. But speed + * should still be quite good. + **/ + +#ifndef ANDROID_JENKINS_HASH_H +#define ANDROID_JENKINS_HASH_H + +#include + +namespace android { + +/* The Jenkins hash of a sequence of 32 bit words A, B, C is: + * Whiten(Mix(Mix(Mix(0, A), B), C)) */ + +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +inline uint32_t JenkinsHashMix(uint32_t hash, uint32_t data) { + hash += data; + hash += (hash << 10); + hash ^= (hash >> 6); + return hash; +} + +hash_t JenkinsHashWhiten(uint32_t hash); + +/* Helpful utility functions for hashing data in 32 bit chunks */ +uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size); + +uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size); + +} + +#endif // ANDROID_JENKINS_HASH_H diff --git a/shims/utils/LruCache.h b/shims/utils/LruCache.h new file mode 100644 index 0000000000..89dccd6138 --- /dev/null +++ b/shims/utils/LruCache.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UTILS_LRU_CACHE_H +#define ANDROID_UTILS_LRU_CACHE_H + +#include +#include + +#include "utils/TypeHelpers.h" // hash_t + +namespace android { + +/** + * GenerationCache callback used when an item is removed + */ +template +class OnEntryRemoved { +public: + virtual ~OnEntryRemoved() { }; + virtual void operator()(EntryKey& key, EntryValue& value) = 0; +}; // class OnEntryRemoved + +template +class LruCache { +public: + explicit LruCache(uint32_t maxCapacity); + virtual ~LruCache(); + + enum Capacity { + kUnlimitedCapacity, + }; + + void setOnEntryRemovedListener(OnEntryRemoved* listener); + size_t size() const; + const TValue& get(const TKey& key); + bool put(const TKey& key, const TValue& value); + bool remove(const TKey& key); + bool removeOldest(); + void clear(); + const TValue& peekOldestValue(); + +private: + LruCache(const LruCache& that); // disallow copy constructor + + // Super class so that we can have entries having only a key reference, for searches. + class KeyedEntry { + public: + virtual const TKey& getKey() const = 0; + // Make sure the right destructor is executed so that keys and values are deleted. + virtual ~KeyedEntry() {} + }; + + class Entry final : public KeyedEntry { + public: + TKey key; + TValue value; + Entry* parent; + Entry* child; + + Entry(TKey _key, TValue _value) : key(_key), value(_value), parent(NULL), child(NULL) { + } + const TKey& getKey() const final { return key; } + }; + + class EntryForSearch : public KeyedEntry { + public: + const TKey& key; + EntryForSearch(const TKey& key_) : key(key_) { + } + const TKey& getKey() const final { return key; } + }; + + struct HashForEntry : public std::unary_function { + size_t operator() (const KeyedEntry* entry) const { + return hash_type(entry->getKey()); + }; + }; + + struct EqualityForHashedEntries : public std::unary_function { + bool operator() (const KeyedEntry* lhs, const KeyedEntry* rhs) const { + return lhs->getKey() == rhs->getKey(); + }; + }; + + // All entries in the set will be Entry*. Using the weaker KeyedEntry as to allow entries + // that have only a key reference, for searching. + typedef std::unordered_set LruCacheSet; + + void attachToCache(Entry& entry); + void detachFromCache(Entry& entry); + + typename LruCacheSet::iterator findByKey(const TKey& key) { + EntryForSearch entryForSearch(key); + typename LruCacheSet::iterator result = mSet->find(&entryForSearch); + return result; + } + + std::unique_ptr mSet; + OnEntryRemoved* mListener; + Entry* mOldest; + Entry* mYoungest; + uint32_t mMaxCapacity; + TValue mNullValue; + +public: + // To be used like: + // while (it.next()) { + // it.value(); it.key(); + // } + class Iterator { + public: + Iterator(const LruCache& cache): + mCache(cache), mIterator(mCache.mSet->begin()), mBeginReturned(false) { + } + + bool next() { + if (mIterator == mCache.mSet->end()) { + return false; + } + if (!mBeginReturned) { + // mIterator has been initialized to the beginning and + // hasn't been returned. Do not advance: + mBeginReturned = true; + } else { + std::advance(mIterator, 1); + } + bool ret = (mIterator != mCache.mSet->end()); + return ret; + } + + const TValue& value() const { + // All the elements in the set are of type Entry. See comment in the definition + // of LruCacheSet above. + return reinterpret_cast(*mIterator)->value; + } + + const TKey& key() const { + return (*mIterator)->getKey(); + } + private: + const LruCache& mCache; + typename LruCacheSet::iterator mIterator; + bool mBeginReturned; + }; +}; + +// Implementation is here, because it's fully templated +template +LruCache::LruCache(uint32_t maxCapacity) + : mSet(new LruCacheSet()) + , mListener(NULL) + , mOldest(NULL) + , mYoungest(NULL) + , mMaxCapacity(maxCapacity) + , mNullValue(0) { + mSet->max_load_factor(1.0); +}; + +template +LruCache::~LruCache() { + // Need to delete created entries. + clear(); +}; + +template +void LruCache::setOnEntryRemovedListener(OnEntryRemoved* listener) { + mListener = listener; +} + +template +size_t LruCache::size() const { + return mSet->size(); +} + +template +const TValue& LruCache::get(const TKey& key) { + typename LruCacheSet::const_iterator find_result = findByKey(key); + if (find_result == mSet->end()) { + return mNullValue; + } + // All the elements in the set are of type Entry. See comment in the definition + // of LruCacheSet above. + Entry *entry = reinterpret_cast(*find_result); + detachFromCache(*entry); + attachToCache(*entry); + return entry->value; +} + +template +bool LruCache::put(const TKey& key, const TValue& value) { + if (mMaxCapacity != kUnlimitedCapacity && size() >= mMaxCapacity) { + removeOldest(); + } + + if (findByKey(key) != mSet->end()) { + return false; + } + + Entry* newEntry = new Entry(key, value); + mSet->insert(newEntry); + attachToCache(*newEntry); + return true; +} + +template +bool LruCache::remove(const TKey& key) { + typename LruCacheSet::const_iterator find_result = findByKey(key); + if (find_result == mSet->end()) { + return false; + } + // All the elements in the set are of type Entry. See comment in the definition + // of LruCacheSet above. + Entry* entry = reinterpret_cast(*find_result); + mSet->erase(entry); + if (mListener) { + (*mListener)(entry->key, entry->value); + } + detachFromCache(*entry); + delete entry; + return true; +} + +template +bool LruCache::removeOldest() { + if (mOldest != NULL) { + return remove(mOldest->key); + // TODO: should probably abort if false + } + return false; +} + +template +const TValue& LruCache::peekOldestValue() { + if (mOldest) { + return mOldest->value; + } + return mNullValue; +} + +template +void LruCache::clear() { + if (mListener) { + for (Entry* p = mOldest; p != NULL; p = p->child) { + (*mListener)(p->key, p->value); + } + } + mYoungest = NULL; + mOldest = NULL; + for (auto entry : *mSet.get()) { + delete entry; + } + mSet->clear(); +} + +template +void LruCache::attachToCache(Entry& entry) { + if (mYoungest == NULL) { + mYoungest = mOldest = &entry; + } else { + entry.parent = mYoungest; + mYoungest->child = &entry; + mYoungest = &entry; + } +} + +template +void LruCache::detachFromCache(Entry& entry) { + if (entry.parent != NULL) { + entry.parent->child = entry.child; + } else { + mOldest = entry.child; + } + if (entry.child != NULL) { + entry.child->parent = entry.parent; + } else { + mYoungest = entry.parent; + } + + entry.parent = NULL; + entry.child = NULL; +} + +} +#endif // ANDROID_UTILS_LRU_CACHE_H diff --git a/shims/utils/TypeHelpers.h b/shims/utils/TypeHelpers.h new file mode 100644 index 0000000000..28fbca508a --- /dev/null +++ b/shims/utils/TypeHelpers.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_TYPE_HELPERS_H +#define ANDROID_TYPE_HELPERS_H + +#include +#include + +#include +#include +#include + +// --------------------------------------------------------------------------- + +namespace android { + +/* + * Types traits + */ + +template struct trait_trivial_ctor { enum { value = false }; }; +template struct trait_trivial_dtor { enum { value = false }; }; +template struct trait_trivial_copy { enum { value = false }; }; +template struct trait_trivial_move { enum { value = false }; }; +template struct trait_pointer { enum { value = false }; }; +template struct trait_pointer { enum { value = true }; }; + +template +struct traits { + enum { + // whether this type is a pointer + is_pointer = trait_pointer::value, + // whether this type's constructor is a no-op + has_trivial_ctor = is_pointer || trait_trivial_ctor::value, + // whether this type's destructor is a no-op + has_trivial_dtor = is_pointer || trait_trivial_dtor::value, + // whether this type type can be copy-constructed with memcpy + has_trivial_copy = is_pointer || trait_trivial_copy::value, + // whether this type can be moved with memmove + has_trivial_move = is_pointer || trait_trivial_move::value + }; +}; + +template +struct aggregate_traits { + enum { + is_pointer = false, + has_trivial_ctor = + traits::has_trivial_ctor && traits::has_trivial_ctor, + has_trivial_dtor = + traits::has_trivial_dtor && traits::has_trivial_dtor, + has_trivial_copy = + traits::has_trivial_copy && traits::has_trivial_copy, + has_trivial_move = + traits::has_trivial_move && traits::has_trivial_move + }; +}; + +#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ + template<> struct trait_trivial_ctor< T > { enum { value = true }; }; + +#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ + template<> struct trait_trivial_dtor< T > { enum { value = true }; }; + +#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \ + template<> struct trait_trivial_copy< T > { enum { value = true }; }; + +#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \ + template<> struct trait_trivial_move< T > { enum { value = true }; }; + +#define ANDROID_BASIC_TYPES_TRAITS( T ) \ + ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ + ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ + ANDROID_TRIVIAL_COPY_TRAIT( T ) \ + ANDROID_TRIVIAL_MOVE_TRAIT( T ) + +// --------------------------------------------------------------------------- + +/* + * basic types traits + */ + +ANDROID_BASIC_TYPES_TRAITS( void ) +ANDROID_BASIC_TYPES_TRAITS( bool ) +ANDROID_BASIC_TYPES_TRAITS( char ) +ANDROID_BASIC_TYPES_TRAITS( unsigned char ) +ANDROID_BASIC_TYPES_TRAITS( short ) +ANDROID_BASIC_TYPES_TRAITS( unsigned short ) +ANDROID_BASIC_TYPES_TRAITS( int ) +ANDROID_BASIC_TYPES_TRAITS( unsigned int ) +ANDROID_BASIC_TYPES_TRAITS( long ) +ANDROID_BASIC_TYPES_TRAITS( unsigned long ) +ANDROID_BASIC_TYPES_TRAITS( long long ) +ANDROID_BASIC_TYPES_TRAITS( unsigned long long ) +ANDROID_BASIC_TYPES_TRAITS( float ) +ANDROID_BASIC_TYPES_TRAITS( double ) + +// --------------------------------------------------------------------------- + + +/* + * compare and order types + */ + +template inline +int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { + return (lhs < rhs) ? 1 : 0; +} + +template inline +int compare_type(const TYPE& lhs, const TYPE& rhs) { + return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs); +} + +/* + * create, destroy, copy and move types... + */ + +template inline +void construct_type(TYPE* p, size_t n) { + if (!traits::has_trivial_ctor) { + while (n > 0) { + n--; + new(p++) TYPE; + } + } +} + +template inline +void destroy_type(TYPE* p, size_t n) { + if (!traits::has_trivial_dtor) { + while (n > 0) { + n--; + p->~TYPE(); + p++; + } + } +} + +template +typename std::enable_if::has_trivial_copy>::type +inline +copy_type(TYPE* d, const TYPE* s, size_t n) { + memcpy(d,s,n*sizeof(TYPE)); +} + +template +typename std::enable_if::has_trivial_copy>::type +inline +copy_type(TYPE* d, const TYPE* s, size_t n) { + while (n > 0) { + n--; + new(d) TYPE(*s); + d++, s++; + } +} + +template inline +void splat_type(TYPE* where, const TYPE* what, size_t n) { + if (!traits::has_trivial_copy) { + while (n > 0) { + n--; + new(where) TYPE(*what); + where++; + } + } else { + while (n > 0) { + n--; + *where++ = *what; + } + } +} + +template +struct use_trivial_move : public std::integral_constant::has_trivial_dtor && traits::has_trivial_copy) + || traits::has_trivial_move +> {}; + +template +typename std::enable_if::value>::type +inline +move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { + memmove(d, s, n*sizeof(TYPE)); +} + +template +typename std::enable_if::value>::type +inline +move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { + d += n; + s += n; + while (n > 0) { + n--; + --d, --s; + if (!traits::has_trivial_copy) { + new(d) TYPE(*s); + } else { + *d = *s; + } + if (!traits::has_trivial_dtor) { + s->~TYPE(); + } + } +} + +template +typename std::enable_if::value>::type +inline +move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { + memmove(d, s, n*sizeof(TYPE)); +} + +template +typename std::enable_if::value>::type +inline +move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { + while (n > 0) { + n--; + if (!traits::has_trivial_copy) { + new(d) TYPE(*s); + } else { + *d = *s; + } + if (!traits::has_trivial_dtor) { + s->~TYPE(); + } + d++, s++; + } +} + +// --------------------------------------------------------------------------- + +/* + * a key/value pair + */ + +template +struct key_value_pair_t { + typedef KEY key_t; + typedef VALUE value_t; + + KEY key; + VALUE value; + key_value_pair_t() { } + key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } + key_value_pair_t& operator=(const key_value_pair_t& o) { + key = o.key; + value = o.value; + return *this; + } + key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } + explicit key_value_pair_t(const KEY& k) : key(k) { } + inline bool operator < (const key_value_pair_t& o) const { + return strictly_order_type(key, o.key); + } + inline const KEY& getKey() const { + return key; + } + inline const VALUE& getValue() const { + return value; + } +}; + +template +struct trait_trivial_ctor< key_value_pair_t > +{ enum { value = aggregate_traits::has_trivial_ctor }; }; +template +struct trait_trivial_dtor< key_value_pair_t > +{ enum { value = aggregate_traits::has_trivial_dtor }; }; +template +struct trait_trivial_copy< key_value_pair_t > +{ enum { value = aggregate_traits::has_trivial_copy }; }; +template +struct trait_trivial_move< key_value_pair_t > +{ enum { value = aggregate_traits::has_trivial_move }; }; + +// --------------------------------------------------------------------------- + +/* + * Hash codes. + */ +typedef uint32_t hash_t; + +template +hash_t hash_type(const TKey& key); + +/* Built-in hash code specializations */ +#define ANDROID_INT32_HASH(T) \ + template <> inline hash_t hash_type(const T& value) { return hash_t(value); } +#define ANDROID_INT64_HASH(T) \ + template <> inline hash_t hash_type(const T& value) { \ + return hash_t((value >> 32) ^ value); } +#define ANDROID_REINTERPRET_HASH(T, R) \ + template <> inline hash_t hash_type(const T& value) { \ + R newValue; \ + static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \ + memcpy(&newValue, &value, sizeof(newValue)); \ + return hash_type(newValue); \ + } + +ANDROID_INT32_HASH(bool) +ANDROID_INT32_HASH(int8_t) +ANDROID_INT32_HASH(uint8_t) +ANDROID_INT32_HASH(int16_t) +ANDROID_INT32_HASH(uint16_t) +ANDROID_INT32_HASH(int32_t) +ANDROID_INT32_HASH(uint32_t) +ANDROID_INT64_HASH(int64_t) +ANDROID_INT64_HASH(uint64_t) +ANDROID_REINTERPRET_HASH(float, uint32_t) +ANDROID_REINTERPRET_HASH(double, uint64_t) + +template inline hash_t hash_type(T* const & value) { + return hash_type(uintptr_t(value)); +} + +}; // namespace android + +// --------------------------------------------------------------------------- + +#endif // ANDROID_TYPE_HELPERS_H diff --git a/tests/perftests/FontCollection.cpp b/tests/perftests/FontCollection.cpp index 79f25631b0..55789f91d1 100644 --- a/tests/perftests/FontCollection.cpp +++ b/tests/perftests/FontCollection.cpp @@ -87,7 +87,7 @@ static void BM_FontCollection_itemize(benchmark::State& state) { std::vector result; FontStyle style(FontStyle::registerLanguageList(ITEMIZE_TEST_CASES[testIndex].languageTag)); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); while (state.KeepRunning()) { result.clear(); collection->itemize(buffer, utf16_length, style, &result); diff --git a/tests/unittest/FontCollectionItemizeTest.cpp b/tests/unittest/FontCollectionItemizeTest.cpp index 78bfa3b94d..974a202e51 100644 --- a/tests/unittest/FontCollectionItemizeTest.cpp +++ b/tests/unittest/FontCollectionItemizeTest.cpp @@ -60,7 +60,7 @@ void itemize(const std::shared_ptr& collection, const char* str, result->clear(); ParseUnicode(buf, BUF_SIZE, str, &len, NULL); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); collection->itemize(buf, len, style, result); } @@ -72,7 +72,7 @@ const std::string& getFontPath(const FontCollection::Run& run) { // Utility function to obtain FontLanguages from string. const FontLanguages& registerAndGetFontLanguages(const std::string& lang_string) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); return FontLanguageListCache::getById(FontLanguageListCache::getId(lang_string)); } diff --git a/tests/unittest/FontFamilyTest.cpp b/tests/unittest/FontFamilyTest.cpp index 5a775a3587..072d3bf87b 100644 --- a/tests/unittest/FontFamilyTest.cpp +++ b/tests/unittest/FontFamilyTest.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include "FontLanguageListCache.h" @@ -30,13 +30,13 @@ typedef ICUTestBase FontLanguagesTest; typedef ICUTestBase FontLanguageTest; static const FontLanguages& createFontLanguages(const std::string& input) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); uint32_t langId = FontLanguageListCache::getId(input); return FontLanguageListCache::getById(langId); } static FontLanguage createFontLanguage(const std::string& input) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); uint32_t langId = FontLanguageListCache::getId(input); return FontLanguageListCache::getById(langId)[0]; } @@ -539,7 +539,7 @@ TEST_F(FontFamilyTest, hasVariationSelectorTest) { std::shared_ptr family( new FontFamily(std::vector{ Font(minikinFont, FontStyle()) })); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); const uint32_t kVS1 = 0xFE00; const uint32_t kVS2 = 0xFE01; @@ -592,7 +592,7 @@ TEST_F(FontFamilyTest, hasVSTableTest) { new MinikinFontForTest(testCase.fontPath)); std::shared_ptr family(new FontFamily( std::vector{ Font(minikinFont, FontStyle()) })); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); EXPECT_EQ(testCase.hasVSTable, family->hasVSTable()); } } @@ -673,7 +673,7 @@ TEST_F(FontFamilyTest, coverageTableSelectionTest) { std::shared_ptr unicodeEnc3Font = makeFamily(kUnicodeEncoding3Font); std::shared_ptr unicodeEnc4Font = makeFamily(kUnicodeEncoding4Font); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); EXPECT_TRUE(unicodeEnc1Font->hasGlyph(0x0061, 0)); EXPECT_TRUE(unicodeEnc3Font->hasGlyph(0x0061, 0)); diff --git a/tests/unittest/FontLanguageListCacheTest.cpp b/tests/unittest/FontLanguageListCacheTest.cpp index 81d84a8a28..27bdc09e06 100644 --- a/tests/unittest/FontLanguageListCacheTest.cpp +++ b/tests/unittest/FontLanguageListCacheTest.cpp @@ -31,7 +31,7 @@ TEST_F(FontLanguageListCacheTest, getId) { EXPECT_NE(0UL, FontStyle::registerLanguageList("jp")); EXPECT_NE(0UL, FontStyle::registerLanguageList("en,zh-Hans")); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); EXPECT_EQ(0UL, FontLanguageListCache::getId("")); EXPECT_EQ(FontLanguageListCache::getId("en"), FontLanguageListCache::getId("en")); @@ -50,7 +50,7 @@ TEST_F(FontLanguageListCacheTest, getId) { } TEST_F(FontLanguageListCacheTest, getById) { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); uint32_t enLangId = FontLanguageListCache::getId("en"); uint32_t jpLangId = FontLanguageListCache::getId("jp"); FontLanguage english = FontLanguageListCache::getById(enLangId)[0]; diff --git a/tests/unittest/HbFontCacheTest.cpp b/tests/unittest/HbFontCacheTest.cpp index a5581a27b8..5816a3250c 100644 --- a/tests/unittest/HbFontCacheTest.cpp +++ b/tests/unittest/HbFontCacheTest.cpp @@ -16,10 +16,10 @@ #include "HbFontCache.h" -#include +#include #include -#include +#include #include #include @@ -33,7 +33,7 @@ namespace minikin { class HbFontCacheTest : public testing::Test { public: virtual void TearDown() { - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); purgeHbFontCacheLocked(); } }; @@ -48,7 +48,7 @@ TEST_F(HbFontCacheTest, getHbFontLockedTest) { std::shared_ptr fontC( new MinikinFontForTest(kTestFontDir "BoldItalic.ttf")); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); // Never return NULL. EXPECT_NE(nullptr, getHbFontLocked(fontA.get())); EXPECT_NE(nullptr, getHbFontLocked(fontB.get())); @@ -70,7 +70,7 @@ TEST_F(HbFontCacheTest, purgeCacheTest) { std::shared_ptr minikinFont( new MinikinFontForTest(kTestFontDir "Regular.ttf")); - android::AutoMutex _l(gMinikinLock); + std::lock_guard _l(gMinikinLock); hb_font_t* font = getHbFontLocked(minikinFont.get()); ASSERT_NE(nullptr, font); diff --git a/tests/unittest/WordBreakerTests.cpp b/tests/unittest/WordBreakerTests.cpp index 13e0420c8a..0e6cea8db6 100644 --- a/tests/unittest/WordBreakerTests.cpp +++ b/tests/unittest/WordBreakerTests.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "Minikin" -#include +#include #include #include "ICUTestBase.h" -- GitLab