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/. */
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
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
21 using mozilla::MakeUnique
;
22 using mozilla::Runnable
;
23 using mozilla::UniquePtr
;
25 NS_IMPL_ISUPPORTS(nsThebesFontEnumerator
, nsIFontEnumerator
)
27 nsThebesFontEnumerator::nsThebesFontEnumerator() = default;
30 nsThebesFontEnumerator::EnumerateAllFonts(nsTArray
<nsString
>& aResult
) {
31 return EnumerateFonts(nullptr, nullptr, aResult
);
35 nsThebesFontEnumerator::EnumerateFonts(const char* aLangGroup
,
37 nsTArray
<nsString
>& aResult
) {
38 nsAutoCString generic
;
40 generic
.Assign(aGeneric
);
42 generic
.SetIsVoid(true);
44 RefPtr
<nsAtom
> langGroupAtom
;
46 nsAutoCString lowered
;
47 lowered
.Assign(aLangGroup
);
49 langGroupAtom
= NS_Atomize(lowered
);
52 return gfxPlatform::GetPlatform()->GetFontList(langGroupAtom
, generic
,
56 struct EnumerateFontsPromise final
{
57 explicit EnumerateFontsPromise(mozilla::dom::Promise
* aPromise
)
58 : mPromise(aPromise
) {
60 MOZ_ASSERT(NS_IsMainThread());
63 RefPtr
<mozilla::dom::Promise
> mPromise
;
66 class EnumerateFontsResult final
: public Runnable
{
68 EnumerateFontsResult(nsresult aRv
,
69 UniquePtr
<EnumerateFontsPromise
> aEnumerateFontsPromise
,
70 nsTArray
<nsString
> aFontList
)
71 : Runnable("EnumerateFontsResult"),
73 mEnumerateFontsPromise(std::move(aEnumerateFontsPromise
)),
74 mFontList(std::move(aFontList
)),
75 mWorkerThread(do_GetCurrentThread()) {
76 MOZ_ASSERT(!NS_IsMainThread());
79 NS_IMETHOD
Run() override
{
80 MOZ_ASSERT(NS_IsMainThread());
83 mEnumerateFontsPromise
->mPromise
->MaybeReject(mRv
);
85 mEnumerateFontsPromise
->mPromise
->MaybeResolve(mFontList
);
88 mWorkerThread
->Shutdown();
95 UniquePtr
<EnumerateFontsPromise
> mEnumerateFontsPromise
;
96 nsTArray
<nsString
> mFontList
;
97 nsCOMPtr
<nsIThread
> mWorkerThread
;
100 class EnumerateFontsTask final
: public Runnable
{
102 EnumerateFontsTask(nsAtom
* aLangGroupAtom
, const nsAutoCString
& aGeneric
,
103 UniquePtr
<EnumerateFontsPromise
> aEnumerateFontsPromise
,
104 nsIEventTarget
* aMainThreadTarget
)
105 : Runnable("EnumerateFontsTask"),
106 mLangGroupAtom(aLangGroupAtom
),
108 mEnumerateFontsPromise(std::move(aEnumerateFontsPromise
)),
109 mMainThreadTarget(aMainThreadTarget
) {
110 MOZ_ASSERT(NS_IsMainThread());
113 NS_IMETHOD
Run() override
{
114 MOZ_ASSERT(!NS_IsMainThread());
116 nsTArray
<nsString
> fontList
;
118 nsresult rv
= gfxPlatform::GetPlatform()->GetFontList(mLangGroupAtom
,
120 nsCOMPtr
<nsIRunnable
> runnable
= new EnumerateFontsResult(
121 rv
, std::move(mEnumerateFontsPromise
), std::move(fontList
));
122 mMainThreadTarget
->Dispatch(runnable
.forget());
128 RefPtr
<nsAtom
> mLangGroupAtom
;
129 nsAutoCStringN
<16> mGeneric
;
130 UniquePtr
<EnumerateFontsPromise
> mEnumerateFontsPromise
;
131 RefPtr
<nsIEventTarget
> mMainThreadTarget
;
135 nsThebesFontEnumerator::EnumerateAllFontsAsync(
136 JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aRval
) {
137 return EnumerateFontsAsync(nullptr, nullptr, aCx
, aRval
);
141 nsThebesFontEnumerator::EnumerateFontsAsync(
142 const char* aLangGroup
, const char* aGeneric
, JSContext
* aCx
,
143 JS::MutableHandle
<JS::Value
> aRval
) {
144 MOZ_ASSERT(NS_IsMainThread());
146 nsCOMPtr
<nsIGlobalObject
> global
= xpc::CurrentNativeGlobal(aCx
);
147 NS_ENSURE_TRUE(global
, NS_ERROR_UNEXPECTED
);
149 mozilla::ErrorResult errv
;
150 RefPtr
<mozilla::dom::Promise
> promise
=
151 mozilla::dom::Promise::Create(global
, errv
);
153 return errv
.StealNSResult();
156 auto enumerateFontsPromise
= MakeUnique
<EnumerateFontsPromise
>(promise
);
158 nsCOMPtr
<nsIThread
> thread
;
159 nsresult rv
= NS_NewNamedThread("FontEnumThread", getter_AddRefs(thread
));
160 NS_ENSURE_SUCCESS(rv
, rv
);
162 RefPtr
<nsAtom
> langGroupAtom
;
164 nsAutoCStringN
<16> lowered
;
165 lowered
.Assign(aLangGroup
);
166 ToLowerCase(lowered
);
167 langGroupAtom
= NS_Atomize(lowered
);
170 nsAutoCString generic
;
172 generic
.Assign(aGeneric
);
174 generic
.SetIsVoid(true);
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
);
182 if (!ToJSValue(aCx
, promise
, aRval
)) {
183 return NS_ERROR_FAILURE
;
190 nsThebesFontEnumerator::HaveFontFor(const char* aLangGroup
, bool* aResult
) {
191 NS_ENSURE_ARG_POINTER(aResult
);
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
;
207 nsAutoCString
defaultFontName(gfxPlatform::GetPlatform()->GetDefaultFontName(
208 nsDependentCString(aLangGroup
), nsDependentCString(aGeneric
)));
209 if (!defaultFontName
.IsEmpty()) {
210 *aResult
= UTF8ToNewUnicode(defaultFontName
);
216 nsThebesFontEnumerator::GetStandardFamilyName(const char16_t
* aName
,
217 char16_t
** aResult
) {
218 NS_ENSURE_ARG_POINTER(aResult
);
219 NS_ENSURE_ARG_POINTER(aName
);
221 nsAutoString
name(aName
);
222 if (name
.IsEmpty()) {
227 nsAutoCString family
;
228 gfxPlatform::GetPlatform()->GetStandardFamilyName(
229 NS_ConvertUTF16toUTF8(aName
), family
);
230 if (family
.IsEmpty()) {
234 *aResult
= UTF8ToNewUnicode(family
);