/* 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/. */
/* * 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 gfxSVGGlyphs::CompareIndexEntries(constvoid* aKey, constvoid* aEntry) { const uint32_t key = *(uint32_t*)aKey; const IndexEntry* entry = (const IndexEntry*)aEntry;
if (key < uint16_t(entry->mStartGlyph)) { return -1;
} if (key > uint16_t(entry->mEndGlyph)) { return 1;
} return 0;
}
/** * Walk the DOM tree to find all glyph elements and insert them into the lookup * table * @param aElem The element to search from
*/ void gfxSVGGlyphsDocument::FindGlyphElements(Element* aElem) { for (nsIContent* child = aElem->GetLastChild(); child;
child = child->GetPreviousSibling()) { if (!child->IsElement()) { continue;
}
FindGlyphElements(child->AsElement());
}
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
*/ void gfxSVGGlyphs::RenderGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
gfxContextAutoSaveRestore aContextRestorer(aContext);
Element* glyph = mGlyphIdMap.Get(aGlyphId);
MOZ_ASSERT(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
#if DEBUG // This will not have any effect, because we're about to restore the state // via the aContextRestorer destructor, but it prevents debug builds from // asserting if it turns out that PaintSVGGlyph didn't actually do anything. // This happens if the SVG document consists of just an image, and the image // hasn't finished loading yet so we can't draw it.
aContext->SetOp(gfx::CompositionOp::OP_OVER); #endif
}
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!");
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 (constauto& entry : mGlyphDocs.Values()) {
result += entry->SizeOfIncludingThis(aMallocSizeOf);
} return result;
}
gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t* aBuffer,
uint32_t aBufLen,
gfxSVGGlyphs* aSVGGlyphs)
: mOwner(aSVGGlyphs) { if (aBufLen >= 14 && aBuffer[0] == 31 && aBuffer[1] == 139) { // It's a gzip-compressed document; decompress it before parsing. // The original length (modulo 2^32) is found in the last 4 bytes // of the data, stored in little-endian format. We read it as // individual bytes to avoid possible alignment issues. // (Note that if the original length was >2^32, then origLen here // will be incorrect; but then the inflate() call will not return // Z_STREAM_END and we'll bail out safely.)
size_t origLen = (size_t(aBuffer[aBufLen - 1]) << 24) +
(size_t(aBuffer[aBufLen - 2]) << 16) +
(size_t(aBuffer[aBufLen - 3]) << 8) +
size_t(aBuffer[aBufLen - 4]);
AutoTArray<uint8_t, 4096> outBuf; if (outBuf.SetLength(origLen, mozilla::fallible)) {
z_stream s = {0};
s.next_in = const_cast<Byte*>(aBuffer);
s.avail_in = aBufLen;
s.next_out = outBuf.Elements();
s.avail_out = outBuf.Length(); // The magic number 16 here is the zlib flag to expect gzip format, // see http://www.zlib.net/manual.html#Advanced if (Z_OK == inflateInit2(&s, 16 + MAX_WBITS)) { int result = inflate(&s, Z_FINISH); if (Z_STREAM_END == result) {
MOZ_ASSERT(size_t(s.next_out - outBuf.Elements()) == origLen);
ParseDocument(outBuf.Elements(), outBuf.Length());
} else {
NS_WARNING("Failed to decompress SVG glyphs document");
}
inflateEnd(&s);
}
} else {
NS_WARNING("Failed to allocate memory for SVG glyphs document");
}
} else {
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;
}
FindGlyphElements(root);
}
gfxSVGGlyphsDocument::~gfxSVGGlyphsDocument() { if (mDocument) {
mDocument->OnPageHide(false, nullptr);
} if (mPresShell) {
mPresShell->RemovePostRefreshObserver(this);
} if (mViewer) {
mViewer->Close(nullptr);
mViewer->Destroy();
}
}
// Set this early because various decisions during page-load depend on it.
document->SetIsBeingUsedAsImage();
document->SetIsSVGGlyphsDocument();
document->SetReadyStateInternal(Document::READYSTATE_UNINITIALIZED);
void gfxSVGGlyphsDocument::InsertGlyphId(Element* aGlyphElement) {
nsAutoString glyphIdStr; staticconst uint32_t glyphPrefixLength = 5; // The maximum glyph ID is 65535 so the maximum length of the numeric part // is 5. if (!aGlyphElement->GetAttr(nsGkAtoms::id, glyphIdStr) ||
!StringBeginsWith(glyphIdStr, u"glyph"_ns) ||
glyphIdStr.Length() > glyphPrefixLength + 5) { return;
}
uint32_t id = 0; for (uint32_t i = glyphPrefixLength; i < glyphIdStr.Length(); ++i) {
char16_t ch = glyphIdStr.CharAt(i); if (ch < '0' || ch > '9') { return;
} if (ch == '0' && i == glyphPrefixLength) { return;
}
id = id * 10 + (ch - '0');
}
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.