LCOV - code coverage report
Current view: directory - gfx/thebes - gfxPlatform.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 550 102 18.5 %
Date: 2012-06-02 Functions: 62 19 30.6 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Foundation code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #ifdef MOZ_LOGGING
      39                 : #define FORCE_PR_LOG /* Allow logging in the release build */
      40                 : #endif
      41                 : #include "prlog.h"
      42                 : 
      43                 : #include "gfxPlatform.h"
      44                 : 
      45                 : #if defined(XP_WIN)
      46                 : #include "gfxWindowsPlatform.h"
      47                 : #include "gfxD2DSurface.h"
      48                 : #elif defined(XP_MACOSX)
      49                 : #include "gfxPlatformMac.h"
      50                 : #elif defined(MOZ_WIDGET_GTK2)
      51                 : #include "gfxPlatformGtk.h"
      52                 : #elif defined(MOZ_WIDGET_QT)
      53                 : #include "gfxQtPlatform.h"
      54                 : #elif defined(XP_OS2)
      55                 : #include "gfxOS2Platform.h"
      56                 : #elif defined(ANDROID)
      57                 : #include "gfxAndroidPlatform.h"
      58                 : #endif
      59                 : 
      60                 : #include "gfxAtoms.h"
      61                 : #include "gfxPlatformFontList.h"
      62                 : #include "gfxContext.h"
      63                 : #include "gfxImageSurface.h"
      64                 : #include "gfxUserFontSet.h"
      65                 : #include "nsUnicodeProperties.h"
      66                 : #include "harfbuzz/hb-unicode.h"
      67                 : #ifdef MOZ_GRAPHITE
      68                 : #include "gfxGraphiteShaper.h"
      69                 : #endif
      70                 : 
      71                 : #include "nsUnicodeRange.h"
      72                 : #include "nsServiceManagerUtils.h"
      73                 : #include "nsTArray.h"
      74                 : #include "nsUnicharUtilCIID.h"
      75                 : #include "nsILocaleService.h"
      76                 : 
      77                 : #include "nsWeakReference.h"
      78                 : 
      79                 : #include "cairo.h"
      80                 : #include "qcms.h"
      81                 : 
      82                 : #include "plstr.h"
      83                 : #include "nsCRT.h"
      84                 : #include "GLContext.h"
      85                 : #include "GLContextProvider.h"
      86                 : 
      87                 : #include "mozilla/FunctionTimer.h"
      88                 : #include "mozilla/Preferences.h"
      89                 : 
      90                 : #include "nsIGfxInfo.h"
      91                 : 
      92                 : using namespace mozilla;
      93                 : 
      94                 : gfxPlatform *gPlatform = nsnull;
      95                 : static bool gEverInitialized = false;
      96                 : 
      97                 : // These two may point to the same profile
      98                 : static qcms_profile *gCMSOutputProfile = nsnull;
      99                 : static qcms_profile *gCMSsRGBProfile = nsnull;
     100                 : 
     101                 : static qcms_transform *gCMSRGBTransform = nsnull;
     102                 : static qcms_transform *gCMSInverseRGBTransform = nsnull;
     103                 : static qcms_transform *gCMSRGBATransform = nsnull;
     104                 : 
     105                 : static bool gCMSInitialized = false;
     106                 : static eCMSMode gCMSMode = eCMSMode_Off;
     107                 : static int gCMSIntent = -2;
     108                 : 
     109                 : static void ShutdownCMS();
     110                 : static void MigratePrefs();
     111                 : 
     112                 : #include "mozilla/gfx/2D.h"
     113                 : using namespace mozilla::gfx;
     114                 : 
     115                 : // logs shared across gfx
     116                 : #ifdef PR_LOGGING
     117                 : static PRLogModuleInfo *sFontlistLog = nsnull;
     118                 : static PRLogModuleInfo *sFontInitLog = nsnull;
     119                 : static PRLogModuleInfo *sTextrunLog = nsnull;
     120                 : static PRLogModuleInfo *sTextrunuiLog = nsnull;
     121                 : static PRLogModuleInfo *sCmapDataLog = nsnull;
     122                 : #endif
     123                 : 
     124                 : /* Class to listen for pref changes so that chrome code can dynamically
     125                 :    force sRGB as an output profile. See Bug #452125. */
     126                 : class SRGBOverrideObserver : public nsIObserver,
     127                 :                              public nsSupportsWeakReference
     128               6 : {
     129                 : public:
     130                 :     NS_DECL_ISUPPORTS
     131                 :     NS_DECL_NSIOBSERVER
     132                 : };
     133                 : 
     134              45 : NS_IMPL_ISUPPORTS2(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
     135                 : 
     136                 : NS_IMETHODIMP
     137               0 : SRGBOverrideObserver::Observe(nsISupports *aSubject,
     138                 :                               const char *aTopic,
     139                 :                               const PRUnichar *someData)
     140                 : {
     141               0 :     NS_ASSERTION(NS_strcmp(someData,
     142                 :                    NS_LITERAL_STRING("gfx.color_mangement.force_srgb").get()),
     143                 :                  "Restarting CMS on wrong pref!");
     144               0 :     ShutdownCMS();
     145               0 :     return NS_OK;
     146                 : }
     147                 : 
     148                 : #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
     149                 : #define GFX_DOWNLOADABLE_FONTS_SANITIZE "gfx.downloadable_fonts.sanitize"
     150                 : 
     151                 : #define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
     152                 : #define HARFBUZZ_SCRIPTS_DEFAULT  mozilla::unicode::SHAPING_DEFAULT
     153                 : #define GFX_PREF_FALLBACK_USE_CMAPS  "gfx.font_rendering.fallback.always_use_cmaps"
     154                 : 
     155                 : #ifdef MOZ_GRAPHITE
     156                 : #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
     157                 : #endif
     158                 : 
     159                 : #define BIDI_NUMERAL_PREF "bidi.numeral"
     160                 : 
     161                 : static const char* kObservedPrefs[] = {
     162                 :     "gfx.downloadable_fonts.",
     163                 :     "gfx.font_rendering.",
     164                 :     "bidi.numeral",
     165                 :     nsnull
     166                 : };
     167                 : 
     168                 : class FontPrefsObserver : public nsIObserver
     169               3 : {
     170                 : public:
     171                 :     NS_DECL_ISUPPORTS
     172                 :     NS_DECL_NSIOBSERVER
     173                 : };
     174                 : 
     175             108 : NS_IMPL_ISUPPORTS1(FontPrefsObserver, nsIObserver)
     176                 : 
     177                 : NS_IMETHODIMP
     178               0 : FontPrefsObserver::Observe(nsISupports *aSubject,
     179                 :                            const char *aTopic,
     180                 :                            const PRUnichar *someData)
     181                 : {
     182               0 :     if (!someData) {
     183               0 :         NS_ERROR("font pref observer code broken");
     184               0 :         return NS_ERROR_UNEXPECTED;
     185                 :     }
     186               0 :     NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
     187               0 :     gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
     188                 : 
     189               0 :     return NS_OK;
     190                 : }
     191                 : 
     192                 : 
     193                 : 
     194                 : // this needs to match the list of pref font.default.xx entries listed in all.js!
     195                 : // the order *must* match the order in eFontPrefLang
     196                 : static const char *gPrefLangNames[] = {
     197                 :     "x-western",
     198                 :     "x-central-euro",
     199                 :     "ja",
     200                 :     "zh-TW",
     201                 :     "zh-CN",
     202                 :     "zh-HK",
     203                 :     "ko",
     204                 :     "x-cyrillic",
     205                 :     "x-baltic",
     206                 :     "el",
     207                 :     "tr",
     208                 :     "th",
     209                 :     "he",
     210                 :     "ar",
     211                 :     "x-devanagari",
     212                 :     "x-tamil",
     213                 :     "x-armn",
     214                 :     "x-beng",
     215                 :     "x-cans",
     216                 :     "x-ethi",
     217                 :     "x-geor",
     218                 :     "x-gujr",
     219                 :     "x-guru",
     220                 :     "x-khmr",
     221                 :     "x-mlym",
     222                 :     "x-orya",
     223                 :     "x-telu",
     224                 :     "x-knda",
     225                 :     "x-sinh",
     226                 :     "x-tibt",
     227                 :     "x-unicode",
     228                 :     "x-user-def"
     229                 : };
     230                 : 
     231               3 : gfxPlatform::gfxPlatform()
     232               3 :   : mAzureBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
     233                 : {
     234               3 :     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     235               3 :     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     236               3 :     mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     237               3 :     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
     238                 : 
     239                 : #ifdef MOZ_GRAPHITE
     240               3 :     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
     241                 : #endif
     242               3 :     mBidiNumeralOption = UNINITIALIZED_VALUE;
     243                 : 
     244               3 :     if (Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
     245               0 :         mPreferredDrawTargetBackend = BACKEND_SKIA;
     246                 :     } else {
     247               3 :         mPreferredDrawTargetBackend = BACKEND_NONE;
     248                 :     }
     249               3 : }
     250                 : 
     251                 : gfxPlatform*
     252              14 : gfxPlatform::GetPlatform()
     253                 : {
     254              14 :     if (!gPlatform) {
     255               3 :         Init();
     256                 :     }
     257              14 :     return gPlatform;
     258                 : }
     259                 : 
     260                 : void
     261               3 : gfxPlatform::Init()
     262                 : {
     263               3 :     if (gEverInitialized) {
     264               0 :         NS_RUNTIMEABORT("Already started???");
     265                 :     }
     266               3 :     gEverInitialized = true;
     267                 : 
     268               3 :     gfxAtoms::RegisterAtoms();
     269                 : 
     270                 : #ifdef PR_LOGGING
     271               3 :     sFontlistLog = PR_NewLogModule("fontlist");;
     272               3 :     sFontInitLog = PR_NewLogModule("fontinit");;
     273               3 :     sTextrunLog = PR_NewLogModule("textrun");;
     274               3 :     sTextrunuiLog = PR_NewLogModule("textrunui");;
     275               3 :     sCmapDataLog = PR_NewLogModule("cmapdata");;
     276                 : #endif
     277                 : 
     278                 : 
     279                 :     /* Initialize the GfxInfo service.
     280                 :      * Note: we can't call functions on GfxInfo that depend
     281                 :      * on gPlatform until after it has been initialized
     282                 :      * below. GfxInfo initialization annotates our
     283                 :      * crash reports so we want to do it before
     284                 :      * we try to load any drivers and do device detection
     285                 :      * incase that code crashes. See bug #591561. */
     286               6 :     nsCOMPtr<nsIGfxInfo> gfxInfo;
     287                 :     /* this currently will only succeed on Windows */
     288               3 :     gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     289                 : 
     290                 : #if defined(XP_WIN)
     291                 :     gPlatform = new gfxWindowsPlatform;
     292                 : #elif defined(XP_MACOSX)
     293                 :     gPlatform = new gfxPlatformMac;
     294                 : #elif defined(MOZ_WIDGET_GTK2)
     295               3 :     gPlatform = new gfxPlatformGtk;
     296                 : #elif defined(MOZ_WIDGET_QT)
     297                 :     gPlatform = new gfxQtPlatform;
     298                 : #elif defined(XP_OS2)
     299                 :     gPlatform = new gfxOS2Platform;
     300                 : #elif defined(ANDROID)
     301                 :     gPlatform = new gfxAndroidPlatform;
     302                 : #else
     303                 :     #error "No gfxPlatform implementation available"
     304                 : #endif
     305                 : 
     306                 : #ifdef DEBUG
     307               3 :     mozilla::gl::GLContext::StaticInit();
     308                 : #endif
     309                 : 
     310                 :     nsresult rv;
     311                 : 
     312                 : #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
     313                 :     rv = gfxPlatformFontList::Init();
     314                 :     if (NS_FAILED(rv)) {
     315                 :         NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
     316                 :     }
     317                 : #endif
     318                 : 
     319                 :     gPlatform->mScreenReferenceSurface =
     320                 :         gPlatform->CreateOffscreenSurface(gfxIntSize(1,1),
     321               3 :                                           gfxASurface::CONTENT_COLOR_ALPHA);
     322               3 :     if (!gPlatform->mScreenReferenceSurface) {
     323               0 :         NS_RUNTIMEABORT("Could not initialize mScreenReferenceSurface");
     324                 :     }
     325                 : 
     326               3 :     rv = gfxFontCache::Init();
     327               3 :     if (NS_FAILED(rv)) {
     328               0 :         NS_RUNTIMEABORT("Could not initialize gfxFontCache");
     329                 :     }
     330                 : 
     331                 :     /* Pref migration hook. */
     332               3 :     MigratePrefs();
     333                 : 
     334                 :     /* Create and register our CMS Override observer. */
     335               3 :     gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
     336               3 :     Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, "gfx.color_management.force_srgb");
     337                 : 
     338               3 :     gPlatform->mFontPrefsObserver = new FontPrefsObserver();
     339               3 :     Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
     340                 : 
     341                 :     // Force registration of the gfx component, thus arranging for
     342                 :     // ::Shutdown to be called.
     343                 :     nsCOMPtr<nsISupports> forceReg
     344               3 :         = do_CreateInstance("@mozilla.org/gfx/init;1");
     345               3 : }
     346                 : 
     347                 : void
     348               4 : gfxPlatform::Shutdown()
     349                 : {
     350                 :     // These may be called before the corresponding subsystems have actually
     351                 :     // started up. That's OK, they can handle it.
     352               4 :     gfxFontCache::Shutdown();
     353               4 :     gfxFontGroup::Shutdown();
     354                 : #ifdef MOZ_GRAPHITE
     355               4 :     gfxGraphiteShaper::Shutdown();
     356                 : #endif
     357                 : #if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
     358                 :     gfxPlatformFontList::Shutdown();
     359                 : #endif
     360                 : 
     361                 :     // Free the various non-null transforms and loaded profiles
     362               4 :     ShutdownCMS();
     363                 : 
     364                 :     // In some cases, gPlatform may not be created but Shutdown() called,
     365                 :     // e.g., during xpcshell tests.
     366               4 :     if (gPlatform) {
     367                 :         /* Unregister our CMS Override callback. */
     368               3 :         NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
     369               3 :         Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, "gfx.color_management.force_srgb");
     370               3 :         gPlatform->mSRGBOverrideObserver = nsnull;
     371                 : 
     372               3 :         NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
     373               3 :         Preferences::RemoveObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
     374               3 :         gPlatform->mFontPrefsObserver = nsnull;
     375                 :     }
     376                 : 
     377                 :     // Shut down the default GL context provider.
     378               4 :     mozilla::gl::GLContextProvider::Shutdown();
     379                 : 
     380                 :     // We always have OSMesa at least potentially available; shut it down too.
     381               4 :     mozilla::gl::GLContextProviderOSMesa::Shutdown();
     382                 : 
     383                 : #if defined(XP_WIN)
     384                 :     // The above shutdown calls operate on the available context providers on
     385                 :     // most platforms.  Windows is a "special snowflake", though, and has three
     386                 :     // context providers available, so we have to shut all of them down.
     387                 :     // We should only support the default GL provider on Windows; then, this
     388                 :     // could go away. Unfortunately, we currently support WGL (the default) for
     389                 :     // WebGL on Optimus.
     390                 :     mozilla::gl::GLContextProviderEGL::Shutdown();
     391                 : #endif
     392                 : 
     393               4 :     delete gPlatform;
     394               4 :     gPlatform = nsnull;
     395               4 : }
     396                 : 
     397               6 : gfxPlatform::~gfxPlatform()
     398                 : {
     399                 :     // The cairo folks think we should only clean up in debug builds,
     400                 :     // but we're generally in the habit of trying to shut down as
     401                 :     // cleanly as possible even in production code, so call this
     402                 :     // cairo_debug_* function unconditionally.
     403                 :     //
     404                 :     // because cairo can assert and thus crash on shutdown, don't do this in release builds
     405                 : #if MOZ_TREE_CAIRO && (defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC))
     406               3 :     cairo_debug_reset_static_data();
     407                 : #endif
     408                 : 
     409                 : #if 0
     410                 :     // It would be nice to do this (although it might need to be after
     411                 :     // the cairo shutdown that happens in ~gfxPlatform).  It even looks
     412                 :     // idempotent.  But it has fatal assertions that fire if stuff is
     413                 :     // leaked, and we hit them.
     414                 :     FcFini();
     415                 : #endif
     416               6 : }
     417                 : 
     418                 : already_AddRefed<gfxASurface>
     419              14 : gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
     420                 :                            gfxASurface::gfxImageFormat format)
     421                 : {
     422              14 :     const gfxIntSize& surfaceSize = aSurface->GetSize();
     423                 : 
     424                 : #ifdef XP_WIN
     425                 :     if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == 
     426                 :         gfxWindowsPlatform::RENDER_DIRECT2D) {
     427                 :         return nsnull;
     428                 :     }
     429                 : #endif
     430              28 :     nsRefPtr<gfxASurface> optSurface = CreateOffscreenSurface(surfaceSize, gfxASurface::ContentFromFormat(format));
     431              14 :     if (!optSurface || optSurface->CairoStatus() != 0)
     432               0 :         return nsnull;
     433                 : 
     434              28 :     gfxContext tmpCtx(optSurface);
     435              14 :     tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
     436              14 :     tmpCtx.SetSource(aSurface);
     437              14 :     tmpCtx.Paint();
     438                 : 
     439              14 :     gfxASurface *ret = optSurface;
     440              14 :     NS_ADDREF(ret);
     441              14 :     return ret;
     442                 : }
     443                 : 
     444                 : cairo_user_data_key_t kDrawTarget;
     445                 : 
     446                 : RefPtr<DrawTarget>
     447               0 : gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
     448                 : {
     449               0 :   RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface());
     450               0 :   aSurface->SetData(&kDrawTarget, drawTarget, NULL);
     451                 :   return drawTarget;
     452                 : }
     453                 : 
     454                 : cairo_user_data_key_t kSourceSurface;
     455                 : 
     456               0 : void SourceBufferDestroy(void *srcBuffer)
     457                 : {
     458               0 :   static_cast<SourceSurface*>(srcBuffer)->Release();
     459               0 : }
     460                 : 
     461               0 : void SourceSnapshotDetached(cairo_surface_t *nullSurf)
     462                 : {
     463                 :   gfxImageSurface* origSurf =
     464               0 :     static_cast<gfxImageSurface*>(cairo_surface_get_user_data(nullSurf, &kSourceSurface));
     465                 : 
     466               0 :   origSurf->SetData(&kSourceSurface, NULL, NULL);
     467               0 : }
     468                 : 
     469                 : RefPtr<SourceSurface>
     470               0 : gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
     471                 : {
     472               0 :   void *userData = aSurface->GetData(&kSourceSurface);
     473                 : 
     474               0 :   if (userData) {
     475               0 :     return static_cast<SourceSurface*>(userData);
     476                 :   }
     477                 : 
     478                 :   SurfaceFormat format;
     479               0 :   if (aSurface->GetContentType() == gfxASurface::CONTENT_ALPHA) {
     480               0 :     format = FORMAT_A8;
     481               0 :   } else if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR) {
     482               0 :     format = FORMAT_B8G8R8X8;
     483                 :   } else {
     484               0 :     format = FORMAT_B8G8R8A8;
     485                 :   }
     486                 : 
     487               0 :   RefPtr<SourceSurface> srcBuffer;
     488                 : 
     489                 : #ifdef XP_WIN
     490                 :   if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
     491                 :     NativeSurface surf;
     492                 :     surf.mFormat = format;
     493                 :     surf.mType = NATIVE_SURFACE_D3D10_TEXTURE;
     494                 :     surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
     495                 :     mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
     496                 :     if (dt) {
     497                 :       dt->Flush();
     498                 :     }
     499                 :     srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
     500                 :   }
     501                 : #endif
     502                 : 
     503               0 :   if (!srcBuffer) {
     504               0 :     nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
     505                 : 
     506               0 :     if (!imgSurface) {
     507               0 :       imgSurface = new gfxImageSurface(aSurface->GetSize(), gfxASurface::FormatFromContent(aSurface->GetContentType()));
     508               0 :       nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
     509               0 :       ctx->SetSource(aSurface);
     510               0 :       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
     511               0 :       ctx->Paint();
     512                 :     }
     513                 : 
     514               0 :     gfxImageFormat cairoFormat = imgSurface->Format();
     515               0 :     switch(cairoFormat) {
     516                 :       case gfxASurface::ImageFormatARGB32:
     517               0 :         format = FORMAT_B8G8R8A8;
     518               0 :         break;
     519                 :       case gfxASurface::ImageFormatRGB24:
     520               0 :         format = FORMAT_B8G8R8X8;
     521               0 :         break;
     522                 :       case gfxASurface::ImageFormatA8:
     523               0 :         format = FORMAT_A8;
     524               0 :         break;
     525                 :       case gfxASurface::ImageFormatRGB16_565:
     526               0 :         format = FORMAT_R5G6B5;
     527               0 :         break;
     528                 :       default:
     529               0 :         NS_RUNTIMEABORT("Invalid surface format!");
     530                 :     }
     531                 : 
     532                 :     srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
     533               0 :                                                      IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height),
     534                 :                                                      imgSurface->Stride(),
     535               0 :                                                      format);
     536                 : 
     537                 :     cairo_surface_t *nullSurf =
     538               0 :         cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
     539                 :     cairo_surface_set_user_data(nullSurf,
     540                 :                                 &kSourceSurface,
     541                 :                                 imgSurface,
     542               0 :                                 NULL);
     543               0 :     cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
     544               0 :     cairo_surface_destroy(nullSurf);
     545                 :   }
     546                 : 
     547               0 :   srcBuffer->AddRef();
     548               0 :   aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
     549                 : 
     550               0 :   return srcBuffer;
     551                 : }
     552                 : 
     553                 : RefPtr<ScaledFont>
     554               0 : gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
     555                 : {
     556                 :   NativeFont nativeFont;
     557               0 :   nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
     558               0 :   nativeFont.mFont = aFont;
     559                 :   RefPtr<ScaledFont> scaledFont =
     560                 :     Factory::CreateScaledFontForNativeFont(nativeFont,
     561               0 :                                            aFont->GetAdjustedSize());
     562                 :   return scaledFont;
     563                 : }
     564                 : 
     565                 : cairo_user_data_key_t kDrawSourceSurface;
     566                 : static void
     567               0 : DataSourceSurfaceDestroy(void *dataSourceSurface)
     568                 : {
     569               0 :   static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
     570               0 : }
     571                 : 
     572                 : UserDataKey kThebesSurfaceKey;
     573                 : void
     574               0 : DestroyThebesSurface(void *data)
     575                 : {
     576               0 :   gfxASurface *surface = static_cast<gfxASurface*>(data);
     577               0 :   surface->Release();
     578               0 : }
     579                 : 
     580                 : already_AddRefed<gfxASurface>
     581               0 : gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
     582                 : {
     583                 :   // If we have already created a thebes surface, we can just return it.
     584               0 :   void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
     585               0 :   if (surface) {
     586               0 :     nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
     587               0 :     return surf.forget();
     588                 :   }
     589                 : 
     590               0 :   nsRefPtr<gfxASurface> surf;
     591               0 :   if (aTarget->GetType() == BACKEND_CAIRO) {
     592                 :     cairo_surface_t* csurf =
     593               0 :       static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
     594               0 :     surf = gfxASurface::Wrap(csurf);
     595                 :   } else {
     596                 :     // The semantics of this part of the function are sort of weird. If we
     597                 :     // don't have direct support for the backend, we snapshot the first time
     598                 :     // and then return the snapshotted surface for the lifetime of the draw
     599                 :     // target. Sometimes it seems like this works out, but it seems like it
     600                 :     // might result in no updates ever.
     601               0 :     RefPtr<SourceSurface> source = aTarget->Snapshot();
     602               0 :     RefPtr<DataSourceSurface> data = source->GetDataSurface();
     603                 : 
     604               0 :     if (!data) {
     605               0 :       return NULL;
     606                 :     }
     607                 : 
     608               0 :     IntSize size = data->GetSize();
     609               0 :     gfxASurface::gfxImageFormat format = gfxASurface::FormatFromContent(ContentForFormat(data->GetFormat()));
     610                 : 
     611                 :     surf =
     612               0 :       new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
     613               0 :                           data->Stride(), format);
     614                 : 
     615               0 :     surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
     616                 :   }
     617                 : 
     618                 :   // add a reference to be held by the drawTarget
     619                 :   // careful, the reference graph is getting complicated here
     620               0 :   surf->AddRef();
     621               0 :   aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
     622                 : 
     623               0 :   return surf.forget();
     624                 : }
     625                 : 
     626                 : RefPtr<DrawTarget>
     627               0 : gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
     628                 : {
     629                 :   BackendType backend;
     630               0 :   if (!SupportsAzure(backend)) {
     631               0 :     return NULL;
     632                 :   }
     633                 : 
     634                 :   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
     635                 :   // create the best offscreen surface for the current system and situation. We
     636                 :   // can easily take advantage of this for the Cairo backend, so that's what we
     637                 :   // do.
     638                 :   // mozilla::gfx::Factory can get away without having all this knowledge for
     639                 :   // now, but this might need to change in the future (using
     640                 :   // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
     641                 :   // backends).
     642               0 :   if (backend == BACKEND_CAIRO) {
     643                 :     nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
     644               0 :                                                         ContentForFormat(aFormat));
     645                 : 
     646               0 :     return CreateDrawTargetForSurface(surf);
     647                 :   } else {
     648               0 :     return Factory::CreateDrawTarget(backend, aSize, aFormat);
     649                 :   }
     650                 : }
     651                 : 
     652                 : nsresult
     653               0 : gfxPlatform::GetFontList(nsIAtom *aLangGroup,
     654                 :                          const nsACString& aGenericFamily,
     655                 :                          nsTArray<nsString>& aListOfFonts)
     656                 : {
     657               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     658                 : }
     659                 : 
     660                 : nsresult
     661               0 : gfxPlatform::UpdateFontList()
     662                 : {
     663               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     664                 : }
     665                 : 
     666                 : bool
     667               0 : gfxPlatform::DownloadableFontsEnabled()
     668                 : {
     669               0 :     if (mAllowDownloadableFonts == UNINITIALIZED_VALUE) {
     670                 :         mAllowDownloadableFonts =
     671               0 :             Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
     672                 :     }
     673                 : 
     674               0 :     return mAllowDownloadableFonts;
     675                 : }
     676                 : 
     677                 : bool
     678               0 : gfxPlatform::SanitizeDownloadedFonts()
     679                 : {
     680               0 :     if (mDownloadableFontsSanitize == UNINITIALIZED_VALUE) {
     681                 :         mDownloadableFontsSanitize =
     682               0 :             Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_SANITIZE, true);
     683                 :     }
     684                 : 
     685               0 :     return mDownloadableFontsSanitize;
     686                 : }
     687                 : 
     688                 : bool
     689               0 : gfxPlatform::UseCmapsDuringSystemFallback()
     690                 : {
     691               0 :     if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
     692                 :         mFallbackUsesCmaps =
     693               0 :             Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
     694                 :     }
     695                 : 
     696               0 :     return mFallbackUsesCmaps;
     697                 : }
     698                 : 
     699                 : #ifdef MOZ_GRAPHITE
     700                 : bool
     701               0 : gfxPlatform::UseGraphiteShaping()
     702                 : {
     703               0 :     if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
     704                 :         mGraphiteShapingEnabled =
     705               0 :             Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
     706                 :     }
     707                 : 
     708               0 :     return mGraphiteShapingEnabled;
     709                 : }
     710                 : #endif
     711                 : 
     712                 : bool
     713               0 : gfxPlatform::UseHarfBuzzForScript(PRInt32 aScriptCode)
     714                 : {
     715               0 :     if (mUseHarfBuzzScripts == UNINITIALIZED_VALUE) {
     716               0 :         mUseHarfBuzzScripts = Preferences::GetInt(GFX_PREF_HARFBUZZ_SCRIPTS, HARFBUZZ_SCRIPTS_DEFAULT);
     717                 :     }
     718                 : 
     719               0 :     PRInt32 shapingType = mozilla::unicode::ScriptShapingType(aScriptCode);
     720                 : 
     721               0 :     return (mUseHarfBuzzScripts & shapingType) != 0;
     722                 : }
     723                 : 
     724                 : gfxFontEntry*
     725               0 : gfxPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
     726                 :                               const PRUint8 *aFontData,
     727                 :                               PRUint32 aLength)
     728                 : {
     729                 :     // Default implementation does not handle activating downloaded fonts;
     730                 :     // just free the data and return.
     731                 :     // Platforms that support @font-face must override this,
     732                 :     // using the data to instantiate the font, and taking responsibility
     733                 :     // for freeing it when no longer required.
     734               0 :     if (aFontData) {
     735               0 :         NS_Free((void*)aFontData);
     736                 :     }
     737               0 :     return nsnull;
     738                 : }
     739                 : 
     740                 : static void
     741               0 : AppendGenericFontFromPref(nsString& aFonts, nsIAtom *aLangGroup, const char *aGenericName)
     742                 : {
     743               0 :     NS_ENSURE_TRUE(Preferences::GetRootBranch(), );
     744                 : 
     745               0 :     nsCAutoString prefName, langGroupString;
     746                 : 
     747               0 :     aLangGroup->ToUTF8String(langGroupString);
     748                 : 
     749               0 :     nsCAutoString genericDotLang;
     750               0 :     if (aGenericName) {
     751               0 :         genericDotLang.Assign(aGenericName);
     752                 :     } else {
     753               0 :         prefName.AssignLiteral("font.default.");
     754               0 :         prefName.Append(langGroupString);
     755               0 :         genericDotLang = Preferences::GetCString(prefName.get());
     756                 :     }
     757                 : 
     758               0 :     genericDotLang.AppendLiteral(".");
     759               0 :     genericDotLang.Append(langGroupString);
     760                 : 
     761                 :     // fetch font.name.xxx value                   
     762               0 :     prefName.AssignLiteral("font.name.");
     763               0 :     prefName.Append(genericDotLang);
     764               0 :     nsAdoptingString nameValue = Preferences::GetString(prefName.get());
     765               0 :     if (nameValue) {
     766               0 :         if (!aFonts.IsEmpty())
     767               0 :             aFonts.AppendLiteral(", ");
     768               0 :         aFonts += nameValue;
     769                 :     }
     770                 : 
     771                 :     // fetch font.name-list.xxx value                   
     772               0 :     prefName.AssignLiteral("font.name-list.");
     773               0 :     prefName.Append(genericDotLang);
     774               0 :     nsAdoptingString nameListValue = Preferences::GetString(prefName.get());
     775               0 :     if (nameListValue && !nameListValue.Equals(nameValue)) {
     776               0 :         if (!aFonts.IsEmpty())
     777               0 :             aFonts.AppendLiteral(", ");
     778               0 :         aFonts += nameListValue;
     779                 :     }
     780                 : }
     781                 : 
     782                 : void
     783               0 : gfxPlatform::GetPrefFonts(nsIAtom *aLanguage, nsString& aFonts, bool aAppendUnicode)
     784                 : {
     785               0 :     aFonts.Truncate();
     786                 : 
     787               0 :     AppendGenericFontFromPref(aFonts, aLanguage, nsnull);
     788               0 :     if (aAppendUnicode)
     789               0 :         AppendGenericFontFromPref(aFonts, gfxAtoms::x_unicode, nsnull);
     790               0 : }
     791                 : 
     792               0 : bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], PRUint32 aLangArrayLen, PrefFontCallback aCallback,
     793                 :                                     void *aClosure)
     794                 : {
     795               0 :     NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
     796                 : 
     797                 :     PRUint32    i;
     798               0 :     for (i = 0; i < aLangArrayLen; i++) {
     799               0 :         eFontPrefLang prefLang = aLangArray[i];
     800               0 :         const char *langGroup = GetPrefLangName(prefLang);
     801                 :         
     802               0 :         nsCAutoString prefName;
     803                 :     
     804               0 :         prefName.AssignLiteral("font.default.");
     805               0 :         prefName.Append(langGroup);
     806               0 :         nsAdoptingCString genericDotLang = Preferences::GetCString(prefName.get());
     807                 :     
     808               0 :         genericDotLang.AppendLiteral(".");
     809               0 :         genericDotLang.Append(langGroup);
     810                 :     
     811                 :         // fetch font.name.xxx value                   
     812               0 :         prefName.AssignLiteral("font.name.");
     813               0 :         prefName.Append(genericDotLang);
     814               0 :         nsAdoptingCString nameValue = Preferences::GetCString(prefName.get());
     815               0 :         if (nameValue) {
     816               0 :             if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameValue), aClosure))
     817               0 :                 return false;
     818                 :         }
     819                 :     
     820                 :         // fetch font.name-list.xxx value                   
     821               0 :         prefName.AssignLiteral("font.name-list.");
     822               0 :         prefName.Append(genericDotLang);
     823               0 :         nsAdoptingCString nameListValue = Preferences::GetCString(prefName.get());
     824               0 :         if (nameListValue && !nameListValue.Equals(nameValue)) {
     825               0 :             const char kComma = ',';
     826                 :             const char *p, *p_end;
     827               0 :             nsCAutoString list(nameListValue);
     828               0 :             list.BeginReading(p);
     829               0 :             list.EndReading(p_end);
     830               0 :             while (p < p_end) {
     831               0 :                 while (nsCRT::IsAsciiSpace(*p)) {
     832               0 :                     if (++p == p_end)
     833               0 :                         break;
     834                 :                 }
     835               0 :                 if (p == p_end)
     836               0 :                     break;
     837               0 :                 const char *start = p;
     838               0 :                 while (++p != p_end && *p != kComma)
     839                 :                     /* nothing */ ;
     840               0 :                 nsCAutoString fontName(Substring(start, p));
     841               0 :                 fontName.CompressWhitespace(false, true);
     842               0 :                 if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(fontName), aClosure))
     843               0 :                     return false;
     844               0 :                 p++;
     845                 :             }
     846                 :         }
     847                 :     }
     848                 : 
     849               0 :     return true;
     850                 : }
     851                 : 
     852                 : eFontPrefLang
     853               0 : gfxPlatform::GetFontPrefLangFor(const char* aLang)
     854                 : {
     855               0 :     if (!aLang || !aLang[0])
     856               0 :         return eFontPrefLang_Others;
     857               0 :     for (PRUint32 i = 0; i < PRUint32(eFontPrefLang_LangCount); ++i) {
     858               0 :         if (!PL_strcasecmp(gPrefLangNames[i], aLang))
     859               0 :             return eFontPrefLang(i);
     860                 :     }
     861               0 :     return eFontPrefLang_Others;
     862                 : }
     863                 : 
     864                 : eFontPrefLang
     865               0 : gfxPlatform::GetFontPrefLangFor(nsIAtom *aLang)
     866                 : {
     867               0 :     if (!aLang)
     868               0 :         return eFontPrefLang_Others;
     869               0 :     nsCAutoString lang;
     870               0 :     aLang->ToUTF8String(lang);
     871               0 :     return GetFontPrefLangFor(lang.get());
     872                 : }
     873                 : 
     874                 : const char*
     875               0 : gfxPlatform::GetPrefLangName(eFontPrefLang aLang)
     876                 : {
     877               0 :     if (PRUint32(aLang) < PRUint32(eFontPrefLang_AllCount))
     878               0 :         return gPrefLangNames[PRUint32(aLang)];
     879               0 :     return nsnull;
     880                 : }
     881                 : 
     882                 : eFontPrefLang
     883               0 : gfxPlatform::GetFontPrefLangFor(PRUint8 aUnicodeRange)
     884                 : {
     885               0 :     switch (aUnicodeRange) {
     886               0 :         case kRangeSetLatin:   return eFontPrefLang_Western;
     887               0 :         case kRangeCyrillic:   return eFontPrefLang_Cyrillic;
     888               0 :         case kRangeGreek:      return eFontPrefLang_Greek;
     889               0 :         case kRangeTurkish:    return eFontPrefLang_Turkish;
     890               0 :         case kRangeHebrew:     return eFontPrefLang_Hebrew;
     891               0 :         case kRangeArabic:     return eFontPrefLang_Arabic;
     892               0 :         case kRangeBaltic:     return eFontPrefLang_Baltic;
     893               0 :         case kRangeThai:       return eFontPrefLang_Thai;
     894               0 :         case kRangeKorean:     return eFontPrefLang_Korean;
     895               0 :         case kRangeJapanese:   return eFontPrefLang_Japanese;
     896               0 :         case kRangeSChinese:   return eFontPrefLang_ChineseCN;
     897               0 :         case kRangeTChinese:   return eFontPrefLang_ChineseTW;
     898               0 :         case kRangeDevanagari: return eFontPrefLang_Devanagari;
     899               0 :         case kRangeTamil:      return eFontPrefLang_Tamil;
     900               0 :         case kRangeArmenian:   return eFontPrefLang_Armenian;
     901               0 :         case kRangeBengali:    return eFontPrefLang_Bengali;
     902               0 :         case kRangeCanadian:   return eFontPrefLang_Canadian;
     903               0 :         case kRangeEthiopic:   return eFontPrefLang_Ethiopic;
     904               0 :         case kRangeGeorgian:   return eFontPrefLang_Georgian;
     905               0 :         case kRangeGujarati:   return eFontPrefLang_Gujarati;
     906               0 :         case kRangeGurmukhi:   return eFontPrefLang_Gurmukhi;
     907               0 :         case kRangeKhmer:      return eFontPrefLang_Khmer;
     908               0 :         case kRangeMalayalam:  return eFontPrefLang_Malayalam;
     909               0 :         case kRangeOriya:      return eFontPrefLang_Oriya;
     910               0 :         case kRangeTelugu:     return eFontPrefLang_Telugu;
     911               0 :         case kRangeKannada:    return eFontPrefLang_Kannada;
     912               0 :         case kRangeSinhala:    return eFontPrefLang_Sinhala;
     913               0 :         case kRangeTibetan:    return eFontPrefLang_Tibetan;
     914               0 :         case kRangeSetCJK:     return eFontPrefLang_CJKSet;
     915               0 :         default:               return eFontPrefLang_Others;
     916                 :     }
     917                 : }
     918                 : 
     919                 : bool 
     920               0 : gfxPlatform::IsLangCJK(eFontPrefLang aLang)
     921                 : {
     922               0 :     switch (aLang) {
     923                 :         case eFontPrefLang_Japanese:
     924                 :         case eFontPrefLang_ChineseTW:
     925                 :         case eFontPrefLang_ChineseCN:
     926                 :         case eFontPrefLang_ChineseHK:
     927                 :         case eFontPrefLang_Korean:
     928                 :         case eFontPrefLang_CJKSet:
     929               0 :             return true;
     930                 :         default:
     931               0 :             return false;
     932                 :     }
     933                 : }
     934                 : 
     935                 : void 
     936               0 : gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
     937                 : {
     938               0 :     if (IsLangCJK(aCharLang)) {
     939               0 :         AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
     940                 :     } else {
     941               0 :         AppendPrefLang(aPrefLangs, aLen, aCharLang);
     942                 :     }
     943                 : 
     944               0 :     AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
     945               0 : }
     946                 : 
     947                 : void
     948               0 : gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
     949                 : {
     950                 :     // prefer the lang specified by the page *if* CJK
     951               0 :     if (IsLangCJK(aPageLang)) {
     952               0 :         AppendPrefLang(aPrefLangs, aLen, aPageLang);
     953                 :     }
     954                 :     
     955                 :     // if not set up, set up the default CJK order, based on accept lang settings and locale
     956               0 :     if (mCJKPrefLangs.Length() == 0) {
     957                 :     
     958                 :         // temp array
     959                 :         eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
     960               0 :         PRUint32 tempLen = 0;
     961                 :         
     962                 :         // Add the CJK pref fonts from accept languages, the order should be same order
     963               0 :         nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
     964               0 :         if (!list.IsEmpty()) {
     965               0 :             const char kComma = ',';
     966                 :             const char *p, *p_end;
     967               0 :             list.BeginReading(p);
     968               0 :             list.EndReading(p_end);
     969               0 :             while (p < p_end) {
     970               0 :                 while (nsCRT::IsAsciiSpace(*p)) {
     971               0 :                     if (++p == p_end)
     972               0 :                         break;
     973                 :                 }
     974               0 :                 if (p == p_end)
     975               0 :                     break;
     976               0 :                 const char *start = p;
     977               0 :                 while (++p != p_end && *p != kComma)
     978                 :                     /* nothing */ ;
     979               0 :                 nsCAutoString lang(Substring(start, p));
     980               0 :                 lang.CompressWhitespace(false, true);
     981               0 :                 eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
     982               0 :                 switch (fpl) {
     983                 :                     case eFontPrefLang_Japanese:
     984                 :                     case eFontPrefLang_Korean:
     985                 :                     case eFontPrefLang_ChineseCN:
     986                 :                     case eFontPrefLang_ChineseHK:
     987                 :                     case eFontPrefLang_ChineseTW:
     988               0 :                         AppendPrefLang(tempPrefLangs, tempLen, fpl);
     989               0 :                         break;
     990                 :                     default:
     991               0 :                         break;
     992                 :                 }
     993               0 :                 p++;
     994                 :             }
     995                 :         }
     996                 : 
     997                 :         do { // to allow 'break' to abort this block if a call fails
     998                 :             nsresult rv;
     999                 :             nsCOMPtr<nsILocaleService> ls =
    1000               0 :                 do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
    1001               0 :             if (NS_FAILED(rv))
    1002                 :                 break;
    1003                 : 
    1004               0 :             nsCOMPtr<nsILocale> appLocale;
    1005               0 :             rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
    1006               0 :             if (NS_FAILED(rv))
    1007                 :                 break;
    1008                 : 
    1009               0 :             nsString localeStr;
    1010               0 :             rv = appLocale->
    1011               0 :                 GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
    1012               0 :             if (NS_FAILED(rv))
    1013                 :                 break;
    1014                 : 
    1015               0 :             const nsAString& lang = Substring(localeStr, 0, 2);
    1016               0 :             if (lang.EqualsLiteral("ja")) {
    1017               0 :                 AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
    1018               0 :             } else if (lang.EqualsLiteral("zh")) {
    1019               0 :                 const nsAString& region = Substring(localeStr, 3, 2);
    1020               0 :                 if (region.EqualsLiteral("CN")) {
    1021               0 :                     AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
    1022               0 :                 } else if (region.EqualsLiteral("TW")) {
    1023               0 :                     AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
    1024               0 :                 } else if (region.EqualsLiteral("HK")) {
    1025               0 :                     AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
    1026                 :                 }
    1027               0 :             } else if (lang.EqualsLiteral("ko")) {
    1028               0 :                 AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
    1029                 :             }
    1030                 :         } while (0);
    1031                 : 
    1032                 :         // last resort... (the order is same as old gfx.)
    1033               0 :         AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
    1034               0 :         AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
    1035               0 :         AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
    1036               0 :         AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
    1037               0 :         AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
    1038                 :         
    1039                 :         // copy into the cached array
    1040                 :         PRUint32 j;
    1041               0 :         for (j = 0; j < tempLen; j++) {
    1042               0 :             mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
    1043                 :         }
    1044                 :     }
    1045                 :     
    1046                 :     // append in cached CJK langs
    1047               0 :     PRUint32  i, numCJKlangs = mCJKPrefLangs.Length();
    1048                 :     
    1049               0 :     for (i = 0; i < numCJKlangs; i++) {
    1050               0 :         AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
    1051                 :     }
    1052                 :         
    1053               0 : }
    1054                 : 
    1055                 : void 
    1056               0 : gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPrefLang aAddLang)
    1057                 : {
    1058               0 :     if (aLen >= kMaxLenPrefLangList) return;
    1059                 :     
    1060                 :     // make sure
    1061               0 :     PRUint32  i = 0;
    1062               0 :     while (i < aLen && aPrefLangs[i] != aAddLang) {
    1063               0 :         i++;
    1064                 :     }
    1065                 :     
    1066               0 :     if (i == aLen) {
    1067               0 :         aPrefLangs[aLen] = aAddLang;
    1068               0 :         aLen++;
    1069                 :     }
    1070                 : }
    1071                 : 
    1072                 : bool
    1073               0 : gfxPlatform::UseAzureContentDrawing()
    1074                 : {
    1075                 :   static bool sAzureContentDrawingEnabled;
    1076                 :   static bool sAzureContentDrawingPrefCached = false;
    1077                 : 
    1078               0 :   if (!sAzureContentDrawingPrefCached) {
    1079               0 :     sAzureContentDrawingPrefCached = true;
    1080                 :     mozilla::Preferences::AddBoolVarCache(&sAzureContentDrawingEnabled, 
    1081               0 :                                           "gfx.content.azure.enabled");
    1082                 :   }
    1083                 : 
    1084               0 :   return sAzureContentDrawingEnabled;
    1085                 : }
    1086                 : 
    1087                 : eCMSMode
    1088              15 : gfxPlatform::GetCMSMode()
    1089                 : {
    1090              15 :     if (gCMSInitialized == false) {
    1091               4 :         gCMSInitialized = true;
    1092                 :         nsresult rv;
    1093                 : 
    1094                 :         PRInt32 mode;
    1095               4 :         rv = Preferences::GetInt("gfx.color_management.mode", &mode);
    1096               4 :         if (NS_SUCCEEDED(rv) && (mode >= 0) && (mode < eCMSMode_AllCount)) {
    1097               4 :             gCMSMode = static_cast<eCMSMode>(mode);
    1098                 :         }
    1099                 : 
    1100                 :         bool enableV4;
    1101               4 :         rv = Preferences::GetBool("gfx.color_management.enablev4", &enableV4);
    1102               4 :         if (NS_SUCCEEDED(rv) && enableV4) {
    1103               0 :             qcms_enable_iccv4();
    1104                 :         }
    1105                 :     }
    1106              15 :     return gCMSMode;
    1107                 : }
    1108                 : 
    1109                 : /* Chris Murphy (CM consultant) suggests this as a default in the event that we
    1110                 : cannot reproduce relative + Black Point Compensation.  BPC brings an
    1111                 : unacceptable performance overhead, so we go with perceptual. */
    1112                 : #define INTENT_DEFAULT QCMS_INTENT_PERCEPTUAL
    1113                 : #define INTENT_MIN 0
    1114                 : #define INTENT_MAX 3
    1115                 : 
    1116                 : int
    1117               4 : gfxPlatform::GetRenderingIntent()
    1118                 : {
    1119               4 :     if (gCMSIntent == -2) {
    1120                 : 
    1121                 :         /* Try to query the pref system for a rendering intent. */
    1122                 :         PRInt32 pIntent;
    1123               3 :         if (NS_SUCCEEDED(Preferences::GetInt("gfx.color_management.rendering_intent", &pIntent))) {
    1124                 :             /* If the pref is within range, use it as an override. */
    1125               3 :             if ((pIntent >= INTENT_MIN) && (pIntent <= INTENT_MAX)) {
    1126               3 :                 gCMSIntent = pIntent;
    1127                 :             }
    1128                 :             /* If the pref is out of range, use embedded profile. */
    1129                 :             else {
    1130               0 :                 gCMSIntent = -1;
    1131                 :             }
    1132                 :         }
    1133                 :         /* If we didn't get a valid intent from prefs, use the default. */
    1134                 :         else {
    1135               0 :             gCMSIntent = INTENT_DEFAULT;
    1136                 :         }
    1137                 :     }
    1138               4 :     return gCMSIntent;
    1139                 : }
    1140                 : 
    1141                 : void 
    1142               0 : gfxPlatform::TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform)
    1143                 : {
    1144                 : 
    1145               0 :     if (transform) {
    1146                 :         /* we want the bytes in RGB order */
    1147                 : #ifdef IS_LITTLE_ENDIAN
    1148                 :         /* ABGR puts the bytes in |RGBA| order on little endian */
    1149               0 :         PRUint32 packed = in.Packed(gfxRGBA::PACKED_ABGR);
    1150                 :         qcms_transform_data(transform,
    1151                 :                        (PRUint8 *)&packed, (PRUint8 *)&packed,
    1152               0 :                        1);
    1153               0 :         out.~gfxRGBA();
    1154               0 :         new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ABGR);
    1155                 : #else
    1156                 :         /* ARGB puts the bytes in |ARGB| order on big endian */
    1157                 :         PRUint32 packed = in.Packed(gfxRGBA::PACKED_ARGB);
    1158                 :         /* add one to move past the alpha byte */
    1159                 :         qcms_transform_data(transform,
    1160                 :                        (PRUint8 *)&packed + 1, (PRUint8 *)&packed + 1,
    1161                 :                        1);
    1162                 :         out.~gfxRGBA();
    1163                 :         new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ARGB);
    1164                 : #endif
    1165                 :     }
    1166                 : 
    1167               0 :     else if (&out != &in)
    1168               0 :         out = in;
    1169               0 : }
    1170                 : 
    1171                 : qcms_profile *
    1172               0 : gfxPlatform::GetPlatformCMSOutputProfile()
    1173                 : {
    1174               0 :     return nsnull;
    1175                 : }
    1176                 : 
    1177                 : qcms_profile *
    1178               0 : gfxPlatform::GetCMSOutputProfile()
    1179                 : {
    1180               0 :     if (!gCMSOutputProfile) {
    1181                 :         NS_TIME_FUNCTION;
    1182                 : 
    1183                 :         /* Determine if we're using the internal override to force sRGB as
    1184                 :            an output profile for reftests. See Bug 452125.
    1185                 : 
    1186                 :            Note that we don't normally (outside of tests) set a
    1187                 :            default value of this preference, which means nsIPrefBranch::GetBoolPref
    1188                 :            will typically throw (and leave its out-param untouched).
    1189                 :          */
    1190               0 :         if (Preferences::GetBool("gfx.color_management.force_srgb", false)) {
    1191               0 :             gCMSOutputProfile = GetCMSsRGBProfile();
    1192                 :         }
    1193                 : 
    1194               0 :         if (!gCMSOutputProfile) {
    1195               0 :             nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
    1196               0 :             if (!fname.IsEmpty()) {
    1197               0 :                 gCMSOutputProfile = qcms_profile_from_path(fname);
    1198                 :             }
    1199                 :         }
    1200                 : 
    1201               0 :         if (!gCMSOutputProfile) {
    1202                 :             gCMSOutputProfile =
    1203               0 :                 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile();
    1204                 :         }
    1205                 : 
    1206                 :         /* Determine if the profile looks bogus. If so, close the profile
    1207                 :          * and use sRGB instead. See bug 460629, */
    1208               0 :         if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
    1209               0 :             NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
    1210                 :                          "Builtin sRGB profile tagged as bogus!!!");
    1211               0 :             qcms_profile_release(gCMSOutputProfile);
    1212               0 :             gCMSOutputProfile = nsnull;
    1213                 :         }
    1214                 : 
    1215               0 :         if (!gCMSOutputProfile) {
    1216               0 :             gCMSOutputProfile = GetCMSsRGBProfile();
    1217                 :         }
    1218                 :         /* Precache the LUT16 Interpolations for the output profile. See 
    1219                 :            bug 444661 for details. */
    1220               0 :         qcms_profile_precache_output_transform(gCMSOutputProfile);
    1221                 :     }
    1222                 : 
    1223               0 :     return gCMSOutputProfile;
    1224                 : }
    1225                 : 
    1226                 : qcms_profile *
    1227               0 : gfxPlatform::GetCMSsRGBProfile()
    1228                 : {
    1229               0 :     if (!gCMSsRGBProfile) {
    1230                 : 
    1231                 :         /* Create the profile using qcms. */
    1232               0 :         gCMSsRGBProfile = qcms_profile_sRGB();
    1233                 :     }
    1234               0 :     return gCMSsRGBProfile;
    1235                 : }
    1236                 : 
    1237                 : qcms_transform *
    1238               0 : gfxPlatform::GetCMSRGBTransform()
    1239                 : {
    1240               0 :     if (!gCMSRGBTransform) {
    1241                 :         qcms_profile *inProfile, *outProfile;
    1242               0 :         outProfile = GetCMSOutputProfile();
    1243               0 :         inProfile = GetCMSsRGBProfile();
    1244                 : 
    1245               0 :         if (!inProfile || !outProfile)
    1246               0 :             return nsnull;
    1247                 : 
    1248                 :         gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
    1249                 :                                               outProfile, QCMS_DATA_RGB_8,
    1250               0 :                                              QCMS_INTENT_PERCEPTUAL);
    1251                 :     }
    1252                 : 
    1253               0 :     return gCMSRGBTransform;
    1254                 : }
    1255                 : 
    1256                 : qcms_transform *
    1257               0 : gfxPlatform::GetCMSInverseRGBTransform()
    1258                 : {
    1259               0 :     if (!gCMSInverseRGBTransform) {
    1260                 :         qcms_profile *inProfile, *outProfile;
    1261               0 :         inProfile = GetCMSOutputProfile();
    1262               0 :         outProfile = GetCMSsRGBProfile();
    1263                 : 
    1264               0 :         if (!inProfile || !outProfile)
    1265               0 :             return nsnull;
    1266                 : 
    1267                 :         gCMSInverseRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
    1268                 :                                                      outProfile, QCMS_DATA_RGB_8,
    1269               0 :                                                      QCMS_INTENT_PERCEPTUAL);
    1270                 :     }
    1271                 : 
    1272               0 :     return gCMSInverseRGBTransform;
    1273                 : }
    1274                 : 
    1275                 : qcms_transform *
    1276               0 : gfxPlatform::GetCMSRGBATransform()
    1277                 : {
    1278               0 :     if (!gCMSRGBATransform) {
    1279                 :         qcms_profile *inProfile, *outProfile;
    1280               0 :         outProfile = GetCMSOutputProfile();
    1281               0 :         inProfile = GetCMSsRGBProfile();
    1282                 : 
    1283               0 :         if (!inProfile || !outProfile)
    1284               0 :             return nsnull;
    1285                 : 
    1286                 :         gCMSRGBATransform = qcms_transform_create(inProfile, QCMS_DATA_RGBA_8,
    1287                 :                                                outProfile, QCMS_DATA_RGBA_8,
    1288               0 :                                                QCMS_INTENT_PERCEPTUAL);
    1289                 :     }
    1290                 : 
    1291               0 :     return gCMSRGBATransform;
    1292                 : }
    1293                 : 
    1294                 : /* Shuts down various transforms and profiles for CMS. */
    1295               4 : static void ShutdownCMS()
    1296                 : {
    1297                 : 
    1298               4 :     if (gCMSRGBTransform) {
    1299               0 :         qcms_transform_release(gCMSRGBTransform);
    1300               0 :         gCMSRGBTransform = nsnull;
    1301                 :     }
    1302               4 :     if (gCMSInverseRGBTransform) {
    1303               0 :         qcms_transform_release(gCMSInverseRGBTransform);
    1304               0 :         gCMSInverseRGBTransform = nsnull;
    1305                 :     }
    1306               4 :     if (gCMSRGBATransform) {
    1307               0 :         qcms_transform_release(gCMSRGBATransform);
    1308               0 :         gCMSRGBATransform = nsnull;
    1309                 :     }
    1310               4 :     if (gCMSOutputProfile) {
    1311               0 :         qcms_profile_release(gCMSOutputProfile);
    1312                 : 
    1313                 :         // handle the aliased case
    1314               0 :         if (gCMSsRGBProfile == gCMSOutputProfile)
    1315               0 :             gCMSsRGBProfile = nsnull;
    1316               0 :         gCMSOutputProfile = nsnull;
    1317                 :     }
    1318               4 :     if (gCMSsRGBProfile) {
    1319               0 :         qcms_profile_release(gCMSsRGBProfile);
    1320               0 :         gCMSsRGBProfile = nsnull;
    1321                 :     }
    1322                 : 
    1323                 :     // Reset the state variables
    1324               4 :     gCMSIntent = -2;
    1325               4 :     gCMSMode = eCMSMode_Off;
    1326               4 :     gCMSInitialized = false;
    1327               4 : }
    1328                 : 
    1329               3 : static void MigratePrefs()
    1330                 : {
    1331                 :     /* Migrate from the boolean color_management.enabled pref - we now use
    1332                 :        color_management.mode. */
    1333               3 :     if (Preferences::HasUserValue("gfx.color_management.enabled")) {
    1334               0 :         if (Preferences::GetBool("gfx.color_management.enabled", false)) {
    1335               0 :             Preferences::SetInt("gfx.color_management.mode", static_cast<PRInt32>(eCMSMode_All));
    1336                 :         }
    1337               0 :         Preferences::ClearUser("gfx.color_management.enabled");
    1338                 :     }
    1339               3 : }
    1340                 : 
    1341                 : // default SetupClusterBoundaries, based on Unicode properties;
    1342                 : // platform subclasses may override if they wish
    1343                 : void
    1344               0 : gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
    1345                 : {
    1346               0 :     if (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) {
    1347                 :         // 8-bit text doesn't have clusters.
    1348                 :         // XXX is this true in all languages???
    1349                 :         // behdad: don't think so.  Czech for example IIRC has a
    1350                 :         // 'ch' grapheme.
    1351                 :         // jfkthame: but that's not expected to behave as a grapheme cluster
    1352                 :         // for selection/editing/etc.
    1353               0 :         return;
    1354                 :     }
    1355                 : 
    1356                 :     gfxShapedWord::SetupClusterBoundaries(aTextRun->GetCharacterGlyphs(),
    1357               0 :                                           aString, aTextRun->GetLength());
    1358                 : }
    1359                 : 
    1360                 : PRInt32
    1361               0 : gfxPlatform::GetBidiNumeralOption()
    1362                 : {
    1363               0 :     if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
    1364               0 :         mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
    1365                 :     }
    1366               0 :     return mBidiNumeralOption;
    1367                 : }
    1368                 : 
    1369                 : void
    1370               0 : gfxPlatform::FontsPrefsChanged(const char *aPref)
    1371                 : {
    1372               0 :     NS_ASSERTION(aPref != nsnull, "null preference");
    1373               0 :     if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
    1374               0 :         mAllowDownloadableFonts = UNINITIALIZED_VALUE;
    1375               0 :     } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_SANITIZE, aPref)) {
    1376               0 :         mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
    1377               0 :     } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
    1378               0 :         mFallbackUsesCmaps = UNINITIALIZED_VALUE;
    1379                 : #ifdef MOZ_GRAPHITE
    1380               0 :     } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
    1381               0 :         mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
    1382               0 :         gfxFontCache *fontCache = gfxFontCache::GetCache();
    1383               0 :         if (fontCache) {
    1384               0 :             fontCache->AgeAllGenerations();
    1385               0 :             fontCache->FlushShapedWordCaches();
    1386                 :         }
    1387                 : #endif
    1388               0 :     } else if (!strcmp(GFX_PREF_HARFBUZZ_SCRIPTS, aPref)) {
    1389               0 :         mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
    1390               0 :         gfxFontCache *fontCache = gfxFontCache::GetCache();
    1391               0 :         if (fontCache) {
    1392               0 :             fontCache->AgeAllGenerations();
    1393               0 :             fontCache->FlushShapedWordCaches();
    1394                 :         }
    1395               0 :     } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
    1396               0 :         mBidiNumeralOption = UNINITIALIZED_VALUE;
    1397                 :     }
    1398               0 : }
    1399                 : 
    1400                 : 
    1401                 : PRLogModuleInfo*
    1402               0 : gfxPlatform::GetLog(eGfxLog aWhichLog)
    1403                 : {
    1404                 : #ifdef PR_LOGGING
    1405               0 :     switch (aWhichLog) {
    1406                 :     case eGfxLog_fontlist:
    1407               0 :         return sFontlistLog;
    1408                 :         break;
    1409                 :     case eGfxLog_fontinit:
    1410               0 :         return sFontInitLog;
    1411                 :         break;
    1412                 :     case eGfxLog_textrun:
    1413               0 :         return sTextrunLog;
    1414                 :         break;
    1415                 :     case eGfxLog_textrunui:
    1416               0 :         return sTextrunuiLog;
    1417                 :         break;
    1418                 :     case eGfxLog_cmapdata:
    1419               0 :         return sCmapDataLog;
    1420                 :         break;
    1421                 :     default:
    1422                 :         break;
    1423                 :     }
    1424                 : 
    1425               0 :     return nsnull;
    1426                 : #else
    1427                 :     return nsnull;
    1428                 : #endif
    1429                 : }

Generated by: LCOV version 1.7