nsThebesFontEnumerator.cpp (7237B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nsThebesFontEnumerator.h" 7 #include <stdint.h> // for uint32_t 8 #include "gfxPlatform.h" // for gfxPlatform 9 #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 10 #include "mozilla/UniquePtr.h" 11 #include "mozilla/dom/Promise.h" // for mozilla::dom::Promise 12 #include "nsCOMPtr.h" // for nsCOMPtr 13 #include "nsDebug.h" // for NS_ENSURE_ARG_POINTER 14 #include "nsError.h" // for NS_OK, NS_FAILED, nsresult 15 #include "nsAtom.h" // for nsAtom, NS_Atomize 16 #include "nsID.h" 17 #include "nsString.h" // for nsAutoCString, nsAutoString, etc 18 #include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc 19 #include "nscore.h" // for char16_t, NS_IMETHODIMP 20 21 using mozilla::MakeUnique; 22 using mozilla::Runnable; 23 using mozilla::UniquePtr; 24 25 NS_IMPL_ISUPPORTS(nsThebesFontEnumerator, nsIFontEnumerator) 26 27 nsThebesFontEnumerator::nsThebesFontEnumerator() = default; 28 29 NS_IMETHODIMP 30 nsThebesFontEnumerator::EnumerateAllFonts(nsTArray<nsString>& aResult) { 31 return EnumerateFonts(nullptr, nullptr, aResult); 32 } 33 34 NS_IMETHODIMP 35 nsThebesFontEnumerator::EnumerateFonts(const char* aLangGroup, 36 const char* aGeneric, 37 nsTArray<nsString>& aResult) { 38 nsAutoCString generic; 39 if (aGeneric) 40 generic.Assign(aGeneric); 41 else 42 generic.SetIsVoid(true); 43 44 RefPtr<nsAtom> langGroupAtom; 45 if (aLangGroup) { 46 nsAutoCString lowered; 47 lowered.Assign(aLangGroup); 48 ToLowerCase(lowered); 49 langGroupAtom = NS_Atomize(lowered); 50 } 51 52 return gfxPlatform::GetPlatform()->GetFontList(langGroupAtom, generic, 53 aResult); 54 } 55 56 struct EnumerateFontsPromise final { 57 explicit EnumerateFontsPromise(mozilla::dom::Promise* aPromise) 58 : mPromise(aPromise) { 59 MOZ_ASSERT(aPromise); 60 MOZ_ASSERT(NS_IsMainThread()); 61 } 62 63 RefPtr<mozilla::dom::Promise> mPromise; 64 }; 65 66 class EnumerateFontsResult final : public Runnable { 67 public: 68 EnumerateFontsResult(nsresult aRv, 69 UniquePtr<EnumerateFontsPromise> aEnumerateFontsPromise, 70 nsTArray<nsString> aFontList) 71 : Runnable("EnumerateFontsResult"), 72 mRv(aRv), 73 mEnumerateFontsPromise(std::move(aEnumerateFontsPromise)), 74 mFontList(std::move(aFontList)), 75 mWorkerThread(do_GetCurrentThread()) { 76 MOZ_ASSERT(!NS_IsMainThread()); 77 } 78 79 NS_IMETHOD Run() override { 80 MOZ_ASSERT(NS_IsMainThread()); 81 82 if (NS_FAILED(mRv)) { 83 mEnumerateFontsPromise->mPromise->MaybeReject(mRv); 84 } else { 85 mEnumerateFontsPromise->mPromise->MaybeResolve(mFontList); 86 } 87 88 mWorkerThread->Shutdown(); 89 90 return NS_OK; 91 } 92 93 private: 94 nsresult mRv; 95 UniquePtr<EnumerateFontsPromise> mEnumerateFontsPromise; 96 nsTArray<nsString> mFontList; 97 nsCOMPtr<nsIThread> mWorkerThread; 98 }; 99 100 class EnumerateFontsTask final : public Runnable { 101 public: 102 EnumerateFontsTask(nsAtom* aLangGroupAtom, const nsAutoCString& aGeneric, 103 UniquePtr<EnumerateFontsPromise> aEnumerateFontsPromise, 104 nsIEventTarget* aMainThreadTarget) 105 : Runnable("EnumerateFontsTask"), 106 mLangGroupAtom(aLangGroupAtom), 107 mGeneric(aGeneric), 108 mEnumerateFontsPromise(std::move(aEnumerateFontsPromise)), 109 mMainThreadTarget(aMainThreadTarget) { 110 MOZ_ASSERT(NS_IsMainThread()); 111 } 112 113 NS_IMETHOD Run() override { 114 MOZ_ASSERT(!NS_IsMainThread()); 115 116 nsTArray<nsString> fontList; 117 118 nsresult rv = gfxPlatform::GetPlatform()->GetFontList(mLangGroupAtom, 119 mGeneric, fontList); 120 nsCOMPtr<nsIRunnable> runnable = new EnumerateFontsResult( 121 rv, std::move(mEnumerateFontsPromise), std::move(fontList)); 122 mMainThreadTarget->Dispatch(runnable.forget()); 123 124 return NS_OK; 125 } 126 127 private: 128 RefPtr<nsAtom> mLangGroupAtom; 129 nsAutoCStringN<16> mGeneric; 130 UniquePtr<EnumerateFontsPromise> mEnumerateFontsPromise; 131 RefPtr<nsIEventTarget> mMainThreadTarget; 132 }; 133 134 NS_IMETHODIMP 135 nsThebesFontEnumerator::EnumerateAllFontsAsync( 136 JSContext* aCx, JS::MutableHandle<JS::Value> aRval) { 137 return EnumerateFontsAsync(nullptr, nullptr, aCx, aRval); 138 } 139 140 NS_IMETHODIMP 141 nsThebesFontEnumerator::EnumerateFontsAsync( 142 const char* aLangGroup, const char* aGeneric, JSContext* aCx, 143 JS::MutableHandle<JS::Value> aRval) { 144 MOZ_ASSERT(NS_IsMainThread()); 145 146 nsCOMPtr<nsIGlobalObject> global = xpc::CurrentNativeGlobal(aCx); 147 NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED); 148 149 mozilla::ErrorResult errv; 150 RefPtr<mozilla::dom::Promise> promise = 151 mozilla::dom::Promise::Create(global, errv); 152 if (errv.Failed()) { 153 return errv.StealNSResult(); 154 } 155 156 auto enumerateFontsPromise = MakeUnique<EnumerateFontsPromise>(promise); 157 158 nsCOMPtr<nsIThread> thread; 159 nsresult rv = NS_NewNamedThread("FontEnumThread", getter_AddRefs(thread)); 160 NS_ENSURE_SUCCESS(rv, rv); 161 162 RefPtr<nsAtom> langGroupAtom; 163 if (aLangGroup) { 164 nsAutoCStringN<16> lowered; 165 lowered.Assign(aLangGroup); 166 ToLowerCase(lowered); 167 langGroupAtom = NS_Atomize(lowered); 168 } 169 170 nsAutoCString generic; 171 if (aGeneric) { 172 generic.Assign(aGeneric); 173 } else { 174 generic.SetIsVoid(true); 175 } 176 177 nsCOMPtr<nsIEventTarget> target = global->SerialEventTarget(); 178 nsCOMPtr<nsIRunnable> runnable = new EnumerateFontsTask( 179 langGroupAtom, generic, std::move(enumerateFontsPromise), target); 180 thread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL); 181 182 if (!ToJSValue(aCx, promise, aRval)) { 183 return NS_ERROR_FAILURE; 184 } 185 186 return NS_OK; 187 } 188 189 NS_IMETHODIMP 190 nsThebesFontEnumerator::HaveFontFor(const char* aLangGroup, bool* aResult) { 191 NS_ENSURE_ARG_POINTER(aResult); 192 193 *aResult = true; 194 return NS_OK; 195 } 196 197 NS_IMETHODIMP 198 nsThebesFontEnumerator::GetDefaultFont(const char* aLangGroup, 199 const char* aGeneric, 200 char16_t** aResult) { 201 if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aLangGroup) || 202 NS_WARN_IF(!aGeneric)) { 203 return NS_ERROR_INVALID_ARG; 204 } 205 206 *aResult = nullptr; 207 nsAutoCString defaultFontName(gfxPlatform::GetPlatform()->GetDefaultFontName( 208 nsDependentCString(aLangGroup), nsDependentCString(aGeneric))); 209 if (!defaultFontName.IsEmpty()) { 210 *aResult = UTF8ToNewUnicode(defaultFontName); 211 } 212 return NS_OK; 213 } 214 215 NS_IMETHODIMP 216 nsThebesFontEnumerator::GetStandardFamilyName(const char16_t* aName, 217 char16_t** aResult) { 218 NS_ENSURE_ARG_POINTER(aResult); 219 NS_ENSURE_ARG_POINTER(aName); 220 221 nsAutoString name(aName); 222 if (name.IsEmpty()) { 223 *aResult = nullptr; 224 return NS_OK; 225 } 226 227 nsAutoCString family; 228 gfxPlatform::GetPlatform()->GetStandardFamilyName( 229 NS_ConvertUTF16toUTF8(aName), family); 230 if (family.IsEmpty()) { 231 *aResult = nullptr; 232 return NS_OK; 233 } 234 *aResult = UTF8ToNewUnicode(family); 235 return NS_OK; 236 }