Bumping manifests a=b2g-bump
[gecko.git] / gfx / thebes / gfxAndroidPlatform.cpp
blob8b2f2c00296fc1ce6472fbe3b70b4ab65553a02f
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"
23 #include "gfxPrefs.h"
24 #include "cairo.h"
26 #ifdef MOZ_WIDGET_ANDROID
27 #include "AndroidBridge.h"
28 #endif
30 #ifdef MOZ_WIDGET_GONK
31 #include <cutils/properties.h>
32 #endif
34 #include "ft2build.h"
35 #include FT_FREETYPE_H
36 #include FT_MODULE_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>
47 private:
48 ~FreetypeReporter() {}
50 public:
51 NS_DECL_ISUPPORTS
53 static void* Malloc(FT_Memory, long size)
55 return CountingMalloc(size);
58 static void Free(FT_Memory, void* p)
60 return CountingFree(p);
63 static void*
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));
102 mScreenDepth = 24;
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);
117 #endif
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();
137 static bool
138 IsJapaneseLocale()
140 static bool sInitialized = false;
141 static bool sIsJapanese = false;
143 if (!sInitialized) {
144 sInitialized = true;
146 do { // to allow 'break' to abandon this block if a call fails
147 nsresult rv;
148 nsCOMPtr<nsILocaleService> ls =
149 do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
150 if (NS_FAILED(rv)) {
151 break;
153 nsCOMPtr<nsILocale> appLocale;
154 rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
155 if (NS_FAILED(rv)) {
156 break;
158 nsString localeStr;
159 rv = appLocale->
160 GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
161 if (NS_FAILED(rv)) {
162 break;
164 const nsAString& lang = nsDependentSubstring(localeStr, 0, 2);
165 if (lang.EqualsLiteral("ja")) {
166 sIsJapanese = true;
168 } while (false);
171 return sIsJapanese;
174 void
175 gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh,
176 int32_t aRunScript,
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;
186 switch (block) {
187 case 0x05:
188 aFontList.AppendElement("Droid Sans Hebrew");
189 aFontList.AppendElement("Droid Sans Armenian");
190 break;
191 case 0x06:
192 aFontList.AppendElement("Droid Sans Arabic");
193 break;
194 case 0x09:
195 aFontList.AppendElement("Noto Sans Devanagari");
196 aFontList.AppendElement("Droid Sans Devanagari");
197 break;
198 case 0x0b:
199 aFontList.AppendElement("Noto Sans Tamil");
200 aFontList.AppendElement("Droid Sans Tamil");
201 break;
202 case 0x0e:
203 aFontList.AppendElement("Noto Sans Thai");
204 aFontList.AppendElement("Droid Sans Thai");
205 break;
206 case 0x10: case 0x2d:
207 aFontList.AppendElement("Droid Sans Georgian");
208 break;
209 case 0x12: case 0x13:
210 aFontList.AppendElement("Droid Sans Ethiopic");
211 break;
212 case 0xf9: case 0xfa:
213 if (IsJapaneseLocale()) {
214 aFontList.AppendElement(kMotoyaLMaru);
215 aFontList.AppendElement(kDroidSansJapanese);
217 break;
218 default:
219 if (block >= 0x2e && block <= 0x9f && IsJapaneseLocale()) {
220 aFontList.AppendElement(kMotoyaLMaru);
221 aFontList.AppendElement(kDroidSansJapanese);
223 break;
226 // and try Droid Sans Fallback as a last resort
227 aFontList.AppendElement("Droid Sans Fallback");
230 nsresult
231 gfxAndroidPlatform::GetFontList(nsIAtom *aLangGroup,
232 const nsACString& aGenericFamily,
233 nsTArray<nsString>& aListOfFonts)
235 gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
236 aGenericFamily,
237 aListOfFonts);
238 return NS_OK;
241 void
242 gfxAndroidPlatform::GetFontList(InfallibleTArray<FontListEntry>* retValue)
244 gfxFT2FontList::PlatformFontList()->GetFontList(retValue);
247 nsresult
248 gfxAndroidPlatform::UpdateFontList()
250 gfxPlatformFontList::PlatformFontList()->UpdateFontList();
251 return NS_OK;
254 nsresult
255 gfxAndroidPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
257 gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
258 return NS_OK;
261 gfxPlatformFontList*
262 gfxAndroidPlatform::CreatePlatformFontList()
264 gfxPlatformFontList* list = new gfxFT2FontList();
265 if (NS_SUCCEEDED(list->InitFontList())) {
266 return list;
268 gfxPlatformFontList::Shutdown();
269 return nullptr;
272 bool
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)) {
283 return true;
286 // reject all other formats, known and unknown
287 if (aFormatFlags != 0) {
288 return false;
291 // no format hint set, need to look at data
292 return true;
295 gfxFontGroup *
296 gfxAndroidPlatform::CreateFontGroup(const FontFamilyList& aFontFamilyList,
297 const gfxFontStyle *aStyle,
298 gfxUserFontSet* aUserFontSet)
300 return new gfxFontGroup(aFontFamilyList, aStyle, aUserFontSet);
303 FT_Library
304 gfxAndroidPlatform::GetFTLibrary()
306 return gPlatformFTLibrary;
309 gfxFontEntry*
310 gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
311 const uint8_t *aFontData, uint32_t aLength)
313 return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
314 aFontData,
315 aLength);
318 gfxFontEntry*
319 gfxAndroidPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
320 const nsAString& aFontName)
322 return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry,
323 aFontName);
326 TemporaryRef<ScaledFont>
327 gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
329 return GetScaledFontForFontWithCairoSkia(aTarget, aFont);
332 bool
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
341 // hinting.
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.
345 return false;
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).
351 return false;
352 #endif
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();
361 bool
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.
371 return true;
372 #endif
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();
380 #endif
382 NS_NOTREACHED("oops, what platform is this?");
383 return gfxPlatform::RequiresLinearZoom();
387 gfxAndroidPlatform::GetScreenDepth() const
389 return mScreenDepth;
392 bool
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
398 return false;
400 #endif
402 return gfxPlatform::UseAcceleratedSkiaCanvas();