gfx/thebes/gfxAndroidPlatform.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/Preferences.h"
    13 #include "gfx2DGlue.h"
    14 #include "gfxFT2FontList.h"
    15 #include "gfxImageSurface.h"
    16 #include "mozilla/dom/ContentChild.h"
    17 #include "nsXULAppAPI.h"
    18 #include "nsIScreen.h"
    19 #include "nsIScreenManager.h"
    20 #include "nsILocaleService.h"
    21 #include "nsServiceManagerUtils.h"
    22 #include "gfxPrefs.h"
    23 #include "cairo.h"
    25 #ifdef MOZ_WIDGET_ANDROID
    26 #include "AndroidBridge.h"
    27 #endif
    29 #ifdef MOZ_WIDGET_GONK
    30 #include <cutils/properties.h>
    31 #endif
    33 #include "ft2build.h"
    34 #include FT_FREETYPE_H
    35 #include FT_MODULE_H
    37 using namespace mozilla;
    38 using namespace mozilla::dom;
    39 using namespace mozilla::gfx;
    41 static FT_Library gPlatformFTLibrary = nullptr;
    43 class FreetypeReporter MOZ_FINAL : public nsIMemoryReporter,
    44                                    public CountingAllocatorBase<FreetypeReporter>
    45 {
    46 public:
    47     NS_DECL_ISUPPORTS
    49     static void* Malloc(FT_Memory, long size)
    50     {
    51         return CountingMalloc(size);
    52     }
    54     static void Free(FT_Memory, void* p)
    55     {
    56         return CountingFree(p);
    57     }
    59     static void*
    60     Realloc(FT_Memory, long cur_size, long new_size, void* p)
    61     {
    62         return CountingRealloc(p, new_size);
    63     }
    65     NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
    66                               nsISupports* aData)
    67     {
    68         return MOZ_COLLECT_REPORT(
    69             "explicit/freetype", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
    70             "Memory used by Freetype.");
    71     }
    72 };
    74 NS_IMPL_ISUPPORTS(FreetypeReporter, nsIMemoryReporter)
    76 template<> Atomic<size_t> CountingAllocatorBase<FreetypeReporter>::sAmount(0);
    78 static FT_MemoryRec_ sFreetypeMemoryRecord;
    80 gfxAndroidPlatform::gfxAndroidPlatform()
    81 {
    82     // A custom allocator.  It counts allocations, enabling memory reporting.
    83     sFreetypeMemoryRecord.user    = nullptr;
    84     sFreetypeMemoryRecord.alloc   = FreetypeReporter::Malloc;
    85     sFreetypeMemoryRecord.free    = FreetypeReporter::Free;
    86     sFreetypeMemoryRecord.realloc = FreetypeReporter::Realloc;
    88     // These two calls are equivalent to FT_Init_FreeType(), but allow us to
    89     // provide a custom memory allocator.
    90     FT_New_Library(&sFreetypeMemoryRecord, &gPlatformFTLibrary);
    91     FT_Add_Default_Modules(gPlatformFTLibrary);
    93     RegisterStrongMemoryReporter(new FreetypeReporter());
    95     nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
    96     nsCOMPtr<nsIScreen> screen;
    97     screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
    98     mScreenDepth = 24;
    99     screen->GetColorDepth(&mScreenDepth);
   101     mOffscreenFormat = mScreenDepth == 16
   102                        ? gfxImageFormat::RGB16_565
   103                        : gfxImageFormat::RGB24;
   105     if (gfxPrefs::AndroidRGB16Force()) {
   106         mOffscreenFormat = gfxImageFormat::RGB16_565;
   107     }
   109 #ifdef MOZ_WIDGET_GONK
   110     char propQemu[PROPERTY_VALUE_MAX];
   111     property_get("ro.kernel.qemu", propQemu, "");
   112     mIsInGonkEmulator = !strncmp(propQemu, "1", 1);
   113 #endif
   114 }
   116 gfxAndroidPlatform::~gfxAndroidPlatform()
   117 {
   118     FT_Done_Library(gPlatformFTLibrary);
   119     gPlatformFTLibrary = nullptr;
   120 }
   122 already_AddRefed<gfxASurface>
   123 gfxAndroidPlatform::CreateOffscreenSurface(const IntSize& size,
   124                                            gfxContentType contentType)
   125 {
   126     nsRefPtr<gfxASurface> newSurface;
   127     newSurface = new gfxImageSurface(ThebesIntSize(size),
   128                                      OptimalFormatForContent(contentType));
   130     return newSurface.forget();
   131 }
   133 static bool
   134 IsJapaneseLocale()
   135 {
   136     static bool sInitialized = false;
   137     static bool sIsJapanese = false;
   139     if (!sInitialized) {
   140         sInitialized = true;
   142         do { // to allow 'break' to abandon this block if a call fails
   143             nsresult rv;
   144             nsCOMPtr<nsILocaleService> ls =
   145                 do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
   146             if (NS_FAILED(rv)) {
   147                 break;
   148             }
   149             nsCOMPtr<nsILocale> appLocale;
   150             rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
   151             if (NS_FAILED(rv)) {
   152                 break;
   153             }
   154             nsString localeStr;
   155             rv = appLocale->
   156                 GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
   157             if (NS_FAILED(rv)) {
   158                 break;
   159             }
   160             const nsAString& lang = nsDependentSubstring(localeStr, 0, 2);
   161             if (lang.EqualsLiteral("ja")) {
   162                 sIsJapanese = true;
   163             }
   164         } while (false);
   165     }
   167     return sIsJapanese;
   168 }
   170 void
   171 gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh,
   172                                            int32_t aRunScript,
   173                                            nsTArray<const char*>& aFontList)
   174 {
   175     static const char kDroidSansJapanese[] = "Droid Sans Japanese";
   176     static const char kMotoyaLMaru[] = "MotoyaLMaru";
   178     if (IS_IN_BMP(aCh)) {
   179         // try language-specific "Droid Sans *" fonts for certain blocks,
   180         // as most devices probably have these
   181         uint8_t block = (aCh >> 8) & 0xff;
   182         switch (block) {
   183         case 0x05:
   184             aFontList.AppendElement("Droid Sans Hebrew");
   185             aFontList.AppendElement("Droid Sans Armenian");
   186             break;
   187         case 0x06:
   188             aFontList.AppendElement("Droid Sans Arabic");
   189             break;
   190         case 0x09:
   191             aFontList.AppendElement("Droid Sans Devanagari");
   192             break;
   193         case 0x0b:
   194             aFontList.AppendElement("Droid Sans Tamil");
   195             break;
   196         case 0x0e:
   197             aFontList.AppendElement("Droid Sans Thai");
   198             break;
   199         case 0x10: case 0x2d:
   200             aFontList.AppendElement("Droid Sans Georgian");
   201             break;
   202         case 0x12: case 0x13:
   203             aFontList.AppendElement("Droid Sans Ethiopic");
   204             break;
   205         case 0xf9: case 0xfa:
   206             if (IsJapaneseLocale()) {
   207                 aFontList.AppendElement(kMotoyaLMaru);
   208                 aFontList.AppendElement(kDroidSansJapanese);
   209             }
   210             break;
   211         default:
   212             if (block >= 0x2e && block <= 0x9f && IsJapaneseLocale()) {
   213                 aFontList.AppendElement(kMotoyaLMaru);
   214                 aFontList.AppendElement(kDroidSansJapanese);
   215             }
   216             break;
   217         }
   218     }
   219     // and try Droid Sans Fallback as a last resort
   220     aFontList.AppendElement("Droid Sans Fallback");
   221 }
   223 nsresult
   224 gfxAndroidPlatform::GetFontList(nsIAtom *aLangGroup,
   225                                 const nsACString& aGenericFamily,
   226                                 nsTArray<nsString>& aListOfFonts)
   227 {
   228     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
   229                                                          aGenericFamily,
   230                                                          aListOfFonts);
   231     return NS_OK;
   232 }
   234 void
   235 gfxAndroidPlatform::GetFontList(InfallibleTArray<FontListEntry>* retValue)
   236 {
   237     gfxFT2FontList::PlatformFontList()->GetFontList(retValue);
   238 }
   240 nsresult
   241 gfxAndroidPlatform::UpdateFontList()
   242 {
   243     gfxPlatformFontList::PlatformFontList()->UpdateFontList();
   244     return NS_OK;
   245 }
   247 nsresult
   248 gfxAndroidPlatform::ResolveFontName(const nsAString& aFontName,
   249                                     FontResolverCallback aCallback,
   250                                     void *aClosure,
   251                                     bool& aAborted)
   252 {
   253     nsAutoString resolvedName;
   254     if (!gfxPlatformFontList::PlatformFontList()->
   255              ResolveFontName(aFontName, resolvedName)) {
   256         aAborted = false;
   257         return NS_OK;
   258     }
   259     aAborted = !(*aCallback)(resolvedName, aClosure);
   260     return NS_OK;
   261 }
   263 nsresult
   264 gfxAndroidPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
   265 {
   266     gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
   267     return NS_OK;
   268 }
   270 gfxPlatformFontList*
   271 gfxAndroidPlatform::CreatePlatformFontList()
   272 {
   273     gfxPlatformFontList* list = new gfxFT2FontList();
   274     if (NS_SUCCEEDED(list->InitFontList())) {
   275         return list;
   276     }
   277     gfxPlatformFontList::Shutdown();
   278     return nullptr;
   279 }
   281 bool
   282 gfxAndroidPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
   283 {
   284     // check for strange format flags
   285     NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
   286                  "strange font format hint set");
   288     // accept supported formats
   289     if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE |
   290                         gfxUserFontSet::FLAG_FORMAT_WOFF |
   291                         gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
   292         return true;
   293     }
   295     // reject all other formats, known and unknown
   296     if (aFormatFlags != 0) {
   297         return false;
   298     }
   300     // no format hint set, need to look at data
   301     return true;
   302 }
   304 gfxFontGroup *
   305 gfxAndroidPlatform::CreateFontGroup(const nsAString &aFamilies,
   306                                const gfxFontStyle *aStyle,
   307                                gfxUserFontSet* aUserFontSet)
   308 {
   309     return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
   310 }
   312 FT_Library
   313 gfxAndroidPlatform::GetFTLibrary()
   314 {
   315     return gPlatformFTLibrary;
   316 }
   318 gfxFontEntry* 
   319 gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
   320                                      const uint8_t *aFontData, uint32_t aLength)
   321 {
   322     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
   323                                                                      aFontData,
   324                                                                      aLength);
   325 }
   327 gfxFontEntry*
   328 gfxAndroidPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
   329                                     const nsAString& aFontName)
   330 {
   331     return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry,
   332                                                                     aFontName);
   333 }
   335 TemporaryRef<ScaledFont>
   336 gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
   337 {
   338     return GetScaledFontForFontWithCairoSkia(aTarget, aFont);
   339 }
   341 bool
   342 gfxAndroidPlatform::FontHintingEnabled()
   343 {
   344     // In "mobile" builds, we sometimes use non-reflow-zoom, so we
   345     // might not want hinting.  Let's see.
   347 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
   348     // On android-java, we currently only use gecko to render web
   349     // content that can always be be non-reflow-zoomed.  So turn off
   350     // hinting.
   351     // 
   352     // XXX when gecko-android-java is used as an "app runtime", we may
   353     // want to re-enable hinting for non-browser processes there.
   354     return false;
   355 #endif //  MOZ_USING_ANDROID_JAVA_WIDGETS
   357 #ifdef MOZ_WIDGET_GONK
   358     // On B2G, the UX preference is currently to keep hinting disabled
   359     // for all text (see bug 829523).
   360     return false;
   361 #endif
   363     // Currently, we don't have any other targets, but if/when we do,
   364     // decide how to handle them here.
   366     NS_NOTREACHED("oops, what platform is this?");
   367     return gfxPlatform::FontHintingEnabled();
   368 }
   370 bool
   371 gfxAndroidPlatform::RequiresLinearZoom()
   372 {
   373 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
   374     // On android-java, we currently only use gecko to render web
   375     // content that can always be be non-reflow-zoomed.
   376     //
   377     // XXX when gecko-android-java is used as an "app runtime", we may
   378     // want to treat it like B2G and use linear zoom only for the web
   379     // browser process, not other apps.
   380     return true;
   381 #endif
   383 #ifdef MOZ_WIDGET_GONK
   384     // On B2G, we need linear zoom for the browser, but otherwise prefer
   385     // the improved glyph spacing that results from respecting the device
   386     // pixel resolution for glyph layout (see bug 816614).
   387     return XRE_GetProcessType() == GeckoProcessType_Content &&
   388            ContentChild::GetSingleton()->IsForBrowser();
   389 #endif
   391     NS_NOTREACHED("oops, what platform is this?");
   392     return gfxPlatform::RequiresLinearZoom();
   393 }
   395 int
   396 gfxAndroidPlatform::GetScreenDepth() const
   397 {
   398     return mScreenDepth;
   399 }
   401 bool
   402 gfxAndroidPlatform::UseAcceleratedSkiaCanvas()
   403 {
   404 #ifdef MOZ_WIDGET_ANDROID
   405     if (AndroidBridge::Bridge()->GetAPIVersion() < 11) {
   406         // It's slower than software due to not having a compositing fast path
   407         return false;
   408     }
   409 #endif
   411     return gfxPlatform::UseAcceleratedSkiaCanvas();
   412 }

mercurial