Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Factory.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "2D.h"
#include "Swizzle.h"

#ifdef USE_CAIRO
#  include "DrawTargetCairo.h"
#  include "PathCairo.h"
#  include "SourceSurfaceCairo.h"
#endif

#include "DrawTargetSkia.h"
#include "PathSkia.h"
#include "ScaledFontBase.h"

#if defined(WIN32)
#  include "ScaledFontWin.h"
#  include "NativeFontResourceGDI.h"
#  include "UnscaledFontGDI.h"
#endif

#ifdef XP_DARWIN
#  include "ScaledFontMac.h"
#  include "NativeFontResourceMac.h"
#  include "UnscaledFontMac.h"
#endif

#ifdef MOZ_WIDGET_GTK
#  include "ScaledFontFontconfig.h"
#  include "NativeFontResourceFreeType.h"
#  include "UnscaledFontFreeType.h"
#endif

#ifdef MOZ_WIDGET_ANDROID
#  include "ScaledFontFreeType.h"
#  include "NativeFontResourceFreeType.h"
#  include "UnscaledFontFreeType.h"
#endif

#ifdef WIN32
#  include "ScaledFontDWrite.h"
#  include "NativeFontResourceDWrite.h"
#  include "UnscaledFontDWrite.h"
#  include <d3d10_1.h>
#  include <stdlib.h>
#  include "HelpersWin.h"
#  include "ImageContainer.h"
#  include "mozilla/layers/LayersSurfaces.h"
#  include "mozilla/layers/TextureD3D11.h"
#  include "mozilla/layers/VideoProcessorD3D11.h"
#  include "nsWindowsHelpers.h"
#endif

#include "DrawTargetOffset.h"
#include "DrawTargetRecording.h"
#include "PathRecording.h"

#include "SourceSurfaceRawData.h"

#include "mozilla/CheckedInt.h"

#ifdef MOZ_ENABLE_FREETYPE
#  include "ft2build.h"
#  include FT_FREETYPE_H
#endif
#include "mozilla/StaticPrefs_gfx.h"

#if defined(MOZ_LOGGING)
GFX2D_API mozilla::LogModule* GetGFX2DLog() {
  static mozilla::LazyLogModule sLog("gfx2d");
  return sLog;
}
#endif

#ifdef MOZ_ENABLE_FREETYPE
extern "C" {

void mozilla_AddRefSharedFTFace(void* aContext) {
  if (aContext) {
    static_cast<mozilla::gfx::SharedFTFace*>(aContext)->AddRef();
  }
}

void mozilla_ReleaseSharedFTFace(void* aContext, void* aOwner) {
  if (aContext) {
    auto* sharedFace = static_cast<mozilla::gfx::SharedFTFace*>(aContext);
    sharedFace->ForgetLockOwner(aOwner);
    sharedFace->Release();
  }
}

void mozilla_ForgetSharedFTFaceLockOwner(void* aContext, void* aOwner) {
  static_cast<mozilla::gfx::SharedFTFace*>(aContext)->ForgetLockOwner(aOwner);
}

int mozilla_LockSharedFTFace(void* aContext,
                             void* aOwner) MOZ_NO_THREAD_SAFETY_ANALYSIS {
  return int(static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock(aOwner));
}

void mozilla_UnlockSharedFTFace(void* aContext) MOZ_NO_THREAD_SAFETY_ANALYSIS {
  static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Unlock();
}

FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex,
                             int32_t aFlags) {
  return mozilla::gfx::Factory::LoadFTGlyph(aFace, aGlyphIndex, aFlags);
}

void mozilla_LockFTLibrary(FT_Library aFTLibrary) {
  mozilla::gfx::Factory::LockFTLibrary(aFTLibrary);
}

void mozilla_UnlockFTLibrary(FT_Library aFTLibrary) {
  mozilla::gfx::Factory::UnlockFTLibrary(aFTLibrary);
}
}
#endif

namespace mozilla::gfx {

#ifdef MOZ_ENABLE_FREETYPE
FT_Library Factory::mFTLibrary = nullptr;
StaticMutex Factory::mFTLock;

already_AddRefed<SharedFTFace> FTUserFontData::CloneFace(int aFaceIndex) {
  if (mFontData) {
    RefPtr<SharedFTFace> face = Factory::NewSharedFTFaceFromData(
        nullptr, mFontData, mLength, aFaceIndex, this);
    if (!face ||
        (FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok &&
         FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) !=
             FT_Err_Ok)) {
      return nullptr;
    }
    return face.forget();
  }
  FT_Face face = Factory::NewFTFace(nullptr, mFilename.c_str(), aFaceIndex);
  if (face) {
    return MakeAndAddRef<SharedFTFace>(face, this);
  }
  return nullptr;
}
#endif

#ifdef WIN32
// Note: mDeviceLock must be held when mutating these values.
StaticRefPtr<ID3D11Device> Factory::mD3D11Device;
StaticRefPtr<IDWriteFactory> Factory::mDWriteFactory;
StaticRefPtr<IDWriteFontCollection> Factory::mDWriteSystemFonts;
StaticMutex Factory::mDeviceLock;
#endif

SubpixelOrder Factory::mSubpixelOrder = SubpixelOrder::UNKNOWN;

mozilla::gfx::Config* Factory::sConfig = nullptr;

void Factory::Init(const Config& aConfig) {
  MOZ_ASSERT(!sConfig);
  sConfig = new Config(aConfig);

#ifdef XP_DARWIN
  NativeFontResourceMac::RegisterMemoryReporter();
#else
  NativeFontResource::RegisterMemoryReporter();
#endif

  SourceSurfaceAlignedRawData::RegisterMemoryReporter();
}

void Factory::ShutDown() {
  if (sConfig) {
    delete sConfig->mLogForwarder;
    delete sConfig;
    sConfig = nullptr;
  }

#ifdef MOZ_ENABLE_FREETYPE
  mFTLibrary = nullptr;
#endif
}

// If the size is "reasonable", we want gfxCriticalError to assert, so
// this is the option set up for it.
inline int LoggerOptionsBasedOnSize(const IntSize& aSize) {
  return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize));
}

bool Factory::ReasonableSurfaceSize(const IntSize& aSize) {
  return Factory::CheckSurfaceSize(aSize, kReasonableSurfaceSize);
}

bool Factory::AllowedSurfaceSize(const IntSize& aSize) {
  if (sConfig) {
    return Factory::CheckSurfaceSize(aSize, sConfig->mMaxTextureSize,
                                     sConfig->mMaxAllocSize);
  }

  return CheckSurfaceSize(aSize);
}

bool Factory::CheckSurfaceSize(const IntSize& sz, int32_t extentLimit,
                               int32_t allocLimit) {
  if (sz.width <= 0 || sz.height <= 0) {
    return false;
  }

  // reject images with sides bigger than limit
  if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) {
    gfxDebug() << "Surface size too large (exceeds extent limit)!";
    return false;
  }

  // assuming 4 bytes per pixel, make sure the allocation size
  // doesn't overflow a int32_t either
  auto stride = GetAlignedStride<16>(sz.width, 4);
  if (stride.isNothing()) {
    gfxDebug() << "Surface size too large (stride is invalid)!";
    return false;
  }

  CheckedInt<int32_t> numBytes =
      CheckedInt<int32_t>(stride.value()) * sz.height;
  if (!numBytes.isValid()) {
    gfxDebug()
        << "Surface size too large (allocation size would overflow int32_t)!";
    return false;
  }

  if (allocLimit && allocLimit < numBytes.value()) {
    gfxDebug() << "Surface size too large (exceeds allocation limit)!";
    return false;
  }

  return true;
}

already_AddRefed<DrawTarget> Factory::CreateDrawTarget(BackendType aBackend,
                                                       const IntSize& aSize,
                                                       SurfaceFormat aFormat) {
  if (!AllowedSurfaceSize(aSize)) {
    gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
        << "Failed to allocate a surface due to invalid size (CDT) " << aSize;
    return nullptr;
  }

  RefPtr<DrawTarget> retVal;
  switch (aBackend) {
    case BackendType::SKIA: {
      RefPtr<DrawTargetSkia> newTarget;
      newTarget = new DrawTargetSkia();
      if (newTarget->Init(aSize, aFormat)) {
        retVal = newTarget;
      }
      break;
    }
#ifdef USE_CAIRO
    case BackendType::CAIRO: {
      RefPtr<DrawTargetCairo> newTarget;
      newTarget = new DrawTargetCairo();
      if (newTarget->Init(aSize, aFormat)) {
        retVal = newTarget;
      }
      break;
    }
#endif
    default:
      return nullptr;
  }

  if (!retVal) {
    // Failed
    gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
        << "Failed to create DrawTarget, Type: " << int(aBackend)
        << " Size: " << aSize;
  }

  return retVal.forget();
}

already_AddRefed<PathBuilder> Factory::CreatePathBuilder(BackendType aBackend,
                                                         FillRule aFillRule) {
  switch (aBackend) {
    case BackendType::SKIA:
    case BackendType::WEBGL:
      return PathBuilderSkia::Create(aFillRule);
#ifdef USE_CAIRO
    case BackendType::CAIRO:
      return PathBuilderCairo::Create(aFillRule);
#endif
    case BackendType::RECORDING:
      return do_AddRef(new PathBuilderRecording(BackendType::SKIA, aFillRule));
    default:
      gfxCriticalNote << "Invalid PathBuilder type specified: "
                      << (int)aBackend;
      return nullptr;
  }
}

already_AddRefed<PathBuilder> Factory::CreateSimplePathBuilder() {
  return CreatePathBuilder(BackendType::SKIA);
}

already_AddRefed<DrawTarget> Factory::CreateRecordingDrawTarget(
    DrawEventRecorder* aRecorder, DrawTarget* aDT, IntRect aRect) {
  return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aRect);
}

already_AddRefed<DrawTarget> Factory::CreateDrawTargetForData(
    BackendType aBackend, unsigned char* aData, const IntSize& aSize,
    int32_t aStride, SurfaceFormat aFormat, bool aUninitialized,
    bool aIsClear) {
  MOZ_ASSERT(aData);
  if (!AllowedSurfaceSize(aSize)) {
    gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
        << "Failed to allocate a surface due to invalid size (DTD) " << aSize;
    return nullptr;
  }

  RefPtr<DrawTarget> retVal;

  switch (aBackend) {
    case BackendType::SKIA: {
      RefPtr<DrawTargetSkia> newTarget;
      newTarget = new DrawTargetSkia();
      if (newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized,
                          aIsClear)) {
        retVal = newTarget;
      }
      break;
    }
#ifdef USE_CAIRO
    case BackendType::CAIRO: {
      RefPtr<DrawTargetCairo> newTarget;
      newTarget = new DrawTargetCairo();
      if (newTarget->Init(aData, aSize, aStride, aFormat)) {
        retVal = std::move(newTarget);
      }
      break;
    }
#endif
    default:
      gfxCriticalNote << "Invalid draw target type specified: "
                      << (int)aBackend;
      return nullptr;
  }

  if (!retVal) {
    gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend)
                    << " Size: " << aSize << ", Data: " << hexa((void*)aData)
                    << ", Stride: " << aStride;
  }

  return retVal.forget();
}

already_AddRefed<DrawTarget> Factory::CreateOffsetDrawTarget(
    DrawTarget* aDrawTarget, IntPoint aTileOrigin) {
  RefPtr dt = MakeRefPtr<DrawTargetOffset>();

  if (!dt->Init(aDrawTarget, aTileOrigin)) {
    return nullptr;
  }

  return dt.forget();
}

bool Factory::DoesBackendSupportDataDrawtarget(BackendType aType) {
  switch (aType) {
    case BackendType::RECORDING:
    case BackendType::NONE:
    case BackendType::BACKEND_LAST:
    case BackendType::WEBRENDER_TEXT:
    case BackendType::WEBGL:
      return false;
    case BackendType::CAIRO:
    case BackendType::SKIA:
      return true;
  }

  return false;
}

size_t Factory::GetMaxSurfaceSize(BackendType aType) {
  switch (aType) {
    case BackendType::CAIRO:
      return DrawTargetCairo::GetMaxSurfaceSize();
    case BackendType::SKIA:
      return DrawTargetSkia::GetMaxSurfaceSize();
    default:
      return 0;
  }
}

size_t Factory::GetMaxSurfaceArea(BackendType aType) {
  switch (aType) {
    case BackendType::CAIRO:
      return DrawTargetCairo::GetMaxSurfaceArea();
    case BackendType::SKIA:
      return DrawTargetSkia::GetMaxSurfaceArea();
    default:
      return 0;
  }
}

already_AddRefed<NativeFontResource> Factory::CreateNativeFontResource(
    const uint8_t* aData, uint32_t aSize, FontType aFontType,
    void* aFontContext) {
  switch (aFontType) {
#ifdef WIN32
    case FontType::DWRITE:
      return NativeFontResourceDWrite::Create(aData, aSize);
    case FontType::GDI:
      return NativeFontResourceGDI::Create(aData, aSize);
#elif defined(XP_DARWIN)
    case FontType::MAC:
      return NativeFontResourceMac::Create(aData, aSize);
#elif defined(MOZ_WIDGET_GTK)
    case FontType::FONTCONFIG:
      return NativeFontResourceFontconfig::Create(
          aData, aSize, static_cast<FT_Library>(aFontContext));
#elif defined(MOZ_WIDGET_ANDROID)
    case FontType::FREETYPE:
      return NativeFontResourceFreeType::Create(
          aData, aSize, static_cast<FT_Library>(aFontContext));
#endif
    default:
      gfxWarning()
          << "Unable to create requested font resource from truetype data";
      return nullptr;
  }
}

already_AddRefed<UnscaledFont> Factory::CreateUnscaledFontFromFontDescriptor(
    FontType aType, const uint8_t* aData, uint32_t aDataLength,
    uint32_t aIndex) {
  switch (aType) {
#ifdef WIN32
    case FontType::DWRITE:
      return UnscaledFontDWrite::CreateFromFontDescriptor(aData, aDataLength,
                                                          aIndex);
    case FontType::GDI:
      return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength,
                                                       aIndex);
#elif defined(XP_DARWIN)
    case FontType::MAC:
      return UnscaledFontMac::CreateFromFontDescriptor(aData, aDataLength,
                                                       aIndex);
#elif defined(MOZ_WIDGET_GTK)
    case FontType::FONTCONFIG:
      return UnscaledFontFontconfig::CreateFromFontDescriptor(
          aData, aDataLength, aIndex);
#elif defined(MOZ_WIDGET_ANDROID)
    case FontType::FREETYPE:
      return UnscaledFontFreeType::CreateFromFontDescriptor(aData, aDataLength,
                                                            aIndex);
#endif
    default:
      gfxWarning() << "Invalid type specified for UnscaledFont font descriptor";
      return nullptr;
  }
}

#ifdef XP_DARWIN
already_AddRefed<ScaledFont> Factory::CreateScaledFontForMacFont(
    CGFontRef aCGFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
    bool aUseFontSmoothing, bool aApplySyntheticBold, bool aHasColorGlyphs) {
  return MakeAndAddRef<ScaledFontMac>(aCGFont, aUnscaledFont, aSize, false,
                                      aUseFontSmoothing, aApplySyntheticBold,
                                      aHasColorGlyphs);
}
#endif

#ifdef MOZ_WIDGET_GTK
already_AddRefed<ScaledFont> Factory::CreateScaledFontForFontconfigFont(
    const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
    RefPtr<SharedFTFace> aFace, FcPattern* aPattern) {
  return MakeAndAddRef<ScaledFontFontconfig>(std::move(aFace), aPattern,
                                             aUnscaledFont, aSize);
}
#endif

#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<ScaledFont> Factory::CreateScaledFontForFreeTypeFont(
    const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
    RefPtr<SharedFTFace> aFace, bool aApplySyntheticBold) {
  return MakeAndAddRef<ScaledFontFreeType>(std::move(aFace), aUnscaledFont,
                                           aSize, aApplySyntheticBold);
}
#endif

void Factory::SetSubpixelOrder(SubpixelOrder aOrder) {
  mSubpixelOrder = aOrder;
}

SubpixelOrder Factory::GetSubpixelOrder() { return mSubpixelOrder; }

#ifdef MOZ_ENABLE_FREETYPE
SharedFTFace::SharedFTFace(FT_Face aFace, SharedFTFaceData* aData)
    : mFace(aFace),
      mData(aData),
      mLock("SharedFTFace::mLock"),
      mLastLockOwner(nullptr) {
  if (mData) {
    mData->BindData();
  }
}

SharedFTFace::~SharedFTFace() {
  Factory::ReleaseFTFace(mFace);
  if (mData) {
    mData->ReleaseData();
  }
}

void Factory::SetFTLibrary(FT_Library aFTLibrary) { mFTLibrary = aFTLibrary; }

FT_Library Factory::GetFTLibrary() {
  MOZ_ASSERT(mFTLibrary);
  return mFTLibrary;
}

FT_Library Factory::NewFTLibrary() {
  FT_Library library;
  if (FT_Init_FreeType(&library) != FT_Err_Ok) {
    return nullptr;
  }
  return library;
}

void Factory::ReleaseFTLibrary(FT_Library aFTLibrary) {
  FT_Done_FreeType(aFTLibrary);
}

void Factory::LockFTLibrary(FT_Library aFTLibrary)
    MOZ_CAPABILITY_ACQUIRE(mFTLock) MOZ_NO_THREAD_SAFETY_ANALYSIS {
  mFTLock.Lock();
}

void Factory::UnlockFTLibrary(FT_Library aFTLibrary)
    MOZ_CAPABILITY_RELEASE(mFTLock) MOZ_NO_THREAD_SAFETY_ANALYSIS {
  mFTLock.Unlock();
}

FT_Face Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName,
                           int aFaceIndex) {
  StaticMutexAutoLock lock(mFTLock);
  if (!aFTLibrary) {
    aFTLibrary = mFTLibrary;
  }
  FT_Face face;
  if (FT_New_Face(aFTLibrary, aFileName, aFaceIndex, &face) != FT_Err_Ok) {
    return nullptr;
  }
  return face;
}

already_AddRefed<SharedFTFace> Factory::NewSharedFTFace(FT_Library aFTLibrary,
                                                        const char* aFilename,
                                                        int aFaceIndex) {
  FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex);
  if (!face) {
    return nullptr;
  }

  RefPtr<FTUserFontData> data;
#  ifdef ANDROID
  // If the font has variations, we may later need to "clone" it in
  // UnscaledFontFreeType::CreateScaledFont. To support this, we attach an
  // FTUserFontData that records the filename used to instantiate the face.
  if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
    data = new FTUserFontData(aFilename);
  }
#  endif
  return MakeAndAddRef<SharedFTFace>(face, data);
}

FT_Face Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData,
                                   size_t aDataSize, int aFaceIndex) {
  StaticMutexAutoLock lock(mFTLock);
  if (!aFTLibrary) {
    aFTLibrary = mFTLibrary;
  }
  FT_Face face;
  if (FT_New_Memory_Face(aFTLibrary, aData, aDataSize, aFaceIndex, &face) !=
      FT_Err_Ok) {
    return nullptr;
  }
  return face;
}

already_AddRefed<SharedFTFace> Factory::NewSharedFTFaceFromData(
    FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize,
    int aFaceIndex, SharedFTFaceData* aSharedData) {
  if (FT_Face face =
          NewFTFaceFromData(aFTLibrary, aData, aDataSize, aFaceIndex)) {
    return MakeAndAddRef<SharedFTFace>(face, aSharedData);
  } else {
    return nullptr;
  }
}

void Factory::ReleaseFTFace(FT_Face aFace) {
  StaticMutexAutoLock lock(mFTLock);
  FT_Done_Face(aFace);
}

FT_Error Factory::LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex,
                              int32_t aFlags) {
  StaticMutexAutoLock lock(mFTLock);
  return FT_Load_Glyph(aFace, aGlyphIndex, aFlags);
}
#endif

#ifdef WIN32
bool Factory::SetDirect3D11Device(ID3D11Device* aDevice) {
  MOZ_RELEASE_ASSERT(NS_IsMainThread());

  StaticMutexAutoLock lock(mDeviceLock);

  mD3D11Device = aDevice;
  return true;
}

RefPtr<ID3D11Device> Factory::GetDirect3D11Device() {
  StaticMutexAutoLock lock(mDeviceLock);
  return mD3D11Device;
}

RefPtr<IDWriteFactory> Factory::GetDWriteFactory() {
  StaticMutexAutoLock lock(mDeviceLock);
  return mDWriteFactory;
}

RefPtr<IDWriteFactory> Factory::EnsureDWriteFactory() {
  StaticMutexAutoLock lock(mDeviceLock);

  if (mDWriteFactory) {
    return mDWriteFactory;
  }

  HMODULE dwriteModule = LoadLibrarySystem32(L"dwrite.dll");
  decltype(DWriteCreateFactory)* createDWriteFactory =
      (decltype(DWriteCreateFactory)*)GetProcAddress(dwriteModule,
                                                     "DWriteCreateFactory");

  if (!createDWriteFactory) {
    gfxWarning() << "Failed to locate DWriteCreateFactory function.";
    return nullptr;
  }

  HRESULT hr =
      createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
                          reinterpret_cast<IUnknown**>(&mDWriteFactory));

  if (FAILED(hr)) {
    gfxWarning() << "Failed to create DWrite Factory.";
  }

  return mDWriteFactory;
}

RefPtr<IDWriteFontCollection> Factory::GetDWriteSystemFonts(bool aUpdate) {
  StaticMutexAutoLock lock(mDeviceLock);

  if (mDWriteSystemFonts && !aUpdate) {
    return mDWriteSystemFonts;
  }

  if (!mDWriteFactory) {
    if ((rand() & 0x3f) == 0) {
      gfxCriticalError(int(gfx::LogOptions::AssertOnCall))
          << "Failed to create DWrite factory";
    } else {
      gfxWarning() << "Failed to create DWrite factory";
    }

    return nullptr;
  }

  RefPtr<IDWriteFontCollection> systemFonts;
  HRESULT hr =
      mDWriteFactory->GetSystemFontCollection(getter_AddRefs(systemFonts));
  if (FAILED(hr) || !systemFonts) {
    // only crash some of the time so those experiencing this problem
    // don't stop using Firefox
    if ((rand() & 0x3f) == 0) {
      gfxCriticalError(int(gfx::LogOptions::AssertOnCall))
          << "Failed to create DWrite system font collection";
    } else {
      gfxWarning() << "Failed to create DWrite system font collection";
    }
    return nullptr;
  }
  mDWriteSystemFonts = systemFonts;

  return mDWriteSystemFonts;
}

BYTE sSystemTextQuality = CLEARTYPE_QUALITY;
void Factory::SetSystemTextQuality(uint8_t aQuality) {
  sSystemTextQuality = aQuality;
}

already_AddRefed<ScaledFont> Factory::CreateScaledFontForDWriteFont(
    IDWriteFontFace* aFontFace, const gfxFontStyle* aStyle,
    const RefPtr<UnscaledFont>& aUnscaledFont, float aSize,
    bool aUseEmbeddedBitmap, bool aUseMultistrikeBold, bool aGDIForced) {
  return MakeAndAddRef<ScaledFontDWrite>(
      aFontFace, aUnscaledFont, aSize, aUseEmbeddedBitmap, aUseMultistrikeBold,
      aGDIForced, aStyle);
}

already_AddRefed<ScaledFont> Factory::CreateScaledFontForGDIFont(
    const void* aLogFont, const RefPtr<UnscaledFont>& aUnscaledFont,
    Float aSize) {
  return MakeAndAddRef<ScaledFontWin>(static_cast<const LOGFONT*>(aLogFont),
                                      aUnscaledFont, aSize);
}
#endif  // WIN32

already_AddRefed<DrawTarget> Factory::CreateDrawTargetWithSkCanvas(
    SkCanvas* aCanvas) {
  RefPtr newTarget = MakeRefPtr<DrawTargetSkia>();
  if (!newTarget->Init(aCanvas)) {
    return nullptr;
  }
  return newTarget.forget();
}

void Factory::PurgeAllCaches() {}

already_AddRefed<DrawTarget> Factory::CreateDrawTargetForCairoSurface(
    cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat) {
  if (!AllowedSurfaceSize(aSize)) {
    gfxWarning() << "Allowing surface with invalid size (Cairo) " << aSize;
  }

  RefPtr<DrawTarget> retVal;

#ifdef USE_CAIRO
  RefPtr newTarget = MakeRefPtr<DrawTargetCairo>();

  if (newTarget->Init(aSurface, aSize, aFormat)) {
    retVal = newTarget;
  }
#endif
  return retVal.forget();
}

already_AddRefed<SourceSurface> Factory::CreateSourceSurfaceForCairoSurface(
    cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat aFormat) {
  if (aSize.width <= 0 || aSize.height <= 0) {
    gfxWarning() << "Can't create a SourceSurface without a valid size";
    return nullptr;
  }

#ifdef USE_CAIRO
  return MakeAndAddRef<SourceSurfaceCairo>(aSurface, aSize, aFormat);
#else
  return nullptr;
#endif
}

already_AddRefed<DataSourceSurface> Factory::CreateWrappingDataSourceSurface(
    uint8_t* aData, int32_t aStride, const IntSize& aSize,
    SurfaceFormat aFormat,
    SourceSurfaceDeallocator aDeallocator /* = nullptr */,
    void* aClosure /* = nullptr */) {
  // Just check for negative/zero size instead of the full AllowedSurfaceSize()
  // - since the data is already allocated we do not need to check for a
  // possible overflow - it already worked.
  if (aSize.width <= 0 || aSize.height <= 0) {
    return nullptr;
  }
  if (!aDeallocator && aClosure) {
    return nullptr;
  }

  MOZ_ASSERT(aData);

  RefPtr newSurf = MakeRefPtr<SourceSurfaceRawData>();
  newSurf->InitWrappingData(aData, aSize, aStride, aFormat, aDeallocator,
                            aClosure);

  return newSurf.forget();
}

already_AddRefed<DataSourceSurface> Factory::CreateDataSourceSurface(
    const IntSize& aSize, SurfaceFormat aFormat, bool aZero) {
  if (!AllowedSurfaceSize(aSize)) {
    gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
        << "Failed to allocate a surface due to invalid size (DSS) " << aSize;
    return nullptr;
  }

  // Skia doesn't support RGBX, so memset RGBX to 0xFF
  bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8;
  uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0;

  RefPtr newSurf = MakeRefPtr<SourceSurfaceAlignedRawData>();
  if (newSurf->Init(aSize, aFormat, clearSurface, clearValue)) {
    return newSurf.forget();
  }

  gfxWarning() << "CreateDataSourceSurface failed in init";
  return nullptr;
}

already_AddRefed<DataSourceSurface> Factory::CreateDataSourceSurfaceWithStride(
    const IntSize& aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero) {
  if (!AllowedSurfaceSize(aSize) ||
      aStride < aSize.width * BytesPerPixel(aFormat)) {
    gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
        << "CreateDataSourceSurfaceWithStride failed with bad stride "
        << aStride << ", " << aSize << ", " << aFormat;
    return nullptr;
  }

  // Skia doesn't support RGBX, so memset RGBX to 0xFF
  bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8;
  uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0;

  RefPtr newSurf = MakeRefPtr<SourceSurfaceAlignedRawData>();
  if (newSurf->Init(aSize, aFormat, clearSurface, clearValue, aStride)) {
    return newSurf.forget();
  }

  gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
      << "CreateDataSourceSurfaceWithStride failed to initialize " << aSize
      << ", " << aFormat << ", " << aStride << ", " << aZero;
  return nullptr;
}

already_AddRefed<DataSourceSurface> Factory::CopyDataSourceSurface(
    DataSourceSurface* aSource) {
  // Don't worry too much about speed.
  MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
             aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
             aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
             aSource->GetFormat() == SurfaceFormat::B8G8R8X8 ||
             aSource->GetFormat() == SurfaceFormat::A8);

  DataSourceSurface::ScopedMap srcMap(aSource, DataSourceSurface::READ);
  if (NS_WARN_IF(!srcMap.IsMapped())) {
    MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface.");
    return nullptr;
  }

  IntSize size = aSource->GetSize();
  SurfaceFormat format = aSource->GetFormat();

  RefPtr<DataSourceSurface> dst = CreateDataSourceSurfaceWithStride(
      size, format, srcMap.GetStride(), /* aZero */ false);
  if (NS_WARN_IF(!dst)) {
    return nullptr;
  }

  DataSourceSurface::ScopedMap dstMap(dst, DataSourceSurface::WRITE);
  if (NS_WARN_IF(!dstMap.IsMapped())) {
    MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface.");
    return nullptr;
  }

  SwizzleData(srcMap.GetData(), srcMap.GetStride(), format, dstMap.GetData(),
              dstMap.GetStride(), format, size);
  return dst.forget();
}

void Factory::CopyDataSourceSurface(DataSourceSurface* aSource,
                                    DataSourceSurface* aDest) {
  // Don't worry too much about speed.
  MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
  MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
             aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
             aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
             aSource->GetFormat() == SurfaceFormat::B8G8R8X8 ||
             aSource->GetFormat() == SurfaceFormat::A8);
  MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
             aDest->GetFormat() == SurfaceFormat::R8G8B8X8 ||
             aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
             aDest->GetFormat() == SurfaceFormat::B8G8R8X8 ||
             aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16 ||
             aDest->GetFormat() == SurfaceFormat::A8);

  DataSourceSurface::MappedSurface srcMap;
  DataSourceSurface::MappedSurface destMap;
  if (!aSource->Map(DataSourceSurface::MapType::READ, &srcMap) ||
      !aDest->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
    MOZ_ASSERT(false"CopyDataSourceSurface: Failed to map surface.");
    return;
  }

  SwizzleData(srcMap.mData, srcMap.mStride, aSource->GetFormat(), destMap.mData,
              destMap.mStride, aDest->GetFormat(), aSource->GetSize());

  aSource->Unmap();
  aDest->Unmap();
}

#ifdef WIN32

/* static */
already_AddRefed<DataSourceSurface>
Factory::CreateBGRA8DataSourceSurfaceForD3D11Texture(
    ID3D11Texture2D* aSrcTexture, uint32_t aArrayIndex,
    gfx::ColorSpace2 aColorSpace, gfx::ColorRange aColorRange,
    gfx::TransferFunction aTransferFunction) {
  D3D11_TEXTURE2D_DESC srcDesc = {0};
  aSrcTexture->GetDesc(&srcDesc);

  RefPtr<gfx::DataSourceSurface> destTexture =
      gfx::Factory::CreateDataSourceSurface(
          IntSize(srcDesc.Width, srcDesc.Height), gfx::SurfaceFormat::B8G8R8A8);
  if (NS_WARN_IF(!destTexture)) {
    return nullptr;
  }
  if (!ReadbackTexture(destTexture, aSrcTexture, aArrayIndex, aColorSpace,
                       aColorRange, aTransferFunction)) {
    return nullptr;
  }
  return destTexture.forget();
}

/* static */ nsresult Factory::CreateSdbForD3D11Texture(
    ID3D11Texture2D* aSrcTexture, const IntSize& aSrcSize,
    layers::SurfaceDescriptorBuffer& aSdBuffer,
    const std::function<layers::MemoryOrShmem(uint32_t)>& aAllocate) {
  D3D11_TEXTURE2D_DESC srcDesc = {0};
  aSrcTexture->GetDesc(&srcDesc);
  if (srcDesc.Width != uint32_t(aSrcSize.width) ||
      srcDesc.Height != uint32_t(aSrcSize.height) ||
      srcDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) {
    return NS_ERROR_NOT_IMPLEMENTED;
  }

  const auto format = gfx::SurfaceFormat::B8G8R8A8;
  uint8_t* buffer = nullptr;
  int32_t stride = 0;
  nsresult rv = layers::Image::AllocateSurfaceDescriptorBufferRgb(
      aSrcSize, format, buffer, aSdBuffer, stride, aAllocate);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (!ReadbackTexture(buffer, stride, aSrcTexture)) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

/* static */
bool Factory::ConvertSourceAndRetryReadback(
    DataSourceSurface* aDestCpuTexture, ID3D11Texture2D* aSrcTexture,
    uint32_t aArrayIndex, gfx::ColorSpace2 aColorSpace,
    gfx::ColorRange aColorRange, gfx::TransferFunction aTransferFunction) {
  MOZ_ASSERT(aDestCpuTexture);
  MOZ_ASSERT(aSrcTexture);

  RefPtr<ID3D11Device> device;
  aSrcTexture->GetDevice(getter_AddRefs(device));
  if (!device) {
    gfxWarning() << "Failed to get D3D11 device from source texture";
    return false;
  }

  CD3D11_TEXTURE2D_DESC desc;
  aSrcTexture->GetDesc(&desc);

  if (desc.Format != DXGI_FORMAT_NV12 && desc.Format != DXGI_FORMAT_P010 &&
      desc.Format != DXGI_FORMAT_P016) {
    gfxWarning() << "Unexpected DXGI format";
    return false;
  }

  desc = CD3D11_TEXTURE2D_DESC(
      DXGI_FORMAT_B8G8R8A8_UNORM, desc.Width, desc.Height, 11,
      D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);

  RefPtr<ID3D11Texture2D> newSrcTexture;
  HRESULT hr =
      device->CreateTexture2D(&desc, nullptr, getter_AddRefs(newSrcTexture));
  if (FAILED(hr)) {
    gfxWarning() << "Failed to create newSrcTexture: " << gfx::hexa(hr);
    return false;
  }

  RefPtr<layers::VideoProcessorD3D11> videoProcessor =
      layers::VideoProcessorD3D11::Create(device);
  if (!videoProcessor) {
    gfxWarning() << "Failed to create VideoProcessorD3D11";
    return false;
  }

  hr = videoProcessor->Init(aDestCpuTexture->GetSize());
  if (FAILED(hr)) {
    gfxWarning() << "Failed to init VideoProcessorD3D11" << gfx::hexa(hr);
    return false;
  }

  layers::VideoProcessorD3D11::InputTextureInfo info(
      aColorSpace, aColorRange, aTransferFunction, aArrayIndex, aSrcTexture);
  if (!videoProcessor->CallVideoProcessorBlt(info, newSrcTexture)) {
    gfxWarning() << "CallVideoProcessorBlt failed";
    return false;
  }

  return ReadbackTexture(aDestCpuTexture, newSrcTexture, 0, aColorSpace,
                         aColorRange, aTransferFunction);
}

/* static */
bool Factory::ReadbackTexture(DataSourceSurface* aDestCpuTexture,
                              ID3D11Texture2D* aSrcTexture,
                              uint32_t aArrayIndex,
                              gfx::ColorSpace2 aColorSpace,
                              gfx::ColorRange aColorRange,
                              gfx::TransferFunction aTransferFunction) {
  D3D11_TEXTURE2D_DESC srcDesc = {0};
  aSrcTexture->GetDesc(&srcDesc);

  // Special case: If the source and destination have different formats and the
  // destination is B8G8R8A8 then convert the source to B8G8R8A8 and readback.
  if ((srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat())) &&
      (aDestCpuTexture->GetFormat() == SurfaceFormat::B8G8R8A8)) {
    return ConvertSourceAndRetryReadback(aDestCpuTexture, aSrcTexture,
                                         aArrayIndex, aColorSpace, aColorRange,
                                         aTransferFunction);
  }

  if ((IntSize(srcDesc.Width, srcDesc.Height) != aDestCpuTexture->GetSize()) ||
      (srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat()))) {
    gfxWarning() << "Attempted readback between incompatible textures";
    return false;
  }

  gfx::DataSourceSurface::MappedSurface mappedSurface;
  if (!aDestCpuTexture->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
    return false;
  }

  MOZ_ASSERT(aArrayIndex == 0);

  bool ret =
      ReadbackTexture(mappedSurface.mData, mappedSurface.mStride, aSrcTexture);
  aDestCpuTexture->Unmap();
  return ret;
}

/* static */
bool Factory::ReadbackTexture(uint8_t* aDestData, int32_t aDestStride,
                              ID3D11Texture2D* aSrcTexture) {
  MOZ_ASSERT(aDestData && aDestStride && aSrcTexture);

  RefPtr<ID3D11Device> device;
  aSrcTexture->GetDevice(getter_AddRefs(device));
  if (!device) {
    gfxWarning() << "Failed to get D3D11 device from source texture";
    return false;
  }

  RefPtr<ID3D11DeviceContext> context;
  device->GetImmediateContext(getter_AddRefs(context));
  if (!context) {
    gfxWarning() << "Could not get an immediate D3D11 context";
    return false;
  }

  RefPtr<IDXGIKeyedMutex> mutex;
  HRESULT hr = aSrcTexture->QueryInterface(__uuidof(IDXGIKeyedMutex),
                                           (void**)getter_AddRefs(mutex));
  if (SUCCEEDED(hr) && mutex) {
    hr = mutex->AcquireSync(02000);
    if (hr != S_OK) {
      gfxWarning() << "Could not acquire DXGI surface lock in 2 seconds";
      return false;
    }
  }

  D3D11_TEXTURE2D_DESC srcDesc = {0};
  aSrcTexture->GetDesc(&srcDesc);
  srcDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  srcDesc.Usage = D3D11_USAGE_STAGING;
  srcDesc.BindFlags = 0;
  srcDesc.MiscFlags = 0;
  srcDesc.MipLevels = 1;
  RefPtr<ID3D11Texture2D> srcCpuTexture;
  hr =
      device->CreateTexture2D(&srcDesc, nullptr, getter_AddRefs(srcCpuTexture));
  if (FAILED(hr)) {
    gfxWarning() << "Could not create source texture for mapping";
    if (mutex) {
      mutex->ReleaseSync(0);
    }
    return false;
  }

  context->CopyResource(srcCpuTexture, aSrcTexture);

  if (mutex) {
    mutex->ReleaseSync(0);
    mutex = nullptr;
  }

  D3D11_MAPPED_SUBRESOURCE srcMap;
  hr = context->Map(srcCpuTexture, 0, D3D11_MAP_READ, 0, &srcMap);
  if (FAILED(hr)) {
    gfxWarning() << "Could not map source texture";
    return false;
  }

  uint32_t width = srcDesc.Width;
  uint32_t height = srcDesc.Height;
  int bpp = BytesPerPixel(gfx::ToPixelFormat(srcDesc.Format));
  for (uint32_t y = 0; y < height; y++) {
    memcpy(aDestData + aDestStride * y,
           (unsigned char*)(srcMap.pData) + srcMap.RowPitch * y, width * bpp);
  }

  context->Unmap(srcCpuTexture, 0);
  return true;
}

#endif  // WIN32

// static
void CriticalLogger::OutputMessage(const std::string& aString, int aLevel,
                                   bool aNoNewline) {
  if (Factory::GetLogForwarder()) {
    Factory::GetLogForwarder()->Log(aString);
  }

  BasicLogger::OutputMessage(aString, aLevel, aNoNewline);
}

void CriticalLogger::CrashAction(LogReason aReason) {
  if (Factory::GetLogForwarder()) {
    Factory::GetLogForwarder()->CrashAction(aReason);
  }
}

#ifdef WIN32
void LogWStr(const wchar_t* aWStr, std::stringstream& aOut) {
  int n =
      WideCharToMultiByte(CP_ACP, 0, aWStr, -1, nullptr, 0, nullptr, nullptr);
  if (n > 1) {
    std::vector<char> str(n);
    WideCharToMultiByte(CP_ACP, 0, aWStr, -1, str.data(), n, nullptr, nullptr);
    aOut << str.data();
  }
}
#endif

}  // namespace mozilla::gfx

Messung V0.5 in Prozent
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.10 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142