gecko/gfx/thebes/gfxAndroidPlatform.cpp
Ehsan Akhgari 6220f98ec6 Backed out 9 changesets (bug 943660, bug 936964) because of ASAN use-after-free crashes on browser-chrome and mochitest-other
Backed out changeset 85486c4aa3d8 (bug 936964)
Backed out changeset 25312eb71998 (bug 936964)
Backed out changeset 6dbb8333960c (bug 936964)
Backed out changeset da6465ad476f (bug 936964)
Backed out changeset a87ffc992f38 (bug 936964)
Backed out changeset 4ae3a61182db (bug 936964)
Backed out changeset 34e9c3137804 (bug 936964)
Backed out changeset fd1459e71585 (bug 936964)
Backed out changeset 3e8a701d8bdc (bug 943660)

Landed on a CLOSED TREE

--HG--
rename : content/canvas/src/WebGLMemoryTracker.h => content/canvas/src/WebGLMemoryReporterWrapper.h
2013-11-27 20:05:00 -05:00

402 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "gfxAndroidPlatform.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Preferences.h"
#include "gfxFT2FontList.h"
#include "gfxImageSurface.h"
#include "mozilla/dom/ContentChild.h"
#include "nsXULAppAPI.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
#include "nsILocaleService.h"
#include "nsServiceManagerUtils.h"
#include "cairo.h"
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_MODULE_H
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
static FT_Library gPlatformFTLibrary = nullptr;
class FreetypeReporter MOZ_FINAL : public MemoryUniReporter
{
public:
FreetypeReporter()
: MemoryUniReporter("explicit/freetype", KIND_HEAP, UNITS_BYTES,
"Memory used by Freetype.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
// being static.
static bool hasRun = false;
MOZ_ASSERT(!hasRun);
hasRun = true;
#endif
}
static void* CountingAlloc(FT_Memory, long size)
{
void *p = malloc(size);
sAmount += MallocSizeOfOnAlloc(p);
return p;
}
static void CountingFree(FT_Memory, void* p)
{
sAmount -= MallocSizeOfOnFree(p);
free(p);
}
static void*
CountingRealloc(FT_Memory, long cur_size, long new_size, void* p)
{
sAmount -= MallocSizeOfOnFree(p);
void *pnew = realloc(p, new_size);
if (pnew) {
sAmount += MallocSizeOfOnAlloc(pnew);
} else {
// realloc failed; undo the decrement from above
sAmount += MallocSizeOfOnAlloc(p);
}
return pnew;
}
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
static int64_t sAmount;
};
int64_t FreetypeReporter::sAmount = 0;
static FT_MemoryRec_ sFreetypeMemoryRecord;
gfxAndroidPlatform::gfxAndroidPlatform()
{
// A custom allocator. It counts allocations, enabling memory reporting.
sFreetypeMemoryRecord.user = nullptr;
sFreetypeMemoryRecord.alloc = FreetypeReporter::CountingAlloc;
sFreetypeMemoryRecord.free = FreetypeReporter::CountingFree;
sFreetypeMemoryRecord.realloc = FreetypeReporter::CountingRealloc;
// These two calls are equivalent to FT_Init_FreeType(), but allow us to
// provide a custom memory allocator.
FT_New_Library(&sFreetypeMemoryRecord, &gPlatformFTLibrary);
FT_Add_Default_Modules(gPlatformFTLibrary);
RegisterStrongMemoryReporter(new FreetypeReporter());
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
nsCOMPtr<nsIScreen> screen;
screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
mScreenDepth = 24;
screen->GetColorDepth(&mScreenDepth);
mOffscreenFormat = mScreenDepth == 16
? gfxImageFormatRGB16_565
: gfxImageFormatRGB24;
if (Preferences::GetBool("gfx.android.rgb16.force", false)) {
mOffscreenFormat = gfxImageFormatRGB16_565;
}
}
gfxAndroidPlatform::~gfxAndroidPlatform()
{
cairo_debug_reset_static_data();
FT_Done_Library(gPlatformFTLibrary);
gPlatformFTLibrary = nullptr;
}
already_AddRefed<gfxASurface>
gfxAndroidPlatform::CreateOffscreenSurface(const gfxIntSize& size,
gfxContentType contentType)
{
nsRefPtr<gfxASurface> newSurface;
newSurface = new gfxImageSurface(size, OptimalFormatForContent(contentType));
return newSurface.forget();
}
static bool
IsJapaneseLocale()
{
static bool sInitialized = false;
static bool sIsJapanese = false;
if (!sInitialized) {
sInitialized = true;
do { // to allow 'break' to abandon this block if a call fails
nsresult rv;
nsCOMPtr<nsILocaleService> ls =
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
break;
}
nsCOMPtr<nsILocale> appLocale;
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
if (NS_FAILED(rv)) {
break;
}
nsString localeStr;
rv = appLocale->
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
if (NS_FAILED(rv)) {
break;
}
const nsAString& lang = nsDependentSubstring(localeStr, 0, 2);
if (lang.EqualsLiteral("ja")) {
sIsJapanese = true;
}
} while (false);
}
return sIsJapanese;
}
void
gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh,
int32_t aRunScript,
nsTArray<const char*>& aFontList)
{
static const char kDroidSansJapanese[] = "Droid Sans Japanese";
static const char kMotoyaLMaru[] = "MotoyaLMaru";
if (IS_IN_BMP(aCh)) {
// try language-specific "Droid Sans *" fonts for certain blocks,
// as most devices probably have these
uint8_t block = (aCh >> 8) & 0xff;
switch (block) {
case 0x05:
aFontList.AppendElement("Droid Sans Hebrew");
aFontList.AppendElement("Droid Sans Armenian");
break;
case 0x06:
aFontList.AppendElement("Droid Sans Arabic");
break;
case 0x09:
aFontList.AppendElement("Droid Sans Devanagari");
break;
case 0x0b:
aFontList.AppendElement("Droid Sans Tamil");
break;
case 0x0e:
aFontList.AppendElement("Droid Sans Thai");
break;
case 0x10: case 0x2d:
aFontList.AppendElement("Droid Sans Georgian");
break;
case 0x12: case 0x13:
aFontList.AppendElement("Droid Sans Ethiopic");
break;
case 0xf9: case 0xfa:
if (IsJapaneseLocale()) {
aFontList.AppendElement(kMotoyaLMaru);
aFontList.AppendElement(kDroidSansJapanese);
}
break;
default:
if (block >= 0x2e && block <= 0x9f && IsJapaneseLocale()) {
aFontList.AppendElement(kMotoyaLMaru);
aFontList.AppendElement(kDroidSansJapanese);
}
break;
}
}
// and try Droid Sans Fallback as a last resort
aFontList.AppendElement("Droid Sans Fallback");
}
nsresult
gfxAndroidPlatform::GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts)
{
gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
aGenericFamily,
aListOfFonts);
return NS_OK;
}
void
gfxAndroidPlatform::GetFontList(InfallibleTArray<FontListEntry>* retValue)
{
gfxFT2FontList::PlatformFontList()->GetFontList(retValue);
}
nsresult
gfxAndroidPlatform::UpdateFontList()
{
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
return NS_OK;
}
nsresult
gfxAndroidPlatform::ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure,
bool& aAborted)
{
nsAutoString resolvedName;
if (!gfxPlatformFontList::PlatformFontList()->
ResolveFontName(aFontName, resolvedName)) {
aAborted = false;
return NS_OK;
}
aAborted = !(*aCallback)(resolvedName, aClosure);
return NS_OK;
}
nsresult
gfxAndroidPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
return NS_OK;
}
gfxPlatformFontList*
gfxAndroidPlatform::CreatePlatformFontList()
{
gfxPlatformFontList* list = new gfxFT2FontList();
if (NS_SUCCEEDED(list->InitFontList())) {
return list;
}
gfxPlatformFontList::Shutdown();
return nullptr;
}
bool
gfxAndroidPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
{
// check for strange format flags
NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
"strange font format hint set");
// accept supported formats
if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE |
gfxUserFontSet::FLAG_FORMAT_WOFF |
gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
return true;
}
// reject all other formats, known and unknown
if (aFormatFlags != 0) {
return false;
}
// no format hint set, need to look at data
return true;
}
gfxFontGroup *
gfxAndroidPlatform::CreateFontGroup(const nsAString &aFamilies,
const gfxFontStyle *aStyle,
gfxUserFontSet* aUserFontSet)
{
return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
}
FT_Library
gfxAndroidPlatform::GetFTLibrary()
{
return gPlatformFTLibrary;
}
gfxFontEntry*
gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
const uint8_t *aFontData, uint32_t aLength)
{
return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
aFontData,
aLength);
}
TemporaryRef<ScaledFont>
gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
{
NativeFont nativeFont;
if (aTarget->GetType() == BACKEND_CAIRO || aTarget->GetType() == BACKEND_SKIA) {
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
nativeFont.mFont = aFont->GetCairoScaledFont();
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
}
return nullptr;
}
bool
gfxAndroidPlatform::FontHintingEnabled()
{
// In "mobile" builds, we sometimes use non-reflow-zoom, so we
// might not want hinting. Let's see.
#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
// On android-java, we currently only use gecko to render web
// content that can always be be non-reflow-zoomed. So turn off
// hinting.
//
// XXX when gecko-android-java is used as an "app runtime", we may
// want to re-enable hinting for non-browser processes there.
return false;
#endif // MOZ_USING_ANDROID_JAVA_WIDGETS
#ifdef MOZ_WIDGET_GONK
// On B2G, the UX preference is currently to keep hinting disabled
// for all text (see bug 829523).
return false;
#endif
// Currently, we don't have any other targets, but if/when we do,
// decide how to handle them here.
NS_NOTREACHED("oops, what platform is this?");
return gfxPlatform::FontHintingEnabled();
}
bool
gfxAndroidPlatform::RequiresLinearZoom()
{
#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
// On android-java, we currently only use gecko to render web
// content that can always be be non-reflow-zoomed.
//
// XXX when gecko-android-java is used as an "app runtime", we may
// want to treat it like B2G and use linear zoom only for the web
// browser process, not other apps.
return true;
#endif
#ifdef MOZ_WIDGET_GONK
// On B2G, we need linear zoom for the browser, but otherwise prefer
// the improved glyph spacing that results from respecting the device
// pixel resolution for glyph layout (see bug 816614).
return XRE_GetProcessType() == GeckoProcessType_Content &&
ContentChild::GetSingleton()->IsForBrowser();
#endif
NS_NOTREACHED("oops, what platform is this?");
return gfxPlatform::RequiresLinearZoom();
}
int
gfxAndroidPlatform::GetScreenDepth() const
{
return mScreenDepth;
}