2013-07-19 19:08:33 +04:00
|
|
|
/* 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/. */
|
2012-09-06 08:57:54 +04:00
|
|
|
|
|
|
|
#include "gfxSVGGlyphs.h"
|
|
|
|
|
2016-07-22 14:07:39 +03:00
|
|
|
#include "mozilla/SVGContextPaint.h"
|
2012-09-06 08:57:54 +04:00
|
|
|
#include "nsError.h"
|
2013-08-22 10:30:55 +04:00
|
|
|
#include "nsIDOMDocument.h"
|
2012-09-06 08:57:54 +04:00
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsICategoryManager.h"
|
|
|
|
#include "nsIDocumentLoaderFactory.h"
|
|
|
|
#include "nsIContentViewer.h"
|
|
|
|
#include "nsIStreamListener.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsNetUtil.h"
|
2017-03-22 13:38:40 +03:00
|
|
|
#include "NullPrincipal.h"
|
2012-09-06 08:57:54 +04:00
|
|
|
#include "nsIInputStream.h"
|
|
|
|
#include "nsStringStream.h"
|
|
|
|
#include "nsStreamUtils.h"
|
|
|
|
#include "nsIPrincipal.h"
|
2015-08-18 10:01:42 +03:00
|
|
|
#include "mozilla/BasePrincipal.h"
|
2013-08-30 21:16:32 +04:00
|
|
|
#include "mozilla/dom/Element.h"
|
2014-07-10 10:56:37 +04:00
|
|
|
#include "mozilla/LoadInfo.h"
|
2012-12-12 03:15:07 +04:00
|
|
|
#include "nsSVGUtils.h"
|
2013-06-10 16:25:12 +04:00
|
|
|
#include "nsHostObjectProtocolHandler.h"
|
|
|
|
#include "nsContentUtils.h"
|
2013-08-19 17:08:45 +04:00
|
|
|
#include "gfxFont.h"
|
|
|
|
#include "nsSMILAnimationController.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
#include "gfxContext.h"
|
2013-05-16 20:29:20 +04:00
|
|
|
#include "harfbuzz/hb.h"
|
2016-10-13 10:04:15 +03:00
|
|
|
#include "mozilla/dom/ImageTracker.h"
|
2012-09-06 08:57:54 +04:00
|
|
|
|
|
|
|
#define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
|
|
|
|
#define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8")
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
typedef mozilla::dom::Element Element;
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2015-09-25 03:50:46 +03:00
|
|
|
/* static */ const Color SimpleTextContextPaint::sZero = Color();
|
2012-09-06 08:58:47 +04:00
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry)
|
|
|
|
: mSVGData(aSVGTable)
|
|
|
|
, mFontEntry(aFontEntry)
|
2012-09-06 08:57:54 +04:00
|
|
|
{
|
2013-08-19 17:08:43 +04:00
|
|
|
unsigned int length;
|
|
|
|
const char* svgData = hb_blob_get_data(mSVGData, &length);
|
2013-05-16 20:29:20 +04:00
|
|
|
mHeader = reinterpret_cast<const Header*>(svgData);
|
2013-08-19 17:08:43 +04:00
|
|
|
mDocIndex = nullptr;
|
|
|
|
|
|
|
|
if (sizeof(Header) <= length && uint16_t(mHeader->mVersion) == 0 &&
|
|
|
|
uint64_t(mHeader->mDocIndexOffset) + 2 <= length) {
|
|
|
|
const DocIndex* docIndex = reinterpret_cast<const DocIndex*>
|
|
|
|
(svgData + mHeader->mDocIndexOffset);
|
|
|
|
// Limit the number of documents to avoid overflow
|
|
|
|
if (uint64_t(mHeader->mDocIndexOffset) + 2 +
|
|
|
|
uint16_t(docIndex->mNumEntries) * sizeof(IndexEntry) <= length) {
|
|
|
|
mDocIndex = docIndex;
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 08:58:47 +04:00
|
|
|
}
|
|
|
|
|
2013-05-16 20:29:20 +04:00
|
|
|
gfxSVGGlyphs::~gfxSVGGlyphs()
|
2012-09-06 08:58:47 +04:00
|
|
|
{
|
2013-05-16 20:29:20 +04:00
|
|
|
hb_blob_destroy(mSVGData);
|
2012-09-06 08:58:47 +04:00
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
void
|
|
|
|
gfxSVGGlyphs::DidRefresh()
|
|
|
|
{
|
|
|
|
mFontEntry->NotifyGlyphsChanged();
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
/*
|
|
|
|
* Comparison operator for finding a range containing a given glyph ID. Simply
|
|
|
|
* checks whether |key| is less (greater) than every element of |range|, in
|
|
|
|
* which case return |key| < |range| (|key| > |range|). Otherwise |key| is in
|
|
|
|
* |range|, in which case return equality.
|
|
|
|
* The total ordering here is guaranteed by
|
|
|
|
* (1) the index ranges being disjoint; and
|
|
|
|
* (2) the (sole) key always being a singleton, so intersection => containment
|
|
|
|
* (note that this is wrong if we have more than one intersection or two
|
|
|
|
* sets intersecting of size > 1 -- so... don't do that)
|
|
|
|
*/
|
|
|
|
/* static */ int
|
2013-06-12 13:48:35 +04:00
|
|
|
gfxSVGGlyphs::CompareIndexEntries(const void *aKey, const void *aEntry)
|
2012-09-06 08:58:47 +04:00
|
|
|
{
|
2013-06-12 13:48:35 +04:00
|
|
|
const uint32_t key = *(uint32_t*)aKey;
|
|
|
|
const IndexEntry *entry = (const IndexEntry*)aEntry;
|
2012-09-06 08:58:47 +04:00
|
|
|
|
2013-06-12 13:48:35 +04:00
|
|
|
if (key < uint16_t(entry->mStartGlyph)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (key > uint16_t(entry->mEndGlyph)) {
|
|
|
|
return 1;
|
|
|
|
}
|
2012-09-06 08:58:47 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxSVGGlyphsDocument *
|
|
|
|
gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId)
|
|
|
|
{
|
2013-08-19 17:08:43 +04:00
|
|
|
if (!mDocIndex) {
|
|
|
|
// Invalid table
|
2013-08-19 17:08:43 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:43 +04:00
|
|
|
IndexEntry *entry = (IndexEntry*)bsearch(&aGlyphId, mDocIndex->mEntries,
|
|
|
|
uint16_t(mDocIndex->mNumEntries),
|
2012-09-06 08:58:47 +04:00
|
|
|
sizeof(IndexEntry),
|
|
|
|
CompareIndexEntries);
|
|
|
|
if (!entry) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxSVGGlyphsDocument *result = mGlyphDocs.Get(entry->mDocOffset);
|
|
|
|
|
|
|
|
if (!result) {
|
2013-08-19 17:08:43 +04:00
|
|
|
unsigned int length;
|
|
|
|
const uint8_t *data = (const uint8_t*)hb_blob_get_data(mSVGData, &length);
|
|
|
|
if (entry->mDocOffset > 0 &&
|
|
|
|
uint64_t(mHeader->mDocIndexOffset) + entry->mDocOffset + entry->mDocLength <= length) {
|
|
|
|
result = new gfxSVGGlyphsDocument(data + mHeader->mDocIndexOffset + entry->mDocOffset,
|
2013-08-19 17:08:45 +04:00
|
|
|
entry->mDocLength, this);
|
2013-08-19 17:08:43 +04:00
|
|
|
mGlyphDocs.Put(entry->mDocOffset, result);
|
|
|
|
}
|
2012-09-06 08:58:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
gfxSVGGlyphsDocument::SetupPresentation()
|
|
|
|
{
|
2012-09-06 08:57:54 +04:00
|
|
|
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
2017-08-21 13:01:27 +03:00
|
|
|
nsCString contractId;
|
2012-09-06 08:58:47 +04:00
|
|
|
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "image/svg+xml", getter_Copies(contractId));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2017-08-21 13:01:27 +03:00
|
|
|
nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
|
|
|
|
do_GetService(contractId.get());
|
2012-09-06 08:57:54 +04:00
|
|
|
NS_ASSERTION(docLoaderFactory, "Couldn't get DocumentLoaderFactory");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContentViewer> viewer;
|
2012-09-06 08:58:47 +04:00
|
|
|
rv = docLoaderFactory->CreateInstanceForDocument(nullptr, mDocument, nullptr, getter_AddRefs(viewer));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2015-05-07 12:07:31 +03:00
|
|
|
rv = viewer->Init(nullptr, gfx::IntRect(0, 0, 1000, 1000));
|
2012-09-06 08:57:54 +04:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = viewer->Open(nullptr, nullptr);
|
2012-09-06 08:58:47 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
rv = viewer->GetPresShell(getter_AddRefs(presShell));
|
2012-09-06 08:58:47 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2013-08-19 17:08:45 +04:00
|
|
|
nsPresContext* presContext = presShell->GetPresContext();
|
|
|
|
presContext->SetIsGlyph(true);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2012-09-07 08:16:09 +04:00
|
|
|
if (!presShell->DidInitialize()) {
|
2013-08-19 17:08:45 +04:00
|
|
|
nsRect rect = presContext->GetVisibleArea();
|
2012-09-07 08:16:09 +04:00
|
|
|
rv = presShell->Initialize(rect.width, rect.height);
|
2012-09-06 08:58:47 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2017-01-05 10:31:56 +03:00
|
|
|
mDocument->FlushPendingNotifications(FlushType::Layout);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2017-08-31 09:00:39 +03:00
|
|
|
if (mDocument->HasAnimationController()) {
|
|
|
|
mDocument->GetAnimationController()
|
|
|
|
->Resume(nsSMILTimeContainer::PAUSE_IMAGE);
|
2013-08-19 17:08:45 +04:00
|
|
|
}
|
2016-10-13 10:04:19 +03:00
|
|
|
mDocument->ImageTracker()->SetAnimatingState(true);
|
2013-08-19 17:08:45 +04:00
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
mViewer = viewer;
|
|
|
|
mPresShell = presShell;
|
2013-08-19 17:08:45 +04:00
|
|
|
mPresShell->AddPostRefreshObserver(this);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
return NS_OK;
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
void
|
|
|
|
gfxSVGGlyphsDocument::DidRefresh()
|
|
|
|
{
|
|
|
|
mOwner->DidRefresh();
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:57:54 +04:00
|
|
|
/**
|
|
|
|
* Walk the DOM tree to find all glyph elements and insert them into the lookup
|
|
|
|
* table
|
|
|
|
* @param aElem The element to search from
|
|
|
|
*/
|
|
|
|
void
|
2013-08-19 17:08:43 +04:00
|
|
|
gfxSVGGlyphsDocument::FindGlyphElements(Element *aElem)
|
2012-09-06 08:57:54 +04:00
|
|
|
{
|
|
|
|
for (nsIContent *child = aElem->GetLastChild(); child;
|
|
|
|
child = child->GetPreviousSibling()) {
|
|
|
|
if (!child->IsElement()) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-08-19 17:08:43 +04:00
|
|
|
FindGlyphElements(child->AsElement());
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
InsertGlyphId(aElem);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If there exists an SVG glyph with the specified glyph id, render it and return true
|
|
|
|
* If no such glyph exists, or in the case of an error return false
|
|
|
|
* @param aContext The thebes aContext to draw to
|
|
|
|
* @param aGlyphId The glyph id
|
|
|
|
* @return true iff rendering succeeded
|
|
|
|
*/
|
2017-05-18 23:03:41 +03:00
|
|
|
void
|
2012-09-06 08:57:54 +04:00
|
|
|
gfxSVGGlyphs::RenderGlyph(gfxContext *aContext, uint32_t aGlyphId,
|
2016-07-22 16:56:09 +03:00
|
|
|
SVGContextPaint* aContextPaint)
|
2012-09-06 08:57:54 +04:00
|
|
|
{
|
|
|
|
gfxContextAutoSaveRestore aContextRestorer(aContext);
|
|
|
|
|
|
|
|
Element *glyph = mGlyphIdMap.Get(aGlyphId);
|
2017-05-18 23:03:41 +03:00
|
|
|
MOZ_ASSERT(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
|
2012-09-06 08:57:54 +04:00
|
|
|
|
2016-07-21 16:33:11 +03:00
|
|
|
AutoSetRestoreSVGContextPaint autoSetRestore(aContextPaint, glyph->OwnerDoc());
|
|
|
|
|
2017-05-18 23:03:41 +03:00
|
|
|
nsSVGUtils::PaintSVGGlyph(glyph, aContext);
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:46 +04:00
|
|
|
bool
|
|
|
|
gfxSVGGlyphs::GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
|
|
|
|
gfxRect *aResult)
|
|
|
|
{
|
|
|
|
Element *glyph = mGlyphIdMap.Get(aGlyphId);
|
|
|
|
NS_ASSERTION(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
|
|
|
|
|
2012-12-12 03:15:07 +04:00
|
|
|
return nsSVGUtils::GetSVGGlyphExtents(glyph, aSVGToAppSpace, aResult);
|
2012-09-06 08:58:46 +04:00
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
Element *
|
|
|
|
gfxSVGGlyphs::GetGlyphElement(uint32_t aGlyphId)
|
|
|
|
{
|
|
|
|
Element *elem;
|
|
|
|
|
|
|
|
if (!mGlyphIdMap.Get(aGlyphId, &elem)) {
|
|
|
|
elem = nullptr;
|
|
|
|
if (gfxSVGGlyphsDocument *set = FindOrCreateGlyphsDocument(aGlyphId)) {
|
|
|
|
elem = set->GetGlyphElement(aGlyphId);
|
|
|
|
}
|
|
|
|
mGlyphIdMap.Put(aGlyphId, elem);
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:57:54 +04:00
|
|
|
bool
|
|
|
|
gfxSVGGlyphs::HasSVGGlyph(uint32_t aGlyphId)
|
|
|
|
{
|
2012-09-06 08:58:47 +04:00
|
|
|
return !!GetGlyphElement(aGlyphId);
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2016-05-03 14:14:35 +03:00
|
|
|
size_t
|
|
|
|
gfxSVGGlyphs::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
|
|
{
|
|
|
|
// We don't include the size of mSVGData here, because (depending on the
|
|
|
|
// font backend implementation) it will either wrap a block of data owned
|
|
|
|
// by the system (and potentially shared), or a table that's in our font
|
|
|
|
// table cache and therefore already counted.
|
|
|
|
size_t result = aMallocSizeOf(this)
|
|
|
|
+ mGlyphDocs.ShallowSizeOfExcludingThis(aMallocSizeOf)
|
|
|
|
+ mGlyphIdMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mGlyphDocs.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
result += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
Element *
|
|
|
|
gfxSVGGlyphsDocument::GetGlyphElement(uint32_t aGlyphId)
|
|
|
|
{
|
|
|
|
return mGlyphIdMap.Get(aGlyphId);
|
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer,
|
|
|
|
uint32_t aBufLen,
|
|
|
|
gfxSVGGlyphs *aSVGGlyphs)
|
|
|
|
: mOwner(aSVGGlyphs)
|
2012-09-06 08:58:47 +04:00
|
|
|
{
|
|
|
|
ParseDocument(aBuffer, aBufLen);
|
|
|
|
if (!mDocument) {
|
|
|
|
NS_WARNING("Could not parse SVG glyphs document");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element *root = mDocument->GetRootElement();
|
|
|
|
if (!root) {
|
|
|
|
NS_WARNING("Could not parse SVG glyphs document");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = SetupPresentation();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Couldn't setup presentation for SVG glyphs document");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:43 +04:00
|
|
|
FindGlyphElements(root);
|
2012-09-06 08:58:47 +04:00
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
gfxSVGGlyphsDocument::~gfxSVGGlyphsDocument()
|
|
|
|
{
|
|
|
|
if (mDocument) {
|
2016-06-18 19:03:11 +03:00
|
|
|
mDocument->OnPageHide(false, nullptr);
|
2013-08-19 17:08:45 +04:00
|
|
|
}
|
|
|
|
if (mPresShell) {
|
|
|
|
mPresShell->RemovePostRefreshObserver(this);
|
|
|
|
}
|
|
|
|
if (mViewer) {
|
2016-06-18 20:32:19 +03:00
|
|
|
mViewer->Close(nullptr);
|
2013-08-19 17:08:45 +04:00
|
|
|
mViewer->Destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
static nsresult
|
2013-05-16 20:29:20 +04:00
|
|
|
CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
|
2012-09-06 08:57:54 +04:00
|
|
|
nsCOMPtr<nsIInputStream> &aResult)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
|
|
|
reinterpret_cast<const char *>(aBuffer),
|
|
|
|
aBufLen, NS_ASSIGNMENT_DEPEND);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> aBufferedStream;
|
|
|
|
if (!NS_InputStreamIsBuffered(stream)) {
|
|
|
|
rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
stream = aBufferedStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResult = stream;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
nsresult
|
2013-05-16 20:29:20 +04:00
|
|
|
gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
|
2012-09-06 08:57:54 +04:00
|
|
|
{
|
|
|
|
// Mostly pulled from nsDOMParser::ParseFromStream
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
nsresult rv = CreateBufferedStream(aBuffer, aBufLen, stream);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-06-10 16:25:12 +04:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsHostObjectProtocolHandler::GenerateURIString(NS_LITERAL_CSTRING(FONTTABLEURI_SCHEME),
|
2014-08-31 14:40:11 +04:00
|
|
|
nullptr,
|
2013-06-10 16:25:12 +04:00
|
|
|
mSVGGlyphsDocumentURI);
|
|
|
|
|
|
|
|
rv = NS_NewURI(getter_AddRefs(uri), mSVGGlyphsDocumentURI);
|
2012-09-06 08:57:54 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2017-03-22 13:38:40 +03:00
|
|
|
nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
|
2012-09-06 08:57:54 +04:00
|
|
|
|
Bug 1389300 - Inherit style backend into NS_NewDOMDocument. r=smaug,r=heycam
Our current machinery for enabling stylo requires a docshell - if there isn't
one, we default to the Gecko style system.
When getComputedStyle operates on an element without a presshell, it uses the
caller's presshell instead. If the element has previously been styled with
one style system (but no longer has a presshell), and the caller uses a
different style backend, using the caller's style system can cause crashes when
we pull bits of cached data off the DOM (like cached style attributes).
So we want to throw when window.getComputedStyle(element) is called for a
(window, element) pair with different style backends (which is what the next
patch in this bug does).
However, that causes a few failures where stylo-backed documents try to do
getComputedStyle on an XHR document (which, without a docshell, will use the
gecko style system).
So this patch does some work to propagate the creator's style backend into
various docshell-less documents. This should allow both chrome (which uses gecko)
and content (which uses stylo) to use getComputedStyle on the response document
for XHRs they create.
Note that the second patch in this bug will make
chromeWin.getComputedStyle(contentObj) throw. If we discover code that does
that, we can just make it invoke the content's getComputedStyle method over Xrays.
MozReview-Commit-ID: 5OsmHJKq5Ui
2017-08-15 05:50:28 +03:00
|
|
|
auto styleBackend = nsLayoutUtils::StyloEnabled() ? StyleBackendType::Servo
|
|
|
|
: StyleBackendType::Gecko;
|
2012-09-06 08:57:54 +04:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
rv = NS_NewDOMDocument(getter_AddRefs(domDoc),
|
|
|
|
EmptyString(), // aNamespaceURI
|
|
|
|
EmptyString(), // aQualifiedName
|
|
|
|
nullptr, // aDoctype
|
|
|
|
uri, uri, principal,
|
|
|
|
false, // aLoadedAsData
|
|
|
|
nullptr, // aEventObject
|
Bug 1389300 - Inherit style backend into NS_NewDOMDocument. r=smaug,r=heycam
Our current machinery for enabling stylo requires a docshell - if there isn't
one, we default to the Gecko style system.
When getComputedStyle operates on an element without a presshell, it uses the
caller's presshell instead. If the element has previously been styled with
one style system (but no longer has a presshell), and the caller uses a
different style backend, using the caller's style system can cause crashes when
we pull bits of cached data off the DOM (like cached style attributes).
So we want to throw when window.getComputedStyle(element) is called for a
(window, element) pair with different style backends (which is what the next
patch in this bug does).
However, that causes a few failures where stylo-backed documents try to do
getComputedStyle on an XHR document (which, without a docshell, will use the
gecko style system).
So this patch does some work to propagate the creator's style backend into
various docshell-less documents. This should allow both chrome (which uses gecko)
and content (which uses stylo) to use getComputedStyle on the response document
for XHRs they create.
Note that the second patch in this bug will make
chromeWin.getComputedStyle(contentObj) throw. If we discover code that does
that, we can just make it invoke the content's getComputedStyle method over Xrays.
MozReview-Commit-ID: 5OsmHJKq5Ui
2017-08-15 05:50:28 +03:00
|
|
|
DocumentFlavorSVG,
|
|
|
|
styleBackend);
|
2012-09-06 08:57:54 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-06-10 16:25:12 +04:00
|
|
|
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDoc));
|
|
|
|
if (!document) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-09-06 08:57:54 +04:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2014-10-16 22:15:40 +04:00
|
|
|
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
|
|
|
uri,
|
|
|
|
nullptr, //aStream
|
|
|
|
principal,
|
|
|
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
|
|
|
nsIContentPolicy::TYPE_OTHER,
|
|
|
|
SVG_CONTENT_TYPE,
|
|
|
|
UTF8_CHARSET);
|
2012-09-06 08:57:54 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-08-19 17:08:45 +04:00
|
|
|
// Set this early because various decisions during page-load depend on it.
|
|
|
|
document->SetIsBeingUsedAsImage();
|
2012-09-06 08:57:54 +04:00
|
|
|
document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStreamListener> listener;
|
|
|
|
rv = document->StartDocumentLoad("external-resource", channel,
|
|
|
|
nullptr, // aLoadGroup
|
|
|
|
nullptr, // aContainer
|
|
|
|
getter_AddRefs(listener),
|
|
|
|
true /* aReset */);
|
|
|
|
if (NS_FAILED(rv) || !listener) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = listener->OnStartRequest(channel, nullptr /* aContext */);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
channel->Cancel(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult status;
|
|
|
|
channel->GetStatus(&status);
|
|
|
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
|
|
|
rv = listener->OnDataAvailable(channel, nullptr /* aContext */, stream, 0, aBufLen);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
channel->Cancel(rv);
|
|
|
|
}
|
|
|
|
channel->GetStatus(&status);
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = listener->OnStopRequest(channel, nullptr /* aContext */, status);
|
|
|
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
|
|
|
|
2012-09-06 08:58:47 +04:00
|
|
|
document.swap(mDocument);
|
2012-09-06 08:57:54 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-09-06 08:58:47 +04:00
|
|
|
gfxSVGGlyphsDocument::InsertGlyphId(Element *aGlyphElement)
|
2012-09-06 08:57:54 +04:00
|
|
|
{
|
|
|
|
nsAutoString glyphIdStr;
|
2013-08-19 17:08:43 +04:00
|
|
|
static const uint32_t glyphPrefixLength = 5;
|
|
|
|
// The maximum glyph ID is 65535 so the maximum length of the numeric part
|
|
|
|
// is 5.
|
|
|
|
if (!aGlyphElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, glyphIdStr) ||
|
|
|
|
!StringBeginsWith(glyphIdStr, NS_LITERAL_STRING("glyph")) ||
|
|
|
|
glyphIdStr.Length() > glyphPrefixLength + 5) {
|
2012-09-06 08:57:54 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:43 +04:00
|
|
|
uint32_t id = 0;
|
|
|
|
for (uint32_t i = glyphPrefixLength; i < glyphIdStr.Length(); ++i) {
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t ch = glyphIdStr.CharAt(i);
|
2013-08-19 17:08:43 +04:00
|
|
|
if (ch < '0' || ch > '9') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ch == '0' && i == glyphPrefixLength) {
|
2012-09-06 08:57:54 +04:00
|
|
|
return;
|
2013-08-19 17:08:43 +04:00
|
|
|
}
|
|
|
|
id = id * 10 + (ch - '0');
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2013-08-19 17:08:43 +04:00
|
|
|
mGlyphIdMap.Put(id, aGlyphElement);
|
2012-09-06 08:57:54 +04:00
|
|
|
}
|
|
|
|
|
2016-05-03 14:14:35 +03:00
|
|
|
size_t
|
|
|
|
gfxSVGGlyphsDocument::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|
|
|
{
|
|
|
|
return aMallocSizeOf(this)
|
|
|
|
+ mGlyphIdMap.ShallowSizeOfExcludingThis(aMallocSizeOf)
|
|
|
|
+ mSVGGlyphsDocumentURI.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
|
|
|
|
}
|