2017-03-27 14:44:52 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* 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/. */
|
|
|
|
|
2018-09-13 23:34:38 +03:00
|
|
|
#include "gfxPrefs.h"
|
2017-04-26 23:31:59 +03:00
|
|
|
#include "gfxUtils.h"
|
2017-11-20 19:34:36 +03:00
|
|
|
#include "mozilla/Mutex.h"
|
2017-03-27 14:44:52 +03:00
|
|
|
#include "mozilla/Range.h"
|
|
|
|
#include "mozilla/gfx/2D.h"
|
2018-08-03 01:09:17 +03:00
|
|
|
#include "mozilla/gfx/RectAbsolute.h"
|
2017-11-15 07:15:31 +03:00
|
|
|
#include "mozilla/gfx/Logging.h"
|
2017-04-26 23:31:59 +03:00
|
|
|
#include "mozilla/gfx/RecordedEvent.h"
|
2018-04-27 02:00:16 +03:00
|
|
|
#include "mozilla/layers/WebRenderDrawEventRecorder.h"
|
2017-03-27 14:44:52 +03:00
|
|
|
#include "WebRenderTypes.h"
|
2017-08-14 22:28:37 +03:00
|
|
|
#include "webrender_ffi.h"
|
2017-03-27 14:44:52 +03:00
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
#include <unordered_map>
|
2017-04-26 23:31:59 +03:00
|
|
|
|
2017-11-07 04:21:25 +03:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
#include "mozilla/gfx/UnscaledFontMac.h"
|
|
|
|
#elif defined(XP_WIN)
|
|
|
|
#include "mozilla/gfx/UnscaledFontDWrite.h"
|
2017-11-07 22:10:31 +03:00
|
|
|
#else
|
2017-11-07 04:21:25 +03:00
|
|
|
#include "mozilla/gfx/UnscaledFontFreeType.h"
|
2017-05-18 04:56:58 +03:00
|
|
|
#endif
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
namespace std {
|
2018-09-06 04:55:53 +03:00
|
|
|
template <> struct hash<mozilla::wr::FontKey> {
|
|
|
|
size_t operator()(const mozilla::wr::FontKey& key) const {
|
|
|
|
return hash<size_t>()(mozilla::wr::AsUint64(key));
|
|
|
|
}
|
|
|
|
};
|
2017-10-28 01:21:27 +03:00
|
|
|
|
2018-09-06 04:55:53 +03:00
|
|
|
template <> struct hash<mozilla::wr::FontInstanceKey> {
|
|
|
|
size_t operator()(const mozilla::wr::FontInstanceKey& key) const {
|
|
|
|
return hash<size_t>()(mozilla::wr::AsUint64(key));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
2017-10-28 01:21:27 +03:00
|
|
|
|
2017-03-27 14:44:52 +03:00
|
|
|
namespace mozilla {
|
2017-10-28 01:21:27 +03:00
|
|
|
|
|
|
|
using namespace gfx;
|
|
|
|
|
2017-03-27 14:44:52 +03:00
|
|
|
namespace wr {
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
struct FontTemplate {
|
2018-04-25 05:24:55 +03:00
|
|
|
const uint8_t* mData;
|
2017-10-28 01:21:27 +03:00
|
|
|
size_t mSize;
|
2017-10-29 01:32:24 +03:00
|
|
|
uint32_t mIndex;
|
2018-04-25 05:24:55 +03:00
|
|
|
const VecU8* mVec;
|
2017-10-28 05:08:47 +03:00
|
|
|
RefPtr<UnscaledFont> mUnscaledFont;
|
2018-04-25 05:24:55 +03:00
|
|
|
|
|
|
|
FontTemplate()
|
|
|
|
: mData(nullptr)
|
|
|
|
, mSize(0)
|
|
|
|
, mIndex(0)
|
|
|
|
, mVec(nullptr)
|
|
|
|
{}
|
|
|
|
|
|
|
|
~FontTemplate() {
|
|
|
|
if (mVec) {
|
|
|
|
wr_dec_ref_arc(mVec);
|
|
|
|
}
|
|
|
|
}
|
2017-10-28 01:21:27 +03:00
|
|
|
};
|
|
|
|
|
2018-09-06 04:55:53 +03:00
|
|
|
struct FontInstanceData {
|
|
|
|
WrFontKey mFontKey;
|
|
|
|
float mSize;
|
|
|
|
Maybe<FontInstanceOptions> mOptions;
|
|
|
|
Maybe<FontInstancePlatformOptions> mPlatformOptions;
|
2018-09-07 17:00:04 +03:00
|
|
|
UniquePtr<gfx::FontVariation[]> mVariations;
|
2018-09-06 04:55:53 +03:00
|
|
|
size_t mNumVariations;
|
|
|
|
RefPtr<ScaledFont> mScaledFont;
|
|
|
|
|
|
|
|
FontInstanceData()
|
|
|
|
: mSize(0)
|
|
|
|
, mNumVariations(0)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2017-11-20 19:34:36 +03:00
|
|
|
StaticMutex sFontDataTableLock;
|
2018-09-06 04:55:53 +03:00
|
|
|
std::unordered_map<WrFontKey, FontTemplate> sFontDataTable;
|
|
|
|
std::unordered_map<WrFontInstanceKey, FontInstanceData> sBlobFontTable;
|
2017-10-28 01:21:27 +03:00
|
|
|
|
2018-04-09 04:31:16 +03:00
|
|
|
// Fixed-size ring buffer logging font deletion events to aid debugging.
|
|
|
|
static struct FontDeleteLog {
|
|
|
|
static const size_t MAX_ENTRIES = 256;
|
|
|
|
|
|
|
|
uint64_t mEntries[MAX_ENTRIES] = { 0 };
|
|
|
|
size_t mNextEntry = 0;
|
|
|
|
|
|
|
|
void AddEntry(uint64_t aEntry) {
|
|
|
|
mEntries[mNextEntry] = aEntry;
|
|
|
|
mNextEntry = (mNextEntry + 1) % MAX_ENTRIES;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(WrFontKey aKey) {
|
|
|
|
AddEntry(AsUint64(aKey));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store namespace clears as font id 0, since this will never be allocated.
|
|
|
|
void Add(WrIdNamespace aNamespace) {
|
|
|
|
AddEntry(AsUint64(WrFontKey { aNamespace, 0 }));
|
|
|
|
}
|
|
|
|
|
2018-04-25 05:24:55 +03:00
|
|
|
void AddAll() {
|
2018-04-26 18:58:49 +03:00
|
|
|
AddEntry(~0);
|
2018-04-25 05:24:55 +03:00
|
|
|
}
|
|
|
|
|
2018-04-09 04:31:16 +03:00
|
|
|
// Find a matching entry in the log, searching backwards starting at the newest
|
|
|
|
// entry and finishing with the oldest entry. Returns a brief description of why
|
|
|
|
// the font was deleted, if known.
|
|
|
|
const char* Find(WrFontKey aKey) {
|
|
|
|
uint64_t keyEntry = AsUint64(aKey);
|
|
|
|
uint64_t namespaceEntry = AsUint64(WrFontKey { aKey.mNamespace, 0 });
|
|
|
|
size_t offset = mNextEntry;
|
|
|
|
do {
|
|
|
|
offset = (offset + MAX_ENTRIES - 1) % MAX_ENTRIES;
|
|
|
|
if (mEntries[offset] == keyEntry) {
|
|
|
|
return "deleted font";
|
|
|
|
} else if (mEntries[offset] == namespaceEntry) {
|
|
|
|
return "cleared namespace";
|
2018-04-26 18:58:49 +03:00
|
|
|
} else if (mEntries[offset] == (uint64_t)~0) {
|
2018-04-25 05:24:55 +03:00
|
|
|
return "cleared all";
|
2018-04-09 04:31:16 +03:00
|
|
|
}
|
|
|
|
} while (offset != mNextEntry);
|
|
|
|
return "unknown font";
|
|
|
|
}
|
|
|
|
} sFontDeleteLog;
|
|
|
|
|
2018-04-25 05:24:55 +03:00
|
|
|
void
|
|
|
|
ClearAllBlobImageResources() {
|
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
|
|
|
sFontDeleteLog.AddAll();
|
2018-09-06 04:55:53 +03:00
|
|
|
sBlobFontTable.clear();
|
2018-04-25 05:24:55 +03:00
|
|
|
sFontDataTable.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
2018-01-18 14:28:09 +03:00
|
|
|
void
|
|
|
|
ClearBlobImageResources(WrIdNamespace aNamespace) {
|
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
2018-04-09 04:31:16 +03:00
|
|
|
sFontDeleteLog.Add(aNamespace);
|
2018-09-06 04:55:53 +03:00
|
|
|
for (auto i = sBlobFontTable.begin(); i != sBlobFontTable.end();) {
|
|
|
|
if (i->first.mNamespace == aNamespace) {
|
|
|
|
i = sBlobFontTable.erase(i);
|
|
|
|
} else {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2018-01-18 14:28:09 +03:00
|
|
|
for (auto i = sFontDataTable.begin(); i != sFontDataTable.end();) {
|
|
|
|
if (i->first.mNamespace == aNamespace) {
|
|
|
|
i = sFontDataTable.erase(i);
|
|
|
|
} else {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
void
|
2017-10-29 01:32:24 +03:00
|
|
|
AddFontData(WrFontKey aKey, const uint8_t *aData, size_t aSize, uint32_t aIndex, const ArcVecU8 *aVec) {
|
2017-11-20 19:34:36 +03:00
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
2017-10-28 01:21:27 +03:00
|
|
|
auto i = sFontDataTable.find(aKey);
|
|
|
|
if (i == sFontDataTable.end()) {
|
2018-04-25 05:24:55 +03:00
|
|
|
FontTemplate& font = sFontDataTable[aKey];
|
2017-10-28 01:21:27 +03:00
|
|
|
font.mData = aData;
|
|
|
|
font.mSize = aSize;
|
|
|
|
font.mIndex = aIndex;
|
|
|
|
font.mVec = wr_add_ref_arc(aVec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-07 04:21:25 +03:00
|
|
|
void
|
|
|
|
AddNativeFontHandle(WrFontKey aKey, void* aHandle, uint32_t aIndex) {
|
2017-11-20 19:34:36 +03:00
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
2017-11-07 04:21:25 +03:00
|
|
|
auto i = sFontDataTable.find(aKey);
|
|
|
|
if (i == sFontDataTable.end()) {
|
2018-04-25 05:24:55 +03:00
|
|
|
FontTemplate& font = sFontDataTable[aKey];
|
2017-11-07 04:21:25 +03:00
|
|
|
#ifdef XP_MACOSX
|
2018-05-04 00:00:53 +03:00
|
|
|
font.mUnscaledFont = new UnscaledFontMac(reinterpret_cast<CGFontRef>(aHandle), false);
|
2017-11-07 04:21:25 +03:00
|
|
|
#elif defined(XP_WIN)
|
|
|
|
font.mUnscaledFont = new UnscaledFontDWrite(reinterpret_cast<IDWriteFontFace*>(aHandle), nullptr);
|
|
|
|
#elif defined(ANDROID)
|
|
|
|
font.mUnscaledFont = new UnscaledFontFreeType(reinterpret_cast<const char*>(aHandle), aIndex);
|
|
|
|
#else
|
|
|
|
font.mUnscaledFont = new UnscaledFontFontconfig(reinterpret_cast<const char*>(aHandle), aIndex);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
void
|
2017-10-29 01:32:24 +03:00
|
|
|
DeleteFontData(WrFontKey aKey) {
|
2017-11-20 19:34:36 +03:00
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
2018-04-09 04:31:16 +03:00
|
|
|
sFontDeleteLog.Add(aKey);
|
2017-10-28 01:21:27 +03:00
|
|
|
auto i = sFontDataTable.find(aKey);
|
|
|
|
if (i != sFontDataTable.end()) {
|
2017-10-31 05:35:40 +03:00
|
|
|
sFontDataTable.erase(i);
|
2017-10-28 01:21:27 +03:00
|
|
|
}
|
|
|
|
}
|
2018-09-06 04:55:53 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
AddBlobFont(WrFontInstanceKey aInstanceKey,
|
|
|
|
WrFontKey aFontKey,
|
|
|
|
float aSize,
|
|
|
|
const FontInstanceOptions* aOptions,
|
|
|
|
const FontInstancePlatformOptions* aPlatformOptions,
|
|
|
|
const FontVariation* aVariations,
|
|
|
|
size_t aNumVariations)
|
|
|
|
{
|
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
|
|
|
auto i = sBlobFontTable.find(aInstanceKey);
|
|
|
|
if (i == sBlobFontTable.end()) {
|
|
|
|
FontInstanceData& font = sBlobFontTable[aInstanceKey];
|
|
|
|
font.mFontKey = aFontKey;
|
|
|
|
font.mSize = aSize;
|
|
|
|
if (aOptions) {
|
|
|
|
font.mOptions = Some(*aOptions);
|
|
|
|
}
|
|
|
|
if (aPlatformOptions) {
|
|
|
|
font.mPlatformOptions = Some(*aPlatformOptions);
|
|
|
|
}
|
|
|
|
if (aNumVariations) {
|
2018-09-26 23:33:01 +03:00
|
|
|
font.mNumVariations = aNumVariations;
|
2018-09-07 17:00:04 +03:00
|
|
|
font.mVariations.reset(new gfx::FontVariation[aNumVariations]);
|
|
|
|
PodCopy(font.mVariations.get(), reinterpret_cast<const gfx::FontVariation*>(aVariations), aNumVariations);
|
2018-09-06 04:55:53 +03:00
|
|
|
}
|
|
|
|
}
|
2017-10-28 01:21:27 +03:00
|
|
|
}
|
|
|
|
|
2018-09-06 04:55:53 +03:00
|
|
|
void
|
|
|
|
DeleteBlobFont(WrFontInstanceKey aKey)
|
|
|
|
{
|
2017-11-20 19:34:36 +03:00
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
2018-09-06 04:55:53 +03:00
|
|
|
auto i = sBlobFontTable.find(aKey);
|
|
|
|
if (i != sBlobFontTable.end()) {
|
|
|
|
sBlobFontTable.erase(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 18:09:42 +03:00
|
|
|
} // extern
|
|
|
|
|
2018-09-06 04:55:53 +03:00
|
|
|
static RefPtr<UnscaledFont>
|
|
|
|
GetUnscaledFont(Translator* aTranslator, WrFontKey aKey)
|
|
|
|
{
|
|
|
|
auto i = sFontDataTable.find(aKey);
|
2017-11-20 19:34:36 +03:00
|
|
|
if (i == sFontDataTable.end()) {
|
2018-09-06 04:55:53 +03:00
|
|
|
gfxDevCrash(LogReason::UnscaledFontNotFound) << "Failed to get UnscaledFont entry for FontKey " << aKey.mHandle
|
|
|
|
<< " because " << sFontDeleteLog.Find(aKey);
|
2017-11-20 19:34:36 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-04-25 05:24:55 +03:00
|
|
|
FontTemplate &data = i->second;
|
2017-10-28 05:08:47 +03:00
|
|
|
if (data.mUnscaledFont) {
|
|
|
|
return data.mUnscaledFont;
|
|
|
|
}
|
2017-11-07 04:21:25 +03:00
|
|
|
MOZ_ASSERT(data.mData);
|
2017-10-28 01:21:27 +03:00
|
|
|
FontType type =
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
FontType::MAC;
|
2017-11-07 04:21:25 +03:00
|
|
|
#elif defined(XP_WIN)
|
2017-10-28 01:21:27 +03:00
|
|
|
FontType::DWRITE;
|
2017-11-07 04:21:25 +03:00
|
|
|
#elif defined(ANDROID)
|
2017-10-28 01:21:27 +03:00
|
|
|
FontType::FREETYPE;
|
|
|
|
#else
|
|
|
|
FontType::FONTCONFIG;
|
|
|
|
#endif
|
|
|
|
// makes a copy of the data
|
|
|
|
RefPtr<NativeFontResource> fontResource = Factory::CreateNativeFontResource((uint8_t*)data.mData, data.mSize,
|
|
|
|
aTranslator->GetReferenceDrawTarget()->GetBackendType(),
|
|
|
|
type,
|
|
|
|
aTranslator->GetFontContext());
|
|
|
|
RefPtr<UnscaledFont> unscaledFont;
|
2017-11-15 07:15:31 +03:00
|
|
|
if (!fontResource) {
|
2018-09-06 04:55:53 +03:00
|
|
|
gfxDevCrash(LogReason::NativeFontResourceNotFound) << "Failed to create NativeFontResource for FontKey " << aKey.mHandle;
|
2017-11-15 07:15:31 +03:00
|
|
|
} else {
|
2017-10-28 01:21:27 +03:00
|
|
|
// Instance data is only needed for GDI fonts which webrender does not
|
|
|
|
// support.
|
|
|
|
unscaledFont = fontResource->CreateUnscaledFont(data.mIndex, nullptr, 0);
|
2017-11-15 07:15:31 +03:00
|
|
|
if (!unscaledFont) {
|
2018-09-06 04:55:53 +03:00
|
|
|
gfxDevCrash(LogReason::UnscaledFontNotFound) << "Failed to create UnscaledFont for FontKey " << aKey.mHandle;
|
2017-11-15 07:15:31 +03:00
|
|
|
}
|
2017-10-28 01:21:27 +03:00
|
|
|
}
|
2017-10-28 05:08:47 +03:00
|
|
|
data.mUnscaledFont = unscaledFont;
|
2017-10-28 01:21:27 +03:00
|
|
|
return unscaledFont;
|
|
|
|
}
|
|
|
|
|
2018-09-06 04:55:53 +03:00
|
|
|
static RefPtr<ScaledFont>
|
|
|
|
GetScaledFont(Translator* aTranslator, WrFontInstanceKey aKey)
|
|
|
|
{
|
|
|
|
StaticMutexAutoLock lock(sFontDataTableLock);
|
|
|
|
auto i = sBlobFontTable.find(aKey);
|
|
|
|
if (i == sBlobFontTable.end()) {
|
|
|
|
gfxDevCrash(LogReason::ScaledFontNotFound) << "Failed to get ScaledFont entry for FontInstanceKey " << aKey.mHandle;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
FontInstanceData &data = i->second;
|
|
|
|
if (data.mScaledFont) {
|
|
|
|
return data.mScaledFont;
|
|
|
|
}
|
|
|
|
RefPtr<UnscaledFont> unscaled = GetUnscaledFont(aTranslator, data.mFontKey);
|
|
|
|
if (!unscaled) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
RefPtr<ScaledFont> scaled =
|
|
|
|
unscaled->CreateScaledFontFromWRFont(data.mSize,
|
|
|
|
data.mOptions.ptrOr(nullptr),
|
|
|
|
data.mPlatformOptions.ptrOr(nullptr),
|
|
|
|
data.mVariations.get(),
|
|
|
|
data.mNumVariations);
|
|
|
|
if (!scaled) {
|
|
|
|
gfxDevCrash(LogReason::ScaledFontNotFound) << "Failed to create ScaledFont for FontKey " << aKey.mHandle;
|
|
|
|
}
|
|
|
|
data.mScaledFont = scaled;
|
|
|
|
return data.mScaledFont;
|
|
|
|
}
|
|
|
|
|
2017-04-11 23:13:44 +03:00
|
|
|
static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
2017-03-27 14:44:52 +03:00
|
|
|
gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
2017-08-14 22:28:37 +03:00
|
|
|
const uint16_t *aTileSize,
|
|
|
|
const mozilla::wr::TileOffset *aTileOffset,
|
2018-04-05 20:18:22 +03:00
|
|
|
const mozilla::wr::DeviceUintRect *aDirtyRect,
|
2017-04-26 23:31:59 +03:00
|
|
|
Range<uint8_t> aOutput)
|
2017-03-27 14:44:52 +03:00
|
|
|
{
|
2017-04-26 23:31:59 +03:00
|
|
|
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
|
|
|
if (aSize.width <= 0 || aSize.height <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto stride = aSize.width * gfx::BytesPerPixel(aFormat);
|
|
|
|
|
|
|
|
if (aOutput.length() < static_cast<size_t>(aSize.height * stride)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// In bindings.rs we allocate a buffer filled with opaque white.
|
|
|
|
bool uninitialized = false;
|
|
|
|
|
|
|
|
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(
|
|
|
|
gfx::BackendType::SKIA,
|
|
|
|
aOutput.begin().get(),
|
|
|
|
aSize,
|
|
|
|
stride,
|
|
|
|
aFormat,
|
|
|
|
uninitialized
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!dt) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-08 05:55:23 +03:00
|
|
|
auto origin = gfx::IntPoint(0, 0);
|
2017-08-14 22:28:37 +03:00
|
|
|
if (aTileOffset) {
|
2018-08-08 05:55:23 +03:00
|
|
|
origin = gfx::IntPoint(aTileOffset->x * *aTileSize, aTileOffset->y * *aTileSize);
|
|
|
|
dt = gfx::Factory::CreateOffsetDrawTarget(dt, origin);
|
2017-08-14 22:28:37 +03:00
|
|
|
}
|
|
|
|
|
2018-08-03 01:09:17 +03:00
|
|
|
auto bounds = gfx::IntRect(origin, aSize);
|
|
|
|
|
2018-04-11 17:27:12 +03:00
|
|
|
if (aDirtyRect) {
|
|
|
|
Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y, aDirtyRect->size.width, aDirtyRect->size.height);
|
|
|
|
dt->PushClipRect(dirty);
|
2018-08-03 01:09:17 +03:00
|
|
|
bounds = bounds.Intersect(IntRect(aDirtyRect->origin.x,
|
|
|
|
aDirtyRect->origin.y,
|
|
|
|
aDirtyRect->size.width,
|
|
|
|
aDirtyRect->size.height));
|
2018-04-11 17:27:12 +03:00
|
|
|
}
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
struct Reader {
|
|
|
|
const uint8_t *buf;
|
|
|
|
size_t len;
|
|
|
|
size_t pos;
|
|
|
|
|
|
|
|
Reader(const uint8_t *buf, size_t len) : buf(buf), len(len), pos(0) {}
|
2017-04-26 23:31:59 +03:00
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
size_t ReadSize() {
|
|
|
|
size_t ret;
|
|
|
|
MOZ_RELEASE_ASSERT(pos + sizeof(ret) <= len);
|
|
|
|
memcpy(&ret, buf + pos, sizeof(ret));
|
|
|
|
pos += sizeof(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2018-03-17 02:20:26 +03:00
|
|
|
int ReadInt() {
|
|
|
|
int ret;
|
|
|
|
MOZ_RELEASE_ASSERT(pos + sizeof(ret) <= len);
|
|
|
|
memcpy(&ret, buf + pos, sizeof(ret));
|
|
|
|
pos += sizeof(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:09:17 +03:00
|
|
|
IntRectAbsolute ReadBounds() {
|
|
|
|
MOZ_RELEASE_ASSERT(pos + sizeof(int32_t) * 4 <= len);
|
|
|
|
int32_t x1, y1, x2, y2;
|
|
|
|
memcpy(&x1, buf + pos + 0 * sizeof(int32_t), sizeof(x1));
|
|
|
|
memcpy(&y1, buf + pos + 1 * sizeof(int32_t), sizeof(y1));
|
|
|
|
memcpy(&x2, buf + pos + 2 * sizeof(int32_t), sizeof(x2));
|
|
|
|
memcpy(&y2, buf + pos + 3 * sizeof(int32_t), sizeof(y2));
|
|
|
|
pos += sizeof(int32_t) * 4;
|
|
|
|
return IntRectAbsolute(x1, y1, x2, y2);
|
2018-03-17 02:20:26 +03:00
|
|
|
}
|
|
|
|
|
2018-09-10 21:59:13 +03:00
|
|
|
layers::BlobFont ReadBlobFont() {
|
|
|
|
MOZ_RELEASE_ASSERT(pos + sizeof(layers::BlobFont) <= len);
|
|
|
|
layers::BlobFont ret;
|
|
|
|
memcpy(&ret, buf + pos, sizeof(ret));
|
|
|
|
pos += sizeof(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
};
|
2018-08-23 22:53:21 +03:00
|
|
|
|
2018-09-12 02:14:42 +03:00
|
|
|
// We try hard to not have empty blobs but we can end up with
|
|
|
|
// them because of CompositorHitTestInfo and merging.
|
|
|
|
MOZ_RELEASE_ASSERT(aBlob.length() >= sizeof(size_t));
|
2017-10-28 01:21:27 +03:00
|
|
|
size_t indexOffset = *(size_t*)(aBlob.end().get()-sizeof(size_t));
|
2018-09-19 11:12:07 +03:00
|
|
|
MOZ_RELEASE_ASSERT(indexOffset <= aBlob.length() - sizeof(size_t));
|
2017-10-28 01:21:27 +03:00
|
|
|
Reader reader(aBlob.begin().get()+indexOffset, aBlob.length()-sizeof(size_t)-indexOffset);
|
|
|
|
|
2018-09-12 02:14:42 +03:00
|
|
|
bool ret = true;
|
2017-10-28 01:21:27 +03:00
|
|
|
size_t offset = 0;
|
2018-08-03 01:09:17 +03:00
|
|
|
auto absBounds = IntRectAbsolute::FromRect(bounds);
|
2017-10-28 01:21:27 +03:00
|
|
|
while (reader.pos < reader.len) {
|
|
|
|
size_t end = reader.ReadSize();
|
|
|
|
size_t extra_end = reader.ReadSize();
|
2018-08-03 01:09:17 +03:00
|
|
|
auto combinedBounds = absBounds.Intersect(reader.ReadBounds());
|
|
|
|
if (combinedBounds.IsEmpty()) {
|
|
|
|
offset = extra_end;
|
|
|
|
continue;
|
|
|
|
}
|
2017-10-28 01:21:27 +03:00
|
|
|
|
2018-04-27 02:00:16 +03:00
|
|
|
layers::WebRenderTranslator translator(dt);
|
2017-10-28 01:21:27 +03:00
|
|
|
|
2018-09-10 21:59:13 +03:00
|
|
|
MOZ_RELEASE_ASSERT(extra_end >= end);
|
|
|
|
MOZ_RELEASE_ASSERT(extra_end < aBlob.length());
|
|
|
|
Reader fontReader(aBlob.begin().get() + end, extra_end - end);
|
|
|
|
size_t count = fontReader.ReadSize();
|
2017-10-28 01:21:27 +03:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
2018-09-10 21:59:13 +03:00
|
|
|
layers::BlobFont blobFont = fontReader.ReadBlobFont();
|
2018-09-06 04:55:53 +03:00
|
|
|
RefPtr<ScaledFont> scaledFont = GetScaledFont(&translator, blobFont.mFontInstanceKey);
|
|
|
|
translator.AddScaledFont(blobFont.mScaledFontPtr, scaledFont);
|
2017-10-28 01:21:27 +03:00
|
|
|
}
|
2018-09-06 04:55:53 +03:00
|
|
|
|
2017-10-28 01:21:27 +03:00
|
|
|
Range<const uint8_t> blob(aBlob.begin() + offset, aBlob.begin() + end);
|
|
|
|
ret = translator.TranslateRecording((char*)blob.begin().get(), blob.length());
|
2018-02-23 21:14:39 +03:00
|
|
|
MOZ_RELEASE_ASSERT(ret);
|
2017-10-28 01:21:27 +03:00
|
|
|
offset = extra_end;
|
|
|
|
}
|
2017-04-26 23:31:59 +03:00
|
|
|
|
2018-09-13 23:34:38 +03:00
|
|
|
if (gfxPrefs::WebRenderBlobPaintFlashing()) {
|
|
|
|
dt->SetTransform(gfx::Matrix());
|
|
|
|
float r = float(rand()) / RAND_MAX;
|
|
|
|
float g = float(rand()) / RAND_MAX;
|
|
|
|
float b = float(rand()) / RAND_MAX;
|
|
|
|
dt->FillRect(gfx::Rect(origin.x, origin.y, aSize.width, aSize.height), gfx::ColorPattern(gfx::Color(r, g, b, 0.5)));
|
|
|
|
}
|
2018-04-05 20:18:22 +03:00
|
|
|
|
|
|
|
if (aDirtyRect) {
|
|
|
|
dt->PopClip();
|
|
|
|
}
|
|
|
|
|
2017-04-26 23:31:59 +03:00
|
|
|
#if 0
|
|
|
|
static int i = 0;
|
|
|
|
char filename[40];
|
|
|
|
sprintf(filename, "out%d.png", i++);
|
|
|
|
gfxUtils::WriteAsPNG(dt, filename);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2017-03-27 14:44:52 +03:00
|
|
|
}
|
|
|
|
|
2018-09-06 18:09:42 +03:00
|
|
|
} // namespace
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
2017-07-19 01:35:52 +03:00
|
|
|
bool wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob,
|
2017-03-27 14:44:52 +03:00
|
|
|
uint32_t width, uint32_t height,
|
|
|
|
mozilla::wr::ImageFormat aFormat,
|
2017-08-14 22:28:37 +03:00
|
|
|
const uint16_t *aTileSize,
|
|
|
|
const mozilla::wr::TileOffset *aTileOffset,
|
2018-04-05 20:18:22 +03:00
|
|
|
const mozilla::wr::DeviceUintRect *aDirtyRect,
|
2017-06-28 02:20:36 +03:00
|
|
|
mozilla::wr::MutByteSlice output)
|
2017-03-27 14:44:52 +03:00
|
|
|
{
|
|
|
|
return mozilla::wr::Moz2DRenderCallback(mozilla::wr::ByteSliceToRange(blob),
|
|
|
|
mozilla::gfx::IntSize(width, height),
|
2017-07-19 10:28:58 +03:00
|
|
|
mozilla::wr::ImageFormatToSurfaceFormat(aFormat),
|
2017-08-14 22:28:37 +03:00
|
|
|
aTileSize,
|
|
|
|
aTileOffset,
|
2018-04-05 20:18:22 +03:00
|
|
|
aDirtyRect,
|
2017-04-26 23:31:59 +03:00
|
|
|
mozilla::wr::MutByteSliceToRange(output));
|
2017-03-27 14:44:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // extern
|
|
|
|
|