1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "gfxAndroidPlatform.h"
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/CountingAllocatorBase.h"
12 #include "mozilla/Preferences.h"
14 #include "gfx2DGlue.h"
15 #include "gfxFT2FontList.h"
16 #include "gfxImageSurface.h"
17 #include "mozilla/dom/ContentChild.h"
18 #include "nsXULAppAPI.h"
19 #include "nsIScreen.h"
20 #include "nsIScreenManager.h"
21 #include "nsILocaleService.h"
22 #include "nsServiceManagerUtils.h"
26 #ifdef MOZ_WIDGET_ANDROID
27 #include "AndroidBridge.h"
30 #ifdef MOZ_WIDGET_GONK
31 #include <cutils/properties.h>
35 #include FT_FREETYPE_H
38 using namespace mozilla
;
39 using namespace mozilla::dom
;
40 using namespace mozilla::gfx
;
42 static FT_Library gPlatformFTLibrary
= nullptr;
44 class FreetypeReporter MOZ_FINAL
: public nsIMemoryReporter
,
45 public CountingAllocatorBase
<FreetypeReporter
>
48 ~FreetypeReporter() {}
53 static void* Malloc(FT_Memory
, long size
)
55 return CountingMalloc(size
);
58 static void Free(FT_Memory
, void* p
)
60 return CountingFree(p
);
64 Realloc(FT_Memory
, long cur_size
, long new_size
, void* p
)
66 return CountingRealloc(p
, new_size
);
69 NS_IMETHOD
CollectReports(nsIHandleReportCallback
* aHandleReport
,
70 nsISupports
* aData
, bool aAnonymize
)
72 return MOZ_COLLECT_REPORT(
73 "explicit/freetype", KIND_HEAP
, UNITS_BYTES
, MemoryAllocated(),
74 "Memory used by Freetype.");
78 NS_IMPL_ISUPPORTS(FreetypeReporter
, nsIMemoryReporter
)
80 template<> Atomic
<size_t> CountingAllocatorBase
<FreetypeReporter
>::sAmount(0);
82 static FT_MemoryRec_ sFreetypeMemoryRecord
;
84 gfxAndroidPlatform::gfxAndroidPlatform()
86 // A custom allocator. It counts allocations, enabling memory reporting.
87 sFreetypeMemoryRecord
.user
= nullptr;
88 sFreetypeMemoryRecord
.alloc
= FreetypeReporter::Malloc
;
89 sFreetypeMemoryRecord
.free
= FreetypeReporter::Free
;
90 sFreetypeMemoryRecord
.realloc
= FreetypeReporter::Realloc
;
92 // These two calls are equivalent to FT_Init_FreeType(), but allow us to
93 // provide a custom memory allocator.
94 FT_New_Library(&sFreetypeMemoryRecord
, &gPlatformFTLibrary
);
95 FT_Add_Default_Modules(gPlatformFTLibrary
);
97 RegisterStrongMemoryReporter(new FreetypeReporter());
99 nsCOMPtr
<nsIScreenManager
> screenMgr
= do_GetService("@mozilla.org/gfx/screenmanager;1");
100 nsCOMPtr
<nsIScreen
> screen
;
101 screenMgr
->GetPrimaryScreen(getter_AddRefs(screen
));
103 screen
->GetColorDepth(&mScreenDepth
);
105 mOffscreenFormat
= mScreenDepth
== 16
106 ? gfxImageFormat::RGB16_565
107 : gfxImageFormat::RGB24
;
109 if (gfxPrefs::AndroidRGB16Force()) {
110 mOffscreenFormat
= gfxImageFormat::RGB16_565
;
113 #ifdef MOZ_WIDGET_GONK
114 char propQemu
[PROPERTY_VALUE_MAX
];
115 property_get("ro.kernel.qemu", propQemu
, "");
116 mIsInGonkEmulator
= !strncmp(propQemu
, "1", 1);
120 gfxAndroidPlatform::~gfxAndroidPlatform()
122 FT_Done_Library(gPlatformFTLibrary
);
123 gPlatformFTLibrary
= nullptr;
126 already_AddRefed
<gfxASurface
>
127 gfxAndroidPlatform::CreateOffscreenSurface(const IntSize
& size
,
128 gfxContentType contentType
)
130 nsRefPtr
<gfxASurface
> newSurface
;
131 newSurface
= new gfxImageSurface(ThebesIntSize(size
),
132 OptimalFormatForContent(contentType
));
134 return newSurface
.forget();
140 static bool sInitialized
= false;
141 static bool sIsJapanese
= false;
146 do { // to allow 'break' to abandon this block if a call fails
148 nsCOMPtr
<nsILocaleService
> ls
=
149 do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
153 nsCOMPtr
<nsILocale
> appLocale
;
154 rv
= ls
->GetApplicationLocale(getter_AddRefs(appLocale
));
160 GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE
), localeStr
);
164 const nsAString
& lang
= nsDependentSubstring(localeStr
, 0, 2);
165 if (lang
.EqualsLiteral("ja")) {
175 gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh
,
177 nsTArray
<const char*>& aFontList
)
179 static const char kDroidSansJapanese
[] = "Droid Sans Japanese";
180 static const char kMotoyaLMaru
[] = "MotoyaLMaru";
182 if (IS_IN_BMP(aCh
)) {
183 // try language-specific "Droid Sans *" and "Noto Sans *" fonts for
184 // certain blocks, as most devices probably have these
185 uint8_t block
= (aCh
>> 8) & 0xff;
188 aFontList
.AppendElement("Droid Sans Hebrew");
189 aFontList
.AppendElement("Droid Sans Armenian");
192 aFontList
.AppendElement("Droid Sans Arabic");
195 aFontList
.AppendElement("Noto Sans Devanagari");
196 aFontList
.AppendElement("Droid Sans Devanagari");
199 aFontList
.AppendElement("Noto Sans Tamil");
200 aFontList
.AppendElement("Droid Sans Tamil");
203 aFontList
.AppendElement("Noto Sans Thai");
204 aFontList
.AppendElement("Droid Sans Thai");
206 case 0x10: case 0x2d:
207 aFontList
.AppendElement("Droid Sans Georgian");
209 case 0x12: case 0x13:
210 aFontList
.AppendElement("Droid Sans Ethiopic");
212 case 0xf9: case 0xfa:
213 if (IsJapaneseLocale()) {
214 aFontList
.AppendElement(kMotoyaLMaru
);
215 aFontList
.AppendElement(kDroidSansJapanese
);
219 if (block
>= 0x2e && block
<= 0x9f && IsJapaneseLocale()) {
220 aFontList
.AppendElement(kMotoyaLMaru
);
221 aFontList
.AppendElement(kDroidSansJapanese
);
226 // and try Droid Sans Fallback as a last resort
227 aFontList
.AppendElement("Droid Sans Fallback");
231 gfxAndroidPlatform::GetFontList(nsIAtom
*aLangGroup
,
232 const nsACString
& aGenericFamily
,
233 nsTArray
<nsString
>& aListOfFonts
)
235 gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup
,
242 gfxAndroidPlatform::GetFontList(InfallibleTArray
<FontListEntry
>* retValue
)
244 gfxFT2FontList::PlatformFontList()->GetFontList(retValue
);
248 gfxAndroidPlatform::UpdateFontList()
250 gfxPlatformFontList::PlatformFontList()->UpdateFontList();
255 gfxAndroidPlatform::GetStandardFamilyName(const nsAString
& aFontName
, nsAString
& aFamilyName
)
257 gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName
, aFamilyName
);
262 gfxAndroidPlatform::CreatePlatformFontList()
264 gfxPlatformFontList
* list
= new gfxFT2FontList();
265 if (NS_SUCCEEDED(list
->InitFontList())) {
268 gfxPlatformFontList::Shutdown();
273 gfxAndroidPlatform::IsFontFormatSupported(nsIURI
*aFontURI
, uint32_t aFormatFlags
)
275 // check for strange format flags
276 NS_ASSERTION(!(aFormatFlags
& gfxUserFontSet::FLAG_FORMAT_NOT_USED
),
277 "strange font format hint set");
279 // accept supported formats
280 if (aFormatFlags
& (gfxUserFontSet::FLAG_FORMAT_OPENTYPE
|
281 gfxUserFontSet::FLAG_FORMAT_WOFF
|
282 gfxUserFontSet::FLAG_FORMAT_TRUETYPE
)) {
286 // reject all other formats, known and unknown
287 if (aFormatFlags
!= 0) {
291 // no format hint set, need to look at data
296 gfxAndroidPlatform::CreateFontGroup(const FontFamilyList
& aFontFamilyList
,
297 const gfxFontStyle
*aStyle
,
298 gfxUserFontSet
* aUserFontSet
)
300 return new gfxFontGroup(aFontFamilyList
, aStyle
, aUserFontSet
);
304 gfxAndroidPlatform::GetFTLibrary()
306 return gPlatformFTLibrary
;
310 gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry
*aProxyEntry
,
311 const uint8_t *aFontData
, uint32_t aLength
)
313 return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry
,
319 gfxAndroidPlatform::LookupLocalFont(const gfxProxyFontEntry
*aProxyEntry
,
320 const nsAString
& aFontName
)
322 return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry
,
326 TemporaryRef
<ScaledFont
>
327 gfxAndroidPlatform::GetScaledFontForFont(DrawTarget
* aTarget
, gfxFont
*aFont
)
329 return GetScaledFontForFontWithCairoSkia(aTarget
, aFont
);
333 gfxAndroidPlatform::FontHintingEnabled()
335 // In "mobile" builds, we sometimes use non-reflow-zoom, so we
336 // might not want hinting. Let's see.
338 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
339 // On android-java, we currently only use gecko to render web
340 // content that can always be be non-reflow-zoomed. So turn off
343 // XXX when gecko-android-java is used as an "app runtime", we may
344 // want to re-enable hinting for non-browser processes there.
346 #endif // MOZ_USING_ANDROID_JAVA_WIDGETS
348 #ifdef MOZ_WIDGET_GONK
349 // On B2G, the UX preference is currently to keep hinting disabled
350 // for all text (see bug 829523).
354 // Currently, we don't have any other targets, but if/when we do,
355 // decide how to handle them here.
357 NS_NOTREACHED("oops, what platform is this?");
358 return gfxPlatform::FontHintingEnabled();
362 gfxAndroidPlatform::RequiresLinearZoom()
364 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
365 // On android-java, we currently only use gecko to render web
366 // content that can always be be non-reflow-zoomed.
368 // XXX when gecko-android-java is used as an "app runtime", we may
369 // want to treat it like B2G and use linear zoom only for the web
370 // browser process, not other apps.
374 #ifdef MOZ_WIDGET_GONK
375 // On B2G, we need linear zoom for the browser, but otherwise prefer
376 // the improved glyph spacing that results from respecting the device
377 // pixel resolution for glyph layout (see bug 816614).
378 return XRE_GetProcessType() == GeckoProcessType_Content
&&
379 ContentChild::GetSingleton()->IsForBrowser();
382 NS_NOTREACHED("oops, what platform is this?");
383 return gfxPlatform::RequiresLinearZoom();
387 gfxAndroidPlatform::GetScreenDepth() const
393 gfxAndroidPlatform::UseAcceleratedSkiaCanvas()
395 #ifdef MOZ_WIDGET_ANDROID
396 if (AndroidBridge::Bridge()->GetAPIVersion() < 11) {
397 // It's slower than software due to not having a compositing fast path
402 return gfxPlatform::UseAcceleratedSkiaCanvas();