コード例 #1
0
nsresult
FT2FontEntry::CopyFontTable(uint32_t aTableTag,
                            FallibleTArray<uint8_t>& aBuffer)
{
    AutoFTFace face(this);
    if (!face) {
        return NS_ERROR_FAILURE;
    }

    FT_Error status;
    FT_ULong len = 0;
    status = FT_Load_Sfnt_Table(face, aTableTag, 0, nullptr, &len);
    if (status != FT_Err_Ok || len == 0) {
        return NS_ERROR_FAILURE;
    }

    if (!aBuffer.SetLength(len)) {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    uint8_t *buf = aBuffer.Elements();
    status = FT_Load_Sfnt_Table(face, aTableTag, 0, buf, &len);
    NS_ENSURE_TRUE(status == FT_Err_Ok, NS_ERROR_FAILURE);

    return NS_OK;
}
コード例 #2
0
already_AddRefed<DOMRequest>
MobileMessageManager::Delete(const Sequence<OwningLongOrSmsMessageOrMmsMessage>& aParams,
                             ErrorResult& aRv)
{
  const uint32_t size = aParams.Length();
  FallibleTArray<int32_t> idArray;
  if (!idArray.SetLength(size, fallible)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return nullptr;
  }

  DebugOnly<nsresult> rv;
  for (uint32_t i = 0; i < size; i++) {
    const OwningLongOrSmsMessageOrMmsMessage& element = aParams[i];
    int32_t &id = idArray[i];

    if (element.IsLong()) {
      id = element.GetAsLong();
    } else if (element.IsMmsMessage()) {
      id = element.GetAsMmsMessage()->Id();
    } else /*if (element.IsSmsMessage())*/ {
      id = element.GetAsSmsMessage()->Id();
    }
  }

  return Delete(idArray.Elements(), size, aRv);
}
コード例 #3
0
nsresult
GDIFontEntry::CopyFontTable(uint32_t aTableTag,
                            FallibleTArray<uint8_t>& aBuffer)
{
    if (!IsTrueType()) {
        return NS_ERROR_FAILURE;
    }

    AutoDC dc;
    AutoSelectFont font(dc.GetDC(), &mLogFont);
    if (font.IsValid()) {
        uint32_t tableSize =
            ::GetFontData(dc.GetDC(),
                          NativeEndian::swapToBigEndian(aTableTag),
                          0, nullptr, 0);
        if (tableSize != GDI_ERROR) {
            if (aBuffer.SetLength(tableSize)) {
                ::GetFontData(dc.GetDC(),
                              NativeEndian::swapToBigEndian(aTableTag), 0,
                              aBuffer.Elements(), tableSize);
                return NS_OK;
            }
            return NS_ERROR_OUT_OF_MEMORY;
        }
    }
    return NS_ERROR_FAILURE;
}
コード例 #4
0
ファイル: gfxContext.cpp プロジェクト: typ4rk/mozilla-history
bool
gfxContext::CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const
{
    int count = cairo_get_dash_count(mCairo);
    if (count <= 0 || !dashes.SetLength(count)) {
        return false;
    }
    cairo_get_dash(mCairo, dashes.Elements(), offset);
    return true;
}
コード例 #5
0
void
StructuredCloneHelper::MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray,
                                             ErrorResult& aRv)
{
  MOZ_ASSERT(mBuffer, "MoveBuffer() cannot be called without a Write().");

  if (NS_WARN_IF(!aArray.SetLength(BufferSize(), mozilla::fallible))) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  uint64_t* buffer;
  size_t size;
  mBuffer->steal(&buffer, &size);
  mBuffer = nullptr;

  memcpy(aArray.Elements(), buffer, size);
  js_free(buffer);
}
コード例 #6
0
/* static */ void
ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
                                       const nsACString& aString,
                                       const Base64URLDecodeOptions& aOptions,
                                       JS::MutableHandle<JSObject*> aRetval,
                                       ErrorResult& aRv)
{
  Base64URLDecodePaddingPolicy paddingPolicy;
  switch (aOptions.mPadding) {
    case Base64URLDecodePadding::Require:
      paddingPolicy = Base64URLDecodePaddingPolicy::Require;
      break;

    case Base64URLDecodePadding::Ignore:
      paddingPolicy = Base64URLDecodePaddingPolicy::Ignore;
      break;

    case Base64URLDecodePadding::Reject:
      paddingPolicy = Base64URLDecodePaddingPolicy::Reject;
      break;

    default:
      aRv.Throw(NS_ERROR_INVALID_ARG);
      return;
  }
  FallibleTArray<uint8_t> data;
  nsresult rv = mozilla::Base64URLDecode(aString, paddingPolicy, data);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv.Throw(rv);
    return;
  }

  JS::Rooted<JSObject*> buffer(aGlobal.Context(),
                               ArrayBuffer::Create(aGlobal.Context(),
                                                   data.Length(),
                                                   data.Elements()));
  if (NS_WARN_IF(!buffer)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }
  aRetval.set(buffer);
}
コード例 #7
0
// OTS drops the OT Layout tables when decoding a WOFF file, so retrieve them
// separately and cache them (unchecked) in the font entry; harfbuzz will
// sanitize them when it needs to use them.
static void
PreloadTableFromWOFF(const PRUint8* aFontData, PRUint32 aLength,
                     PRUint32 aTableTag, gfxFontEntry* aFontEntry)
{
    PRUint32 status = eWOFF_ok;
    PRUint32 len = woffGetTableSize(aFontData, aLength, aTableTag, &status);
    if (WOFF_SUCCESS(status) && len > 0) {
        FallibleTArray<PRUint8> buffer;
        if (!buffer.AppendElements(len)) {
            NS_WARNING("failed to cache font table - out of memory?");
            return;
        }
        woffGetTableToBuffer(aFontData, aLength, aTableTag,
                             buffer.Elements(), buffer.Length(),
                             &len, &status);
        if (WOFF_FAILURE(status)) {
            NS_WARNING("failed to cache font table - WOFF decoding error?");
            return;
        }
        aFontEntry->PreloadFontTable(aTableTag, buffer);
    }
}
コード例 #8
0
nsresult
FT2FontEntry::GetFontTable(PRUint32 aTableTag,
                           FallibleTArray<PRUint8>& aBuffer)
{
    // Ensure existence of mFTFace
    CairoFontFace();
    NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);

    FT_Error status;
    FT_ULong len = 0;
    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
    NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);

    if (!aBuffer.SetLength(len)) {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    PRUint8 *buf = aBuffer.Elements();
    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);

    return NS_OK;
}
コード例 #9
0
ファイル: gfxGDIFontList.cpp プロジェクト: mmmulani/v8monkey
nsresult
GDIFontEntry::GetFontTable(PRUint32 aTableTag,
                           FallibleTArray<PRUint8>& aBuffer)
{
    if (!IsTrueType()) {
        return NS_ERROR_FAILURE;
    }

    AutoDC dc;
    AutoSelectFont font(dc.GetDC(), &mLogFont);
    if (font.IsValid()) {
        PRInt32 tableSize =
            ::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0, NULL, NULL);
        if (tableSize != GDI_ERROR) {
            if (aBuffer.SetLength(tableSize)) {
                ::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0,
                              aBuffer.Elements(), tableSize);
                return NS_OK;
            }
            return NS_ERROR_OUT_OF_MEMORY;
        }
    }
    return NS_ERROR_FAILURE;
}
コード例 #10
0
PRBool
gfxFT2LockedFace::GetFontTable(PRUint32 aTag, FallibleTArray<PRUint8>& aBuffer)
{
    if (!mFace || !FT_IS_SFNT(mFace))
        return PR_FALSE;

    FT_ULong length = 0;
    // TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
    FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
    if (error != 0)
        return PR_FALSE;

    if (NS_UNLIKELY(length > static_cast<FallibleTArray<PRUint8>::size_type>(-1))
        || NS_UNLIKELY(!aBuffer.SetLength(length)))
        return PR_FALSE;
        
    error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
    if (NS_UNLIKELY(error != 0)) {
        aBuffer.Clear();
        return PR_FALSE;
    }

    return PR_TRUE;
}
コード例 #11
0
nsresult
FT2FontEntry::GetFontTable(uint32_t aTableTag,
                           FallibleTArray<uint8_t>& aBuffer)
{
    // Ensure existence of mFTFace
    CairoFontFace();
    NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);

    FT_Error status;
    FT_ULong len = 0;
    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nullptr, &len);
    if (status != FT_Err_Ok || len == 0) {
        return NS_ERROR_FAILURE;
    }

    if (!aBuffer.SetLength(len)) {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    uint8_t *buf = aBuffer.Elements();
    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
    NS_ENSURE_TRUE(status == FT_Err_Ok, NS_ERROR_FAILURE);

    return NS_OK;
}
コード例 #12
0
bool
gfxFT2LockedFace::GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer)
{
    if (!mFace || !FT_IS_SFNT(mFace))
        return false;

    FT_ULong length = 0;
    // TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
    FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
    if (error != 0)
        return false;

    if (MOZ_UNLIKELY(length > static_cast<FallibleTArray<uint8_t>::size_type>(-1))
        || MOZ_UNLIKELY(!aBuffer.SetLength(length)))
        return false;
        
    error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
    if (MOZ_UNLIKELY(error != 0)) {
        aBuffer.Clear();
        return false;
    }

    return true;
}
コード例 #13
0
ファイル: ChromeUtils.cpp プロジェクト: MekliCZ/positron
/* static */ void
ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
                                       const nsACString& aString,
                                       const Base64URLDecodeOptions& aOptions,
                                       JS::MutableHandle<JSObject*> aRetval,
                                       ErrorResult& aRv)
{
  FallibleTArray<uint8_t> data;
  nsresult rv = mozilla::Base64URLDecode(aString, aOptions, data);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv.Throw(rv);
    return;
  }

  JS::Rooted<JSObject*> buffer(aGlobal.Context(),
                               ArrayBuffer::Create(aGlobal.Context(),
                                                   data.Length(),
                                                   data.Elements()));
  if (NS_WARN_IF(!buffer)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }
  aRetval.set(buffer);
}
コード例 #14
0
gfxFontEntry* 
gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 
                                 const uint8_t *aFontData,
                                 uint32_t aLength)
{
    // MakePlatformFont is responsible for deleting the font data with NS_Free
    // so we set up a stack object to ensure it is freed even if we take an
    // early exit
    struct FontDataDeleter {
        FontDataDeleter(const uint8_t *aFontData)
            : mFontData(aFontData) { }
        ~FontDataDeleter() { NS_Free((void*)mFontData); }
        const uint8_t *mFontData;
    };
    FontDataDeleter autoDelete(aFontData);

    bool hasVertical;
    bool isCFF = gfxFontUtils::IsCffFont(aFontData, hasVertical);

    nsresult rv;
    HANDLE fontRef = nullptr;
    bool isEmbedded = false;

    nsAutoString uniqueName;
    rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
    if (NS_FAILED(rv))
        return nullptr;

    // for TTF fonts, first try using the t2embed library if available
    if (!isCFF && TTLoadEmbeddedFontPtr && TTDeleteEmbeddedFontPtr) {
        // TrueType-style glyphs, use EOT library
        AutoFallibleTArray<uint8_t,2048> eotHeader;
        uint8_t *buffer;
        uint32_t eotlen;

        isEmbedded = true;
        uint32_t nameLen = NS_MIN<uint32_t>(uniqueName.Length(), LF_FACESIZE - 1);
        nsAutoString fontName(Substring(uniqueName, 0, nameLen));
        
        FontDataOverlay overlayNameData = {0, 0, 0};

        rv = gfxFontUtils::MakeEOTHeader(aFontData, aLength, &eotHeader, 
                                         &overlayNameData);
        if (NS_SUCCEEDED(rv)) {

            // load in embedded font data
            eotlen = eotHeader.Length();
            buffer = reinterpret_cast<uint8_t*> (eotHeader.Elements());
            
            int32_t ret;
            ULONG privStatus, pulStatus;
            EOTFontStreamReader eotReader(aFontData, aLength, buffer, eotlen,
                                          &overlayNameData);

            ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
                                        LICENSE_PREVIEWPRINT, &pulStatus,
                                        EOTFontStreamReader::ReadEOTStream,
                                        &eotReader,
                                        (PRUnichar*)(fontName.get()), 0, 0);
            if (ret != E_NONE) {
                fontRef = nullptr;
                char buf[256];
                sprintf(buf, "font (%s) not loaded using TTLoadEmbeddedFont - error %8.8x",
                        NS_ConvertUTF16toUTF8(aProxyEntry->Name()).get(), ret);
                NS_WARNING(buf);
            }
        }
    }

    // load CFF fonts or fonts that failed with t2embed loader
    if (fontRef == nullptr) {
        // Postscript-style glyphs, swizzle name table, load directly
        FallibleTArray<uint8_t> newFontData;

        isEmbedded = false;
        rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);

        if (NS_FAILED(rv))
            return nullptr;
        
        DWORD numFonts = 0;

        uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements());
        uint32_t fontLength = newFontData.Length();
        NS_ASSERTION(fontData, "null font data after renaming");

        // http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
        // "A font that is added by AddFontMemResourceEx is always private 
        //  to the process that made the call and is not enumerable."
        fontRef = AddFontMemResourceEx(fontData, fontLength, 
                                       0 /* reserved */, &numFonts);
        if (!fontRef)
            return nullptr;

        // only load fonts with a single face contained in the data
        // AddFontMemResourceEx generates an additional face name for
        // vertical text if the font supports vertical writing
        if (fontRef && numFonts != 1 + !!hasVertical) {
            RemoveFontMemResourceEx(fontRef);
            return nullptr;
        }
    }

    // make a new font entry using the unique name
    WinUserFontData *winUserFontData = new WinUserFontData(fontRef, isEmbedded);
    uint16_t w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);

    GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName, 
        gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, 
        uint32_t(aProxyEntry->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL), 
        w, aProxyEntry->mStretch, winUserFontData, false);

    if (!fe)
        return fe;

    fe->mIsUserFont = true;

    // Uniscribe doesn't place CFF fonts loaded privately 
    // via AddFontMemResourceEx on XP/Vista
    if (isCFF && gfxWindowsPlatform::WindowsOSVersion() 
                 < gfxWindowsPlatform::kWindows7) {
        fe->mForceGDI = true;
    }
 
    return fe;
}
コード例 #15
0
gfxFontEntry* 
gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 
                                 const uint8_t *aFontData,
                                 uint32_t aLength)
{
    // MakePlatformFont is responsible for deleting the font data with NS_Free
    // so we set up a stack object to ensure it is freed even if we take an
    // early exit
    struct FontDataDeleter {
        FontDataDeleter(const uint8_t *aFontData)
            : mFontData(aFontData) { }
        ~FontDataDeleter() { NS_Free((void*)mFontData); }
        const uint8_t *mFontData;
    };
    FontDataDeleter autoDelete(aFontData);

    bool isCFF = gfxFontUtils::IsCffFont(aFontData);

    nsresult rv;
    HANDLE fontRef = nullptr;

    nsAutoString uniqueName;
    rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
    if (NS_FAILED(rv))
        return nullptr;

    FallibleTArray<uint8_t> newFontData;

    rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);

    if (NS_FAILED(rv))
        return nullptr;
        
    DWORD numFonts = 0;

    uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements());
    uint32_t fontLength = newFontData.Length();
    NS_ASSERTION(fontData, "null font data after renaming");

    // http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
    // "A font that is added by AddFontMemResourceEx is always private 
    //  to the process that made the call and is not enumerable."
    fontRef = AddFontMemResourceEx(fontData, fontLength, 
                                    0 /* reserved */, &numFonts);
    if (!fontRef)
        return nullptr;

    // only load fonts with a single face contained in the data
    // AddFontMemResourceEx generates an additional face name for
    // vertical text if the font supports vertical writing but since
    // the font is referenced via the name this can be ignored
    if (fontRef && numFonts > 2) {
        RemoveFontMemResourceEx(fontRef);
        return nullptr;
    }

    // make a new font entry using the unique name
    WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
    uint16_t w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);

    GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName, 
        gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, 
        uint32_t(aProxyEntry->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL), 
        w, aProxyEntry->mStretch, winUserFontData, false);

    if (!fe)
        return fe;

    fe->mIsUserFont = true;

    // Uniscribe doesn't place CFF fonts loaded privately 
    // via AddFontMemResourceEx on XP/Vista
    if (isCFF && !IsWin7OrLater()) {
        fe->mForceGDI = true;
    }

    return fe;
}
コード例 #16
0
nsresult
gfxDWriteFontEntry::GetFontTable(PRUint32 aTableTag,
                                 FallibleTArray<PRUint8> &aBuffer)
{
    gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList();

    // don't use GDI table loading for symbol fonts or for
    // italic fonts in Arabic-script system locales because of
    // potential cmap discrepancies, see bug 629386
    if (mFont && pFontList->UseGDIFontTableAccess() &&
        !(mItalic && UsingArabicScriptSystemLocale()) &&
        !mFont->IsSymbolFont())
    {
        LOGFONTW logfont = { 0 };
        if (!InitLogFont(mFont, &logfont))
            return NS_ERROR_FAILURE;

        AutoDC dc;
        AutoSelectFont font(dc.GetDC(), &logfont);
        if (font.IsValid()) {
            PRInt32 tableSize =
                ::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0, NULL, NULL);
            if (tableSize != GDI_ERROR) {
                if (aBuffer.SetLength(tableSize)) {
                    ::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0,
                                  aBuffer.Elements(), aBuffer.Length());
                    return NS_OK;
                }
                return NS_ERROR_OUT_OF_MEMORY;
            }
        }
        return NS_ERROR_FAILURE;
    }

    HRESULT hr;
    nsresult rv;
    nsRefPtr<IDWriteFontFace> fontFace;

    rv = CreateFontFace(getter_AddRefs(fontFace));

    if (NS_FAILED(rv)) {
        return rv;
    }

    PRUint8 *tableData;
    PRUint32 len;
    void *tableContext = NULL;
    BOOL exists;
    hr = fontFace->TryGetFontTable(NS_SWAP32(aTableTag),
                                   (const void**)&tableData,
                                   &len,
                                   &tableContext,
                                   &exists);

    if (FAILED(hr) || !exists) {
        return NS_ERROR_FAILURE;
    }
    if (!aBuffer.SetLength(len)) {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    memcpy(aBuffer.Elements(), tableData, len);
    if (tableContext) {
        fontFace->ReleaseFontTable(&tableContext);
    }
    return NS_OK;
}
コード例 #17
0
nsresult
gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag,
                                  FallibleTArray<uint8_t> &aBuffer)
{
    gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList();

    // Don't use GDI table loading for symbol fonts or for
    // italic fonts in Arabic-script system locales because of
    // potential cmap discrepancies, see bug 629386.
    // Ditto for Hebrew, bug 837498.
    if (mFont && pFontList->UseGDIFontTableAccess() &&
        !(mItalic && UsingArabicOrHebrewScriptSystemLocale()) &&
        !mFont->IsSymbolFont())
    {
        LOGFONTW logfont = { 0 };
        if (!InitLogFont(mFont, &logfont))
            return NS_ERROR_FAILURE;

        AutoDC dc;
        AutoSelectFont font(dc.GetDC(), &logfont);
        if (font.IsValid()) {
            uint32_t tableSize =
                ::GetFontData(dc.GetDC(),
                              NativeEndian::swapToBigEndian(aTableTag), 0,
                              NULL, 0);
            if (tableSize != GDI_ERROR) {
                if (aBuffer.SetLength(tableSize)) {
                    ::GetFontData(dc.GetDC(),
                                  NativeEndian::swapToBigEndian(aTableTag), 0,
                                  aBuffer.Elements(), aBuffer.Length());
                    return NS_OK;
                }
                return NS_ERROR_OUT_OF_MEMORY;
            }
        }
        return NS_ERROR_FAILURE;
    }

    nsRefPtr<IDWriteFontFace> fontFace;
    nsresult rv = CreateFontFace(getter_AddRefs(fontFace));
    if (NS_FAILED(rv)) {
        return rv;
    }

    uint8_t *tableData;
    uint32_t len;
    void *tableContext = NULL;
    BOOL exists;
    HRESULT hr =
        fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag),
                                  (const void**)&tableData, &len,
                                  &tableContext, &exists);
    if (FAILED(hr) || !exists) {
        return NS_ERROR_FAILURE;
    }

    if (aBuffer.SetLength(len)) {
        memcpy(aBuffer.Elements(), tableData, len);
        rv = NS_OK;
    } else {
        rv = NS_ERROR_OUT_OF_MEMORY;
    }

    if (tableContext) {
        fontFace->ReleaseFontTable(&tableContext);
    }

    return rv;
}