gfx/thebes/gfxAndroidPlatform.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/thebes/gfxAndroidPlatform.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,412 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "base/basictypes.h"
    1.11 +
    1.12 +#include "gfxAndroidPlatform.h"
    1.13 +#include "mozilla/gfx/2D.h"
    1.14 +#include "mozilla/Preferences.h"
    1.15 +
    1.16 +#include "gfx2DGlue.h"
    1.17 +#include "gfxFT2FontList.h"
    1.18 +#include "gfxImageSurface.h"
    1.19 +#include "mozilla/dom/ContentChild.h"
    1.20 +#include "nsXULAppAPI.h"
    1.21 +#include "nsIScreen.h"
    1.22 +#include "nsIScreenManager.h"
    1.23 +#include "nsILocaleService.h"
    1.24 +#include "nsServiceManagerUtils.h"
    1.25 +#include "gfxPrefs.h"
    1.26 +#include "cairo.h"
    1.27 +
    1.28 +#ifdef MOZ_WIDGET_ANDROID
    1.29 +#include "AndroidBridge.h"
    1.30 +#endif
    1.31 +
    1.32 +#ifdef MOZ_WIDGET_GONK
    1.33 +#include <cutils/properties.h>
    1.34 +#endif
    1.35 +
    1.36 +#include "ft2build.h"
    1.37 +#include FT_FREETYPE_H
    1.38 +#include FT_MODULE_H
    1.39 +
    1.40 +using namespace mozilla;
    1.41 +using namespace mozilla::dom;
    1.42 +using namespace mozilla::gfx;
    1.43 +
    1.44 +static FT_Library gPlatformFTLibrary = nullptr;
    1.45 +
    1.46 +class FreetypeReporter MOZ_FINAL : public nsIMemoryReporter,
    1.47 +                                   public CountingAllocatorBase<FreetypeReporter>
    1.48 +{
    1.49 +public:
    1.50 +    NS_DECL_ISUPPORTS
    1.51 +
    1.52 +    static void* Malloc(FT_Memory, long size)
    1.53 +    {
    1.54 +        return CountingMalloc(size);
    1.55 +    }
    1.56 +
    1.57 +    static void Free(FT_Memory, void* p)
    1.58 +    {
    1.59 +        return CountingFree(p);
    1.60 +    }
    1.61 +
    1.62 +    static void*
    1.63 +    Realloc(FT_Memory, long cur_size, long new_size, void* p)
    1.64 +    {
    1.65 +        return CountingRealloc(p, new_size);
    1.66 +    }
    1.67 +
    1.68 +    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
    1.69 +                              nsISupports* aData)
    1.70 +    {
    1.71 +        return MOZ_COLLECT_REPORT(
    1.72 +            "explicit/freetype", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
    1.73 +            "Memory used by Freetype.");
    1.74 +    }
    1.75 +};
    1.76 +
    1.77 +NS_IMPL_ISUPPORTS(FreetypeReporter, nsIMemoryReporter)
    1.78 +
    1.79 +template<> Atomic<size_t> CountingAllocatorBase<FreetypeReporter>::sAmount(0);
    1.80 +
    1.81 +static FT_MemoryRec_ sFreetypeMemoryRecord;
    1.82 +
    1.83 +gfxAndroidPlatform::gfxAndroidPlatform()
    1.84 +{
    1.85 +    // A custom allocator.  It counts allocations, enabling memory reporting.
    1.86 +    sFreetypeMemoryRecord.user    = nullptr;
    1.87 +    sFreetypeMemoryRecord.alloc   = FreetypeReporter::Malloc;
    1.88 +    sFreetypeMemoryRecord.free    = FreetypeReporter::Free;
    1.89 +    sFreetypeMemoryRecord.realloc = FreetypeReporter::Realloc;
    1.90 +
    1.91 +    // These two calls are equivalent to FT_Init_FreeType(), but allow us to
    1.92 +    // provide a custom memory allocator.
    1.93 +    FT_New_Library(&sFreetypeMemoryRecord, &gPlatformFTLibrary);
    1.94 +    FT_Add_Default_Modules(gPlatformFTLibrary);
    1.95 +
    1.96 +    RegisterStrongMemoryReporter(new FreetypeReporter());
    1.97 +
    1.98 +    nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
    1.99 +    nsCOMPtr<nsIScreen> screen;
   1.100 +    screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
   1.101 +    mScreenDepth = 24;
   1.102 +    screen->GetColorDepth(&mScreenDepth);
   1.103 +
   1.104 +    mOffscreenFormat = mScreenDepth == 16
   1.105 +                       ? gfxImageFormat::RGB16_565
   1.106 +                       : gfxImageFormat::RGB24;
   1.107 +
   1.108 +    if (gfxPrefs::AndroidRGB16Force()) {
   1.109 +        mOffscreenFormat = gfxImageFormat::RGB16_565;
   1.110 +    }
   1.111 +
   1.112 +#ifdef MOZ_WIDGET_GONK
   1.113 +    char propQemu[PROPERTY_VALUE_MAX];
   1.114 +    property_get("ro.kernel.qemu", propQemu, "");
   1.115 +    mIsInGonkEmulator = !strncmp(propQemu, "1", 1);
   1.116 +#endif
   1.117 +}
   1.118 +
   1.119 +gfxAndroidPlatform::~gfxAndroidPlatform()
   1.120 +{
   1.121 +    FT_Done_Library(gPlatformFTLibrary);
   1.122 +    gPlatformFTLibrary = nullptr;
   1.123 +}
   1.124 +
   1.125 +already_AddRefed<gfxASurface>
   1.126 +gfxAndroidPlatform::CreateOffscreenSurface(const IntSize& size,
   1.127 +                                           gfxContentType contentType)
   1.128 +{
   1.129 +    nsRefPtr<gfxASurface> newSurface;
   1.130 +    newSurface = new gfxImageSurface(ThebesIntSize(size),
   1.131 +                                     OptimalFormatForContent(contentType));
   1.132 +
   1.133 +    return newSurface.forget();
   1.134 +}
   1.135 +
   1.136 +static bool
   1.137 +IsJapaneseLocale()
   1.138 +{
   1.139 +    static bool sInitialized = false;
   1.140 +    static bool sIsJapanese = false;
   1.141 +
   1.142 +    if (!sInitialized) {
   1.143 +        sInitialized = true;
   1.144 +
   1.145 +        do { // to allow 'break' to abandon this block if a call fails
   1.146 +            nsresult rv;
   1.147 +            nsCOMPtr<nsILocaleService> ls =
   1.148 +                do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
   1.149 +            if (NS_FAILED(rv)) {
   1.150 +                break;
   1.151 +            }
   1.152 +            nsCOMPtr<nsILocale> appLocale;
   1.153 +            rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
   1.154 +            if (NS_FAILED(rv)) {
   1.155 +                break;
   1.156 +            }
   1.157 +            nsString localeStr;
   1.158 +            rv = appLocale->
   1.159 +                GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
   1.160 +            if (NS_FAILED(rv)) {
   1.161 +                break;
   1.162 +            }
   1.163 +            const nsAString& lang = nsDependentSubstring(localeStr, 0, 2);
   1.164 +            if (lang.EqualsLiteral("ja")) {
   1.165 +                sIsJapanese = true;
   1.166 +            }
   1.167 +        } while (false);
   1.168 +    }
   1.169 +
   1.170 +    return sIsJapanese;
   1.171 +}
   1.172 +
   1.173 +void
   1.174 +gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh,
   1.175 +                                           int32_t aRunScript,
   1.176 +                                           nsTArray<const char*>& aFontList)
   1.177 +{
   1.178 +    static const char kDroidSansJapanese[] = "Droid Sans Japanese";
   1.179 +    static const char kMotoyaLMaru[] = "MotoyaLMaru";
   1.180 +
   1.181 +    if (IS_IN_BMP(aCh)) {
   1.182 +        // try language-specific "Droid Sans *" fonts for certain blocks,
   1.183 +        // as most devices probably have these
   1.184 +        uint8_t block = (aCh >> 8) & 0xff;
   1.185 +        switch (block) {
   1.186 +        case 0x05:
   1.187 +            aFontList.AppendElement("Droid Sans Hebrew");
   1.188 +            aFontList.AppendElement("Droid Sans Armenian");
   1.189 +            break;
   1.190 +        case 0x06:
   1.191 +            aFontList.AppendElement("Droid Sans Arabic");
   1.192 +            break;
   1.193 +        case 0x09:
   1.194 +            aFontList.AppendElement("Droid Sans Devanagari");
   1.195 +            break;
   1.196 +        case 0x0b:
   1.197 +            aFontList.AppendElement("Droid Sans Tamil");
   1.198 +            break;
   1.199 +        case 0x0e:
   1.200 +            aFontList.AppendElement("Droid Sans Thai");
   1.201 +            break;
   1.202 +        case 0x10: case 0x2d:
   1.203 +            aFontList.AppendElement("Droid Sans Georgian");
   1.204 +            break;
   1.205 +        case 0x12: case 0x13:
   1.206 +            aFontList.AppendElement("Droid Sans Ethiopic");
   1.207 +            break;
   1.208 +        case 0xf9: case 0xfa:
   1.209 +            if (IsJapaneseLocale()) {
   1.210 +                aFontList.AppendElement(kMotoyaLMaru);
   1.211 +                aFontList.AppendElement(kDroidSansJapanese);
   1.212 +            }
   1.213 +            break;
   1.214 +        default:
   1.215 +            if (block >= 0x2e && block <= 0x9f && IsJapaneseLocale()) {
   1.216 +                aFontList.AppendElement(kMotoyaLMaru);
   1.217 +                aFontList.AppendElement(kDroidSansJapanese);
   1.218 +            }
   1.219 +            break;
   1.220 +        }
   1.221 +    }
   1.222 +    // and try Droid Sans Fallback as a last resort
   1.223 +    aFontList.AppendElement("Droid Sans Fallback");
   1.224 +}
   1.225 +
   1.226 +nsresult
   1.227 +gfxAndroidPlatform::GetFontList(nsIAtom *aLangGroup,
   1.228 +                                const nsACString& aGenericFamily,
   1.229 +                                nsTArray<nsString>& aListOfFonts)
   1.230 +{
   1.231 +    gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
   1.232 +                                                         aGenericFamily,
   1.233 +                                                         aListOfFonts);
   1.234 +    return NS_OK;
   1.235 +}
   1.236 +
   1.237 +void
   1.238 +gfxAndroidPlatform::GetFontList(InfallibleTArray<FontListEntry>* retValue)
   1.239 +{
   1.240 +    gfxFT2FontList::PlatformFontList()->GetFontList(retValue);
   1.241 +}
   1.242 +
   1.243 +nsresult
   1.244 +gfxAndroidPlatform::UpdateFontList()
   1.245 +{
   1.246 +    gfxPlatformFontList::PlatformFontList()->UpdateFontList();
   1.247 +    return NS_OK;
   1.248 +}
   1.249 +
   1.250 +nsresult
   1.251 +gfxAndroidPlatform::ResolveFontName(const nsAString& aFontName,
   1.252 +                                    FontResolverCallback aCallback,
   1.253 +                                    void *aClosure,
   1.254 +                                    bool& aAborted)
   1.255 +{
   1.256 +    nsAutoString resolvedName;
   1.257 +    if (!gfxPlatformFontList::PlatformFontList()->
   1.258 +             ResolveFontName(aFontName, resolvedName)) {
   1.259 +        aAborted = false;
   1.260 +        return NS_OK;
   1.261 +    }
   1.262 +    aAborted = !(*aCallback)(resolvedName, aClosure);
   1.263 +    return NS_OK;
   1.264 +}
   1.265 +
   1.266 +nsresult
   1.267 +gfxAndroidPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
   1.268 +{
   1.269 +    gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
   1.270 +    return NS_OK;
   1.271 +}
   1.272 +
   1.273 +gfxPlatformFontList*
   1.274 +gfxAndroidPlatform::CreatePlatformFontList()
   1.275 +{
   1.276 +    gfxPlatformFontList* list = new gfxFT2FontList();
   1.277 +    if (NS_SUCCEEDED(list->InitFontList())) {
   1.278 +        return list;
   1.279 +    }
   1.280 +    gfxPlatformFontList::Shutdown();
   1.281 +    return nullptr;
   1.282 +}
   1.283 +
   1.284 +bool
   1.285 +gfxAndroidPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
   1.286 +{
   1.287 +    // check for strange format flags
   1.288 +    NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
   1.289 +                 "strange font format hint set");
   1.290 +
   1.291 +    // accept supported formats
   1.292 +    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE |
   1.293 +                        gfxUserFontSet::FLAG_FORMAT_WOFF |
   1.294 +                        gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
   1.295 +        return true;
   1.296 +    }
   1.297 +
   1.298 +    // reject all other formats, known and unknown
   1.299 +    if (aFormatFlags != 0) {
   1.300 +        return false;
   1.301 +    }
   1.302 +
   1.303 +    // no format hint set, need to look at data
   1.304 +    return true;
   1.305 +}
   1.306 +
   1.307 +gfxFontGroup *
   1.308 +gfxAndroidPlatform::CreateFontGroup(const nsAString &aFamilies,
   1.309 +                               const gfxFontStyle *aStyle,
   1.310 +                               gfxUserFontSet* aUserFontSet)
   1.311 +{
   1.312 +    return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
   1.313 +}
   1.314 +
   1.315 +FT_Library
   1.316 +gfxAndroidPlatform::GetFTLibrary()
   1.317 +{
   1.318 +    return gPlatformFTLibrary;
   1.319 +}
   1.320 +
   1.321 +gfxFontEntry* 
   1.322 +gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
   1.323 +                                     const uint8_t *aFontData, uint32_t aLength)
   1.324 +{
   1.325 +    return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
   1.326 +                                                                     aFontData,
   1.327 +                                                                     aLength);
   1.328 +}
   1.329 +
   1.330 +gfxFontEntry*
   1.331 +gfxAndroidPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
   1.332 +                                    const nsAString& aFontName)
   1.333 +{
   1.334 +    return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry,
   1.335 +                                                                    aFontName);
   1.336 +}
   1.337 +
   1.338 +TemporaryRef<ScaledFont>
   1.339 +gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
   1.340 +{
   1.341 +    return GetScaledFontForFontWithCairoSkia(aTarget, aFont);
   1.342 +}
   1.343 +
   1.344 +bool
   1.345 +gfxAndroidPlatform::FontHintingEnabled()
   1.346 +{
   1.347 +    // In "mobile" builds, we sometimes use non-reflow-zoom, so we
   1.348 +    // might not want hinting.  Let's see.
   1.349 +
   1.350 +#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
   1.351 +    // On android-java, we currently only use gecko to render web
   1.352 +    // content that can always be be non-reflow-zoomed.  So turn off
   1.353 +    // hinting.
   1.354 +    // 
   1.355 +    // XXX when gecko-android-java is used as an "app runtime", we may
   1.356 +    // want to re-enable hinting for non-browser processes there.
   1.357 +    return false;
   1.358 +#endif //  MOZ_USING_ANDROID_JAVA_WIDGETS
   1.359 +
   1.360 +#ifdef MOZ_WIDGET_GONK
   1.361 +    // On B2G, the UX preference is currently to keep hinting disabled
   1.362 +    // for all text (see bug 829523).
   1.363 +    return false;
   1.364 +#endif
   1.365 +
   1.366 +    // Currently, we don't have any other targets, but if/when we do,
   1.367 +    // decide how to handle them here.
   1.368 +
   1.369 +    NS_NOTREACHED("oops, what platform is this?");
   1.370 +    return gfxPlatform::FontHintingEnabled();
   1.371 +}
   1.372 +
   1.373 +bool
   1.374 +gfxAndroidPlatform::RequiresLinearZoom()
   1.375 +{
   1.376 +#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
   1.377 +    // On android-java, we currently only use gecko to render web
   1.378 +    // content that can always be be non-reflow-zoomed.
   1.379 +    //
   1.380 +    // XXX when gecko-android-java is used as an "app runtime", we may
   1.381 +    // want to treat it like B2G and use linear zoom only for the web
   1.382 +    // browser process, not other apps.
   1.383 +    return true;
   1.384 +#endif
   1.385 +
   1.386 +#ifdef MOZ_WIDGET_GONK
   1.387 +    // On B2G, we need linear zoom for the browser, but otherwise prefer
   1.388 +    // the improved glyph spacing that results from respecting the device
   1.389 +    // pixel resolution for glyph layout (see bug 816614).
   1.390 +    return XRE_GetProcessType() == GeckoProcessType_Content &&
   1.391 +           ContentChild::GetSingleton()->IsForBrowser();
   1.392 +#endif
   1.393 +
   1.394 +    NS_NOTREACHED("oops, what platform is this?");
   1.395 +    return gfxPlatform::RequiresLinearZoom();
   1.396 +}
   1.397 +
   1.398 +int
   1.399 +gfxAndroidPlatform::GetScreenDepth() const
   1.400 +{
   1.401 +    return mScreenDepth;
   1.402 +}
   1.403 +
   1.404 +bool
   1.405 +gfxAndroidPlatform::UseAcceleratedSkiaCanvas()
   1.406 +{
   1.407 +#ifdef MOZ_WIDGET_ANDROID
   1.408 +    if (AndroidBridge::Bridge()->GetAPIVersion() < 11) {
   1.409 +        // It's slower than software due to not having a compositing fast path
   1.410 +        return false;
   1.411 +    }
   1.412 +#endif
   1.413 +
   1.414 +    return gfxPlatform::UseAcceleratedSkiaCanvas();
   1.415 +}

mercurial