mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:48:43 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 967693 - Temporarily turn on HTTP cache v2 on for Desktop Firefox Nightly users, r=jduell+ehsan (0fb43bca09)
- Bug 1230939 - check the return of sGlobalEntryTables->Get(aContextKey, &diskEntries). r=mayhemer (da62f5bd04)
- fix header include (52d6efa786)
- Bug 1193605 - Part 3: do not stop non-started service; r=mcmanus (dfe2187f22)
- Bug 1193605 - Part 4: add UUID for listeners; r=mcmanus (fee78fd19d)
- Bug 1214176 - fix typo in _onOffer. r=junior. (b388d1f2a6)
- align test to 1216398 (74d505d1d6)
- Bug 1228457 create pref to allow blocking .onion at dns level rfc 7687 r=valentin.gosu (521aab1e58)
- Bug 1216370 - For safety and searchability, define the nsHostResolver::RES_* enum in terms of the nsIDNSService::RESOLVE_* enum. r=mayhemer (84c22f815f)
- Bug 1194763 - Ensure non-cluster-start flag is set properly for a run-initial supplementary-plane combining mark when shaping text. r=jdaggett (17c3ad163d)
- Bug 1168176 - Mark gfxFontShaper::mFont as MOZ_NON_OWNING_REF. r=jtd (0f3ca78c16)
- Bug 1167403 - Mark gfxFont::GlyphChangeObserver::mFont as MOZ_NON_OWNING_REF. r=jtd (ec77538943)
- align gfxContext to pre-1232822 (part 6) (bb7fa256c9)
- Bug 1231889 - Moz2Dify gfxWindowsNativeDrawing::PaintToContext(). r=mattwoodrow. (69b1d62395)
- Bug 1231864 (part 1) - Remove useless GetCairo() call in gfxWindowsNativeDrawing::BeginNativeDrawing(). r=mattwoodrow. (aa3017c392)
- Bug 1231864 (part 2) - Clean up gfxWindowsNativeDrawing::BeginNativeDrawing(). r=mattwoodrow. (860a81ba59)
- Bug 1225682 - Don't use nsAuto{,C}String as class member variables in gfx/. r=jrmuizel (a1cc11b749)
- Bug 1230611 - Make gfxWindowsPlatform::SupportsApzTouchInput use a pref cache to speed it up. r=dvander (4026e5dfe8)
- Bug 1193842 - Delete touch resampling preference and non resampling paths. r=kats (ff58c7753c)
- Bug 1177335 - Skip resampling if the time difference of touches is less than 2ms. (b98e40343d)
- Bug 1204518 - Fix warnings in widget/gonk/. r=mwu. (ddc13a4c24)
- Bug 1231832. Make IsActive work on Querys that have not begun. r=jgilbert (4b70a8fb0b)
- Bug 1218881. Enforce queries' new availability semantics. r=jgilbert (503bf80f8b)
- Bug 1233858 - Part 1 - ensure Skia's SkGraphics::Init is called from gfxPlatform::Init. r=jmuizelaar (db5fde96b1)
- Bug 1233858 -Part 2 - implement runtime-detected SSE2 optimizations for Skia. r=jmuizelaar (3c9ebaa64d)
- Bug 1233858 - work around Skia __vectorcall bugs on Win32. r=jmuizelaar (b5b5e2bbcf)
- Bug 1222569 - remove unused function from gfxPlatformFontList.cpp; r=Bas (68e1615eb2)
- Bug 1234566: Use LoadLibraryA instead of LoadLibrary in some skia Windows code to allow UNICODE to be defined. r=lsalzman (e45bf51ef7)
- Bug 1156742 Part 1: Change Moz2D recording, so that it can be used in isolation. r=bas (f02fd4992b)
- Bug 1156742 Part 2: Make gfx thebes/gl/2d work with UNICODE defined. r=bas, r=glandium (8fca45d9a3)
- Bug 1156742 Part 3: Add support for FontType::CAIRO to CreateScaledFontForTrueTypeData on Windows. r=bas (863ea539c4)
- Bug 1156742 Part 4: Add an in memory DrawEventRecorder. r=bas (c9196512a1)
- Bug 1156742 Part 5: Add a skeleton RemotePrintJob. r=mconley (aa48df9f32)
- Bug 1156742 Part 6: Add RemotePrintJob to PrintSession and PrintData. r=roc, r=mconley (607a3e6b9b)
- Bug 1233444 - add override declarations for widget/windows/; r=roc (edab847cb0)
- Bug 1156742 Part 7: Refactor nsDeviceContext.cpp to use printing surface for size and nsIDeviceContextSpec for DPI and scale. r=roc (ec6ff3d592)
- Bug 1156742 Part 8: Change gfxWindowsSurface, so that a non-printing surface can be used when recording a print. r=roc (1ab167635e)
- Bug 1156742 Part 9: Add a new nsIDeviceContextSpec for proxied printing. r=roc (11c3909a8f)
- Bug 1156742 Part 10: Allow RemotePrintJob to influence nsPagePrintTimer. r=roc (c658e96338)
- Bug 1156742 Part 11: Allow RemotePrintJobChild to abort the print. r=roc (30f3e9bce4)
- Bug 1156742 Part 12: Record CreateSimilarDrawTarget separately for Moz2D. r=bas (a978b691c3)
- Bug 1156742 Part 13: Create a Moz2D PrintTranslator. r=bas (1eca4e9b33)
- Bug 1156742 Part 14: Complete RemotePrintJob using PrintTranslator. r=mconley (7db80f0ba7)
- Bug 1156742 Part 15: Add pref for turning on printing via the parent process. r=mconley (e3dbf281ea)
- Bug 1156742 Part 16: Add recording and forwarding of Matrix attribute set for Moz2D recording. r=bas (cd5da598ea)
- Bug 1156742 Part 17: Add virtual destructor to RecorededEvent and fix subsequent crash with DWrite playback fonts. r=bas (c20a0b84fc)
- Bug 1156742 Part 18: Fix the way we hold custom font data so that they can be recorded with Moz2D. r=bas (54b4630927)
- Bug 1156742 Part 19: Implement GetFontFileData for ScaledFontWin. r=bas (f1df40b31b)
- Bug 1156742 Part 20: Move Moz2D PreferenceAccess into its own header. r=bas (0afdff8e14)
- Bug 1156742 Part 21: Use GetDirect3D11Device instead of DrawTargetD2D::GetDWriteFactory to determine if DWrite fonts should be used. r=Bas (0c87a5866d)
- Bug 1156742 Part 22: Change ScaledFontDWrite to support creation from TrueType Collection data. r=bas (5f2c607e64)
- Bug 1156742 Part 23: Assert in PrintTranslator when a lookup fails. r=bas (72e24c789f)
- Bug 1156742 Part 24: Add new Recorded event to record font data. r=bas (a0c6f951aa)
- Bug 1156742 Part 25: Flip the big switch and wait for the lightning. r=mconley (082a1a3ede)
- Bug 1203232 - Fix -Wshadow warnings in some ipc/chromium headers. r=njn (018499b8a1)
- Bug 1089837 - Make IPC::Message use MOZ_COUNT_CTOR/DTOR. r=jld (124e011902)
- Bug 1235234 - Fix unintentional switch fallthrough in ipc/chromium/ found by -Wimplicit-fallthrough warning. r=gcp (af37d85c1c)
- Bug 1207498 - Part 2: Remove use of expression closure from tests in toolkit/components/. r=Gijs (98915956bd)
- Bug 1157282 - Add test coverage for telemetry histogram recording. r=gfritzsche (f403b07c7f)
- Bug 1228147: part 1: Add telemetry RecordingEnabled support. r=gfritzsche f=froydnj (610c92394f)
- Bug 1228147: part 2: Add telemetry probe for synchronous scroll. r=kats (6816099c37)
- Bug 1201492 - Remove extended_statistics_ok from Telemetry histograms. r=dexter (f7f991249f)
- Bug 842894 - Support DirectWrite using the Skia backend. r=bas (f2487cf863)
This commit is contained in:
@@ -1112,12 +1112,6 @@ pref("dom.mozSettings.allowForceReadOnly", false);
|
||||
// RequestSync API is enabled by default on B2G.
|
||||
pref("dom.requestSync.enabled", true);
|
||||
|
||||
// Use vsync aligned rendering
|
||||
pref("gfx.vsync.hw-vsync.enabled", true);
|
||||
pref("gfx.vsync.compositor", true);
|
||||
pref("gfx.touch.resample", true);
|
||||
pref("gfx.vsync.refreshdriver", true);
|
||||
|
||||
// Comma separated list of activity names that can only be provided by
|
||||
// the system app in dev mode.
|
||||
pref("dom.activities.developer_mode_only", "import-app");
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "WebGL2Context.h"
|
||||
#include "GLContext.h"
|
||||
#include "WebGLQuery.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -255,6 +257,7 @@ WebGL2Context::EndQuery(GLenum target)
|
||||
}
|
||||
|
||||
UpdateBoundQuery(target, nullptr);
|
||||
NS_DispatchToCurrentThread(new WebGLQuery::AvailableRunnable(activeQuery));
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLQuery>
|
||||
@@ -325,6 +328,11 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
|
||||
return;
|
||||
}
|
||||
|
||||
// We must wait for an event loop before the query can be available
|
||||
if (!query->mCanBeAvailable && !gfxPrefs::WebGLImmediateQueries()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
GLuint returned = 0;
|
||||
switch (pname) {
|
||||
|
||||
@@ -20,6 +20,7 @@ WebGLQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
|
||||
|
||||
WebGLQuery::WebGLQuery(WebGLContext* webgl)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mCanBeAvailable(false)
|
||||
, mGLName(0)
|
||||
, mType(0)
|
||||
{
|
||||
@@ -40,6 +41,9 @@ WebGLQuery::Delete()
|
||||
bool
|
||||
WebGLQuery::IsActive() const
|
||||
{
|
||||
if (!HasEverBeenActive())
|
||||
return false;
|
||||
|
||||
WebGLRefPtr<WebGLQuery>& targetSlot = mContext->GetQuerySlotByTarget(mType);
|
||||
|
||||
return targetSlot.get() == this;
|
||||
|
||||
+17
-1
@@ -10,6 +10,7 @@
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -22,9 +23,22 @@ class WebGLQuery final
|
||||
public:
|
||||
explicit WebGLQuery(WebGLContext* webgl);
|
||||
|
||||
class AvailableRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit AvailableRunnable(WebGLQuery* query) : mQuery(query) { }
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mQuery->mCanBeAvailable = true;
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
const RefPtr<WebGLQuery> mQuery;
|
||||
};
|
||||
|
||||
bool IsActive() const;
|
||||
|
||||
bool HasEverBeenActive() {
|
||||
bool HasEverBeenActive() const {
|
||||
return mType != 0;
|
||||
}
|
||||
|
||||
@@ -42,6 +56,8 @@ public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQuery)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQuery)
|
||||
|
||||
// Track whether the event loop has spun
|
||||
bool mCanBeAvailable;
|
||||
|
||||
private:
|
||||
~WebGLQuery() {
|
||||
|
||||
@@ -608,7 +608,7 @@ TCPControlChannel.prototype = {
|
||||
return;
|
||||
}
|
||||
if (!this._listener) {
|
||||
this._pendingOffer = offer;
|
||||
this._pendingOffer = aOffer;
|
||||
return;
|
||||
}
|
||||
DEBUG && log("TCPControlChannel - notify offer: "
|
||||
|
||||
@@ -645,231 +645,6 @@ function noAddDevice() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function handleSessionRequest() {
|
||||
Services.prefs.setBoolPref(PREF_DISCOVERY, true);
|
||||
|
||||
const testUrl = "http://example.com";
|
||||
const testPresentationId = "test-presentation-id";
|
||||
|
||||
let mockDevice = createDevice("device.local",
|
||||
12345,
|
||||
"service.name",
|
||||
"_mozilla_papi._tcp");
|
||||
let mockSDObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {
|
||||
listener.onDiscoveryStarted(serviceType);
|
||||
listener.onServiceFound(createDevice("",
|
||||
0,
|
||||
mockDevice.serviceName,
|
||||
mockDevice.serviceType));
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {}
|
||||
};
|
||||
},
|
||||
registerService: function(serviceInfo, listener) {},
|
||||
resolveService: function(serviceInfo, listener) {
|
||||
listener.onServiceResolved(createDevice(mockDevice.host,
|
||||
mockDevice.port,
|
||||
mockDevice.serviceName,
|
||||
mockDevice.serviceType));
|
||||
}
|
||||
};
|
||||
|
||||
let mockServerObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
|
||||
requestSession: function(deviceInfo, url, presentationId) {
|
||||
this.request = {
|
||||
deviceInfo: deviceInfo,
|
||||
url: url,
|
||||
presentationId: presentationId,
|
||||
};
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
|
||||
let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) {
|
||||
this.device = device;
|
||||
},
|
||||
};
|
||||
|
||||
provider.listener = listener;
|
||||
|
||||
let controlChannel = listener.device.establishControlChannel(testUrl, testPresentationId);
|
||||
|
||||
Assert.equal(mockServerObj.request.deviceInfo.id, mockDevice.host);
|
||||
Assert.equal(mockServerObj.request.deviceInfo.host, mockDevice.host);
|
||||
Assert.equal(mockServerObj.request.deviceInfo.port, mockDevice.port);
|
||||
Assert.equal(mockServerObj.request.url, testUrl);
|
||||
Assert.equal(mockServerObj.request.presentationId, testPresentationId);
|
||||
|
||||
provider.listener = null;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function handleOnSessionRequest() {
|
||||
Services.prefs.setBoolPref(PREF_DISCOVERY, true);
|
||||
|
||||
let mockDevice = createDevice("device.local",
|
||||
12345,
|
||||
"service.name",
|
||||
"_mozilla_papi._tcp");
|
||||
let mockSDObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {
|
||||
listener.onDiscoveryStarted(serviceType);
|
||||
listener.onServiceFound(createDevice("",
|
||||
0,
|
||||
mockDevice.serviceName,
|
||||
mockDevice.serviceType));
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {}
|
||||
};
|
||||
},
|
||||
registerService: function(serviceInfo, listener) {},
|
||||
resolveService: function(serviceInfo, listener) {
|
||||
listener.onServiceResolved(createDevice(mockDevice.host,
|
||||
mockDevice.port,
|
||||
mockDevice.serviceName,
|
||||
mockDevice.serviceType));
|
||||
}
|
||||
};
|
||||
|
||||
let mockServerObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
|
||||
startService: function() {},
|
||||
sessionRequest: function() {},
|
||||
close: function() {},
|
||||
id: '',
|
||||
port: 0,
|
||||
listener: null,
|
||||
};
|
||||
|
||||
let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
|
||||
let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) {},
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {},
|
||||
onSessionRequest: function(device, url, presentationId, controlChannel) {
|
||||
Assert.ok(true, "recieve onSessionRequest event");
|
||||
this.request = {
|
||||
deviceId: device.id,
|
||||
url: url,
|
||||
presentationId: presentationId,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
provider.listener = listener;
|
||||
|
||||
const deviceInfo = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
|
||||
id: mockDevice.host,
|
||||
host: mockDevice.host,
|
||||
port: 54321,
|
||||
};
|
||||
|
||||
const testUrl = "http://example.com";
|
||||
const testPresentationId = "test-presentation-id";
|
||||
const testControlChannel = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
|
||||
};
|
||||
provider.QueryInterface(Ci.nsITCPPresentationServerListener)
|
||||
.onSessionRequest(deviceInfo, testUrl, testPresentationId, testControlChannel);
|
||||
|
||||
Assert.equal(listener.request.deviceId, deviceInfo.id);
|
||||
Assert.equal(listener.request.url, testUrl);
|
||||
Assert.equal(listener.request.presentationId, testPresentationId);
|
||||
|
||||
provider.listener = null;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function handleOnSessionRequestFromUnknownDevice() {
|
||||
let mockSDObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {},
|
||||
registerService: function(serviceInfo, listener) {},
|
||||
resolveService: function(serviceInfo, listener) {}
|
||||
};
|
||||
|
||||
let mockServerObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
|
||||
init: function() {},
|
||||
sessionRequest: function() {},
|
||||
close: function() {},
|
||||
id: '',
|
||||
port: 0,
|
||||
listener: null,
|
||||
};
|
||||
|
||||
let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
|
||||
let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) {
|
||||
Assert.ok(false, "shouldn't create any new device");
|
||||
},
|
||||
removeDevice: function(device) {
|
||||
Assert.ok(false, "shouldn't remote any device");
|
||||
},
|
||||
updateDevice: function(device) {
|
||||
Assert.ok(false, "shouldn't update any device");
|
||||
},
|
||||
onSessionRequest: function(device, url, presentationId, controlChannel) {
|
||||
Assert.ok(true, "recieve onSessionRequest event");
|
||||
this.request = {
|
||||
deviceId: device.id,
|
||||
url: url,
|
||||
presentationId: presentationId,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
provider.listener = listener;
|
||||
|
||||
const deviceInfo = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
|
||||
id: "unknown-device.local",
|
||||
host: "unknown-device.local",
|
||||
port: 12345,
|
||||
};
|
||||
|
||||
const testUrl = "http://example.com";
|
||||
const testPresentationId = "test-presentation-id";
|
||||
const testControlChannel = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
|
||||
};
|
||||
provider.QueryInterface(Ci.nsITCPPresentationServerListener)
|
||||
.onSessionRequest(deviceInfo, testUrl, testPresentationId, testControlChannel);
|
||||
|
||||
Assert.equal(listener.request.deviceId, deviceInfo.id);
|
||||
Assert.equal(listener.request.url, testUrl);
|
||||
Assert.equal(listener.request.presentationId, testPresentationId);
|
||||
|
||||
provider.listener = null;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function ignoreSelfDevice() {
|
||||
Services.prefs.setBoolPref(PREF_DISCOVERY, false);
|
||||
Services.prefs.setBoolPref(PREF_DISCOVERABLE, true);
|
||||
@@ -913,7 +688,7 @@ function ignoreSelfDevice() {
|
||||
|
||||
let mockServerObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
|
||||
init: function() {},
|
||||
startService: function() {},
|
||||
sessionRequest: function() {},
|
||||
close: function() {},
|
||||
id: '',
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
include PPrintingTypes;
|
||||
include protocol PPrinting;
|
||||
include protocol PRemotePrintJob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace embedding {
|
||||
|
||||
@@ -8,6 +8,7 @@ include protocol PContent;
|
||||
include protocol PBrowser;
|
||||
include protocol PPrintProgressDialog;
|
||||
include protocol PPrintSettingsDialog;
|
||||
include protocol PRemotePrintJob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace embedding {
|
||||
@@ -17,6 +18,7 @@ sync protocol PPrinting
|
||||
manager PContent;
|
||||
manages PPrintProgressDialog;
|
||||
manages PPrintSettingsDialog;
|
||||
manages PRemotePrintJob;
|
||||
|
||||
parent:
|
||||
sync ShowProgress(PBrowser browser,
|
||||
@@ -37,6 +39,7 @@ parent:
|
||||
returns(nsresult rv);
|
||||
|
||||
child:
|
||||
async PRemotePrintJob();
|
||||
__delete__();
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* 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 protocol PRemotePrintJob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace embedding {
|
||||
|
||||
@@ -12,6 +14,7 @@ struct CStringKeyValue {
|
||||
};
|
||||
|
||||
struct PrintData {
|
||||
nullable PRemotePrintJob remotePrintJob;
|
||||
int32_t startPageRange;
|
||||
int32_t endPageRange;
|
||||
double edgeTop;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
@@ -19,9 +19,11 @@
|
||||
#include "PrintDataUtils.h"
|
||||
#include "PrintProgressDialogParent.h"
|
||||
#include "PrintSettingsDialogParent.h"
|
||||
#include "mozilla/layout/RemotePrintJobParent.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layout;
|
||||
|
||||
namespace mozilla {
|
||||
namespace embedding {
|
||||
@@ -102,6 +104,10 @@ PrintingParent::ShowPrintDialog(PBrowserParent* aParent,
|
||||
|
||||
// And send it back.
|
||||
rv = po->SerializeToPrintData(settings, nullptr, aResult);
|
||||
|
||||
PRemotePrintJobParent* remotePrintJob = new RemotePrintJobParent(settings);
|
||||
aResult->remotePrintJobParent() = SendPRemotePrintJobConstructor(remotePrintJob);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -183,6 +189,20 @@ PrintingParent::DeallocPPrintSettingsDialogParent(PPrintSettingsDialogParent* aD
|
||||
return true;
|
||||
}
|
||||
|
||||
PRemotePrintJobParent*
|
||||
PrintingParent::AllocPRemotePrintJobParent()
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("No default constructors for implementations.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
PrintingParent::DeallocPRemotePrintJobParent(PRemotePrintJobParent* aDoomed)
|
||||
{
|
||||
delete aDoomed;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PrintingParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,10 @@ class PPrintProgressDialogParent;
|
||||
class PPrintSettingsDialogParent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
class PRemotePrintJobParent;
|
||||
}
|
||||
|
||||
namespace embedding {
|
||||
|
||||
class PrintingParent final : public PPrintingParent
|
||||
@@ -49,6 +53,12 @@ public:
|
||||
virtual bool
|
||||
DeallocPPrintSettingsDialogParent(PPrintSettingsDialogParent* aActor);
|
||||
|
||||
virtual PRemotePrintJobParent*
|
||||
AllocPRemotePrintJobParent();
|
||||
|
||||
virtual bool
|
||||
DeallocPRemotePrintJobParent(PRemotePrintJobParent* aActor);
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy);
|
||||
|
||||
@@ -69,4 +79,3 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
* 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 "nsPrintingProxy.h"
|
||||
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/layout/RemotePrintJobChild.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIPrintingPromptService.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsPrintingProxy.h"
|
||||
#include "nsPrintOptionsImpl.h"
|
||||
#include "PrintDataUtils.h"
|
||||
#include "PrintProgressDialogChild.h"
|
||||
@@ -20,6 +22,7 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::embedding;
|
||||
using namespace mozilla::layout;
|
||||
|
||||
static StaticRefPtr<nsPrintingProxy> sPrintingProxyInstance;
|
||||
|
||||
@@ -233,3 +236,18 @@ nsPrintingProxy::DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aAc
|
||||
// will take itself out.
|
||||
return true;
|
||||
}
|
||||
|
||||
PRemotePrintJobChild*
|
||||
nsPrintingProxy::AllocPRemotePrintJobChild()
|
||||
{
|
||||
RefPtr<RemotePrintJobChild> remotePrintJob = new RemotePrintJobChild();
|
||||
return remotePrintJob.forget().take();
|
||||
}
|
||||
|
||||
bool
|
||||
nsPrintingProxy::DeallocPRemotePrintJobChild(PRemotePrintJobChild* aDoomed)
|
||||
{
|
||||
RemotePrintJobChild* remotePrintJob = static_cast<RemotePrintJobChild*>(aDoomed);
|
||||
NS_RELEASE(remotePrintJob);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#include "nsIPrintingPromptService.h"
|
||||
#include "mozilla/embedding/PPrintingChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
class PRemotePrintJobChild;
|
||||
}
|
||||
}
|
||||
|
||||
class nsPrintingProxy: public nsIPrintingPromptService,
|
||||
public mozilla::embedding::PPrintingChild
|
||||
{
|
||||
@@ -39,6 +45,12 @@ public:
|
||||
|
||||
virtual bool
|
||||
DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aActor) override;
|
||||
|
||||
virtual PRemotePrintJobChild*
|
||||
AllocPRemotePrintJobChild() override;
|
||||
|
||||
virtual bool
|
||||
DeallocPRemotePrintJobChild(PRemotePrintJobChild* aActor) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+40
-6
@@ -42,6 +42,9 @@ struct ID3D11Texture2D;
|
||||
struct ID3D11Device;
|
||||
struct ID2D1Device;
|
||||
struct IDWriteRenderingParams;
|
||||
struct IDWriteFont;
|
||||
struct IDWriteFontFamily;
|
||||
struct IDWriteFontFace;
|
||||
|
||||
class GrContext;
|
||||
|
||||
@@ -667,6 +670,29 @@ protected:
|
||||
UserData mUserData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived classes hold a native font resource from which to create
|
||||
* ScaledFonts.
|
||||
*/
|
||||
class NativeFontResource : public RefCounted<NativeFontResource>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource)
|
||||
|
||||
/**
|
||||
* Creates a ScaledFont using the font corresponding to the index and
|
||||
* the given glyph size.
|
||||
*
|
||||
* @param aIndex index for the font within the resource.
|
||||
* @param aGlyphSize the size of ScaledFont required.
|
||||
* @return an already_addrefed ScaledFont, containing nullptr if failed.
|
||||
*/
|
||||
virtual already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) = 0;
|
||||
|
||||
virtual ~NativeFontResource() {};
|
||||
};
|
||||
|
||||
/** This class is designed to allow passing additional glyph rendering
|
||||
* parameters to the glyph drawing functions. This is an empty wrapper class
|
||||
* merely used to allow holding on to and passing around platform specific
|
||||
@@ -703,6 +729,9 @@ public:
|
||||
virtual DrawTargetType GetType() const = 0;
|
||||
|
||||
virtual BackendType GetBackendType() const = 0;
|
||||
|
||||
virtual bool IsRecording() const { return false; }
|
||||
|
||||
/**
|
||||
* Returns a SourceSurface which is a snapshot of the current contents of the DrawTarget.
|
||||
* Multiple calls to Snapshot() without any drawing operations in between will
|
||||
@@ -1190,16 +1219,15 @@ public:
|
||||
CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize);
|
||||
|
||||
/**
|
||||
* This creates a ScaledFont from TrueType data.
|
||||
* This creates a NativeFontResource from TrueType data.
|
||||
*
|
||||
* @param aData Pointer to the data
|
||||
* @param aSize Size of the TrueType data
|
||||
* @param aFaceIndex Index of the font face in the truetype data this ScaledFont needs to represent.
|
||||
* @param aGlyphSize Size of the glyphs in this ScaledFont
|
||||
* @param aType Type of ScaledFont that should be created.
|
||||
* @param aType Type of NativeFontResource that should be created.
|
||||
* @return a NativeFontResource of nullptr if failed.
|
||||
*/
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType);
|
||||
static already_AddRefed<NativeFontResource>
|
||||
CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType);
|
||||
|
||||
/**
|
||||
* This creates a scaled font with an associated cairo_scaled_font_t, and
|
||||
@@ -1314,6 +1342,12 @@ public:
|
||||
static uint64_t GetD2DVRAMUsageSourceSurface();
|
||||
static void D2DCleanup();
|
||||
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateScaledFontForDWriteFont(IDWriteFont* aFont,
|
||||
IDWriteFontFamily* aFontFamily,
|
||||
IDWriteFontFace* aFontFace,
|
||||
Float aSize);
|
||||
|
||||
private:
|
||||
static ID2D1Device *mD2D1Device;
|
||||
static ID3D10Device1 *mD3D10Device;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_AutoHelpersWin_h
|
||||
#define mozilla_gfx_AutoHelpersWin_h
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
// Get the global device context, and auto-release it on destruction.
|
||||
class AutoDC
|
||||
{
|
||||
public:
|
||||
AutoDC() {
|
||||
mDC = ::GetDC(nullptr);
|
||||
}
|
||||
|
||||
~AutoDC() {
|
||||
::ReleaseDC(nullptr, mDC);
|
||||
}
|
||||
|
||||
HDC GetDC() {
|
||||
return mDC;
|
||||
}
|
||||
|
||||
private:
|
||||
HDC mDC;
|
||||
};
|
||||
|
||||
// Select a font into the given DC, and auto-restore.
|
||||
class AutoSelectFont
|
||||
{
|
||||
public:
|
||||
AutoSelectFont(HDC aDC, LOGFONTW *aLogFont)
|
||||
: mOwnsFont(false)
|
||||
{
|
||||
mFont = ::CreateFontIndirectW(aLogFont);
|
||||
if (mFont) {
|
||||
mOwnsFont = true;
|
||||
mDC = aDC;
|
||||
mOldFont = (HFONT)::SelectObject(aDC, mFont);
|
||||
} else {
|
||||
mOldFont = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AutoSelectFont(HDC aDC, HFONT aFont)
|
||||
: mOwnsFont(false)
|
||||
{
|
||||
mDC = aDC;
|
||||
mFont = aFont;
|
||||
mOldFont = (HFONT)::SelectObject(aDC, aFont);
|
||||
}
|
||||
|
||||
~AutoSelectFont() {
|
||||
if (mOldFont) {
|
||||
::SelectObject(mDC, mOldFont);
|
||||
if (mOwnsFont) {
|
||||
::DeleteObject(mFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return mFont != nullptr;
|
||||
}
|
||||
|
||||
HFONT GetFont() const {
|
||||
return mFont;
|
||||
}
|
||||
|
||||
private:
|
||||
HDC mDC;
|
||||
HFONT mFont;
|
||||
HFONT mOldFont;
|
||||
bool mOwnsFont;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_AutoHelpersWin_h
|
||||
@@ -0,0 +1,80 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_BigEndianInts_h
|
||||
#define mozilla_BigEndianInts_h
|
||||
|
||||
#include "mozilla/Endian.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct BigEndianUint16
|
||||
{
|
||||
#ifdef __SUNPRO_CC
|
||||
BigEndianUint16& operator=(const uint16_t aValue)
|
||||
{
|
||||
value = NativeEndian::swapToBigEndian(aValue);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
MOZ_IMPLICIT BigEndianUint16(const uint16_t aValue)
|
||||
{
|
||||
value = NativeEndian::swapToBigEndian(aValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
operator uint16_t() const
|
||||
{
|
||||
return NativeEndian::swapFromBigEndian(value);
|
||||
}
|
||||
|
||||
friend inline bool
|
||||
operator==(const BigEndianUint16& lhs, const BigEndianUint16& rhs)
|
||||
{
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
friend inline bool
|
||||
operator!=(const BigEndianUint16& lhs, const BigEndianUint16& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
struct BigEndianUint32
|
||||
{
|
||||
#ifdef __SUNPRO_CC
|
||||
BigEndianUint32& operator=(const uint32_t aValue)
|
||||
{
|
||||
value = NativeEndian::swapToBigEndian(aValue);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
MOZ_IMPLICIT BigEndianUint32(const uint32_t aValue)
|
||||
{
|
||||
value = NativeEndian::swapToBigEndian(aValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
operator uint32_t() const
|
||||
{
|
||||
return NativeEndian::swapFromBigEndian(value);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_BigEndianInts_h
|
||||
@@ -5,19 +5,26 @@
|
||||
|
||||
#include "DrawEventRecorder.h"
|
||||
#include "PathRecording.h"
|
||||
#include "RecordingTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
using namespace std;
|
||||
|
||||
const uint32_t kMagicInt = 0xc001feed;
|
||||
|
||||
DrawEventRecorderPrivate::DrawEventRecorderPrivate(std::ostream *aStream)
|
||||
: mOutputStream(aStream)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderPrivate::WriteHeader()
|
||||
{
|
||||
WriteElement(*mOutputStream, kMagicInt);
|
||||
WriteElement(*mOutputStream, kMajorRevision);
|
||||
WriteElement(*mOutputStream, kMinorRevision);
|
||||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderPrivate::RecordEvent(const RecordedEvent &aEvent)
|
||||
{
|
||||
@@ -34,9 +41,7 @@ DrawEventRecorderFile::DrawEventRecorderFile(const char *aFilename)
|
||||
{
|
||||
mOutputStream = &mOutputFile;
|
||||
|
||||
WriteElement(*mOutputStream, kMagicInt);
|
||||
WriteElement(*mOutputStream, kMajorRevision);
|
||||
WriteElement(*mOutputStream, kMinorRevision);
|
||||
WriteHeader();
|
||||
}
|
||||
|
||||
DrawEventRecorderFile::~DrawEventRecorderFile()
|
||||
@@ -50,5 +55,40 @@ DrawEventRecorderFile::Flush()
|
||||
mOutputFile.flush();
|
||||
}
|
||||
|
||||
DrawEventRecorderMemory::DrawEventRecorderMemory()
|
||||
: DrawEventRecorderPrivate(nullptr)
|
||||
{
|
||||
mOutputStream = &mMemoryStream;
|
||||
|
||||
WriteHeader();
|
||||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderMemory::Flush()
|
||||
{
|
||||
mOutputStream->flush();
|
||||
}
|
||||
|
||||
size_t
|
||||
DrawEventRecorderMemory::RecordingSize()
|
||||
{
|
||||
return mMemoryStream.tellp();
|
||||
}
|
||||
|
||||
bool
|
||||
DrawEventRecorderMemory::CopyRecording(char* aBuffer, size_t aBufferLen)
|
||||
{
|
||||
return !!mMemoryStream.read(aBuffer, aBufferLen);
|
||||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderMemory::WipeRecording()
|
||||
{
|
||||
mMemoryStream.str(std::string());
|
||||
mMemoryStream.clear();
|
||||
|
||||
WriteHeader();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
+59
-11
@@ -29,22 +29,29 @@ public:
|
||||
explicit DrawEventRecorderPrivate(std::ostream *aStream);
|
||||
virtual ~DrawEventRecorderPrivate() { }
|
||||
|
||||
void WriteHeader();
|
||||
|
||||
void RecordEvent(const RecordedEvent &aEvent);
|
||||
void WritePath(const PathRecording *aPath);
|
||||
|
||||
void AddStoredPath(const ReferencePtr aPath) {
|
||||
mStoredPaths.insert(aPath);
|
||||
void AddStoredObject(const ReferencePtr aObject) {
|
||||
mStoredObjects.insert(aObject);
|
||||
}
|
||||
|
||||
void RemoveStoredPath(const ReferencePtr aPath) {
|
||||
mStoredPaths.erase(aPath);
|
||||
void RemoveStoredObject(const ReferencePtr aObject) {
|
||||
mStoredObjects.erase(aObject);
|
||||
}
|
||||
|
||||
bool HasStoredPath(const ReferencePtr aPath) {
|
||||
if (mStoredPaths.find(aPath) != mStoredPaths.end()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool HasStoredObject(const ReferencePtr aObject) {
|
||||
return mStoredObjects.find(aObject) != mStoredObjects.end();
|
||||
}
|
||||
|
||||
void AddStoredFontData(const uint64_t aFontDataKey) {
|
||||
mStoredFontData.insert(aFontDataKey);
|
||||
}
|
||||
|
||||
bool HasStoredFontData(const uint64_t aFontDataKey) {
|
||||
return mStoredFontData.find(aFontDataKey) != mStoredFontData.end();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -54,12 +61,14 @@ protected:
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef std::unordered_set<const void*> ObjectSet;
|
||||
typedef std::unordered_set<uint64_t> Uint64Set;
|
||||
#else
|
||||
typedef std::set<const void*> ObjectSet;
|
||||
typedef std::set<uint64_t> Uint64Set;
|
||||
#endif
|
||||
|
||||
ObjectSet mStoredPaths;
|
||||
ObjectSet mStoredScaledFonts;
|
||||
ObjectSet mStoredObjects;
|
||||
Uint64Set mStoredFontData;
|
||||
};
|
||||
|
||||
class DrawEventRecorderFile : public DrawEventRecorderPrivate
|
||||
@@ -75,6 +84,45 @@ private:
|
||||
std::ofstream mOutputFile;
|
||||
};
|
||||
|
||||
class DrawEventRecorderMemory final : public DrawEventRecorderPrivate
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderMemory)
|
||||
|
||||
/**
|
||||
* Constructs a DrawEventRecorder that stores the recording in memory.
|
||||
*/
|
||||
DrawEventRecorderMemory();
|
||||
|
||||
/**
|
||||
* @return the current size of the recording (in chars).
|
||||
*/
|
||||
size_t RecordingSize();
|
||||
|
||||
/**
|
||||
* Copies at most aBufferLen chars of the recording into aBuffer.
|
||||
*
|
||||
* @param aBuffer buffer to receive the recording chars
|
||||
* @param aBufferLen length of aBuffer
|
||||
* @return true if copied successfully
|
||||
*/
|
||||
bool CopyRecording(char* aBuffer, size_t aBufferLen);
|
||||
|
||||
/**
|
||||
* Wipes the internal recording buffer, but the recorder does NOT forget which
|
||||
* objects it has recorded. This can be used so that a recording can be copied
|
||||
* and processed in chunks, releasing memory as it goes.
|
||||
*/
|
||||
void WipeRecording();
|
||||
|
||||
private:
|
||||
~DrawEventRecorderMemory() {};
|
||||
|
||||
void Flush() final;
|
||||
|
||||
std::stringstream mMemoryStream;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
+186
-82
@@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
@@ -10,10 +11,70 @@
|
||||
#include "Logging.h"
|
||||
#include "Tools.h"
|
||||
#include "Filters.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "RecordingTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
struct RecordingSourceSurfaceUserData
|
||||
{
|
||||
void *refPtr;
|
||||
RefPtr<DrawEventRecorderPrivate> recorder;
|
||||
};
|
||||
|
||||
void RecordingSourceSurfaceUserDataFunc(void *aUserData)
|
||||
{
|
||||
RecordingSourceSurfaceUserData *userData =
|
||||
static_cast<RecordingSourceSurfaceUserData*>(aUserData);
|
||||
|
||||
userData->recorder->RemoveStoredObject(userData->refPtr);
|
||||
userData->recorder->RecordEvent(
|
||||
RecordedSourceSurfaceDestruction(userData->refPtr));
|
||||
|
||||
delete userData;
|
||||
}
|
||||
|
||||
static void
|
||||
StoreSourceSurface(DrawEventRecorderPrivate *aRecorder, SourceSurface *aSurface,
|
||||
DataSourceSurface *aDataSurf, const char *reason)
|
||||
{
|
||||
if (!aDataSurf) {
|
||||
gfxWarning() << "Recording failed to record SourceSurface for " << reason;
|
||||
// Insert a bogus source surface.
|
||||
int32_t stride = aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat());
|
||||
UniquePtr<uint8_t[]> sourceData(new uint8_t[stride * aSurface->GetSize().height]());
|
||||
aRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(aSurface, sourceData.get(), stride,
|
||||
aSurface->GetSize(), aSurface->GetFormat()));
|
||||
} else {
|
||||
DataSourceSurface::ScopedMap map(aDataSurf, DataSourceSurface::READ);
|
||||
aRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(aSurface, map.GetData(), map.GetStride(),
|
||||
aDataSurf->GetSize(), aDataSurf->GetFormat()));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EnsureSurfaceStored(DrawEventRecorderPrivate *aRecorder, SourceSurface *aSurface,
|
||||
const char *reason)
|
||||
{
|
||||
if (aRecorder->HasStoredObject(aSurface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
|
||||
StoreSourceSurface(aRecorder, aSurface, dataSurf, reason);
|
||||
aRecorder->AddStoredObject(aSurface);
|
||||
|
||||
RecordingSourceSurfaceUserData *userData = new RecordingSourceSurfaceUserData;
|
||||
userData->refPtr = aSurface;
|
||||
userData->recorder = aRecorder;
|
||||
aSurface->AddUserData(reinterpret_cast<UserDataKey*>(aRecorder),
|
||||
userData, &RecordingSourceSurfaceUserDataFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
class SourceSurfaceRecording : public SourceSurface
|
||||
{
|
||||
public:
|
||||
@@ -21,10 +82,12 @@ public:
|
||||
SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
|
||||
: mFinalSurface(aFinalSurface), mRecorder(aRecorder)
|
||||
{
|
||||
mRecorder->AddStoredObject(this);
|
||||
}
|
||||
|
||||
~SourceSurfaceRecording()
|
||||
{
|
||||
mRecorder->RemoveStoredObject(this);
|
||||
mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
|
||||
}
|
||||
|
||||
@@ -44,10 +107,12 @@ public:
|
||||
GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder)
|
||||
: mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder)
|
||||
{
|
||||
mRecorder->AddStoredObject(this);
|
||||
}
|
||||
|
||||
~GradientStopsRecording()
|
||||
{
|
||||
mRecorder->RemoveStoredObject(this);
|
||||
mRecorder->RecordEvent(RecordedGradientStopsDestruction(this));
|
||||
}
|
||||
|
||||
@@ -86,29 +151,39 @@ public:
|
||||
FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder)
|
||||
: mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder)
|
||||
{
|
||||
mRecorder->AddStoredObject(this);
|
||||
}
|
||||
|
||||
~FilterNodeRecording()
|
||||
{
|
||||
mRecorder->RemoveStoredObject(this);
|
||||
mRecorder->RecordEvent(RecordedFilterNodeDestruction(this));
|
||||
}
|
||||
|
||||
static FilterNode*
|
||||
GetFilterNode(FilterNode* aNode)
|
||||
{
|
||||
if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
|
||||
gfxWarning() << "Non recording filter node used with recording DrawTarget!";
|
||||
return aNode;
|
||||
}
|
||||
|
||||
return static_cast<FilterNodeRecording*>(aNode)->mFinalFilterNode;
|
||||
}
|
||||
|
||||
virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) override
|
||||
{
|
||||
EnsureSurfaceStored(mRecorder, aSurface, "SetInput");
|
||||
|
||||
mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
|
||||
mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface));
|
||||
}
|
||||
virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) override
|
||||
{
|
||||
FilterNode *finalNode = aFilter;
|
||||
if (aFilter->GetBackendType() != FILTER_BACKEND_RECORDING) {
|
||||
gfxWarning() << "Non recording filter node used with recording DrawTarget!";
|
||||
} else {
|
||||
finalNode = static_cast<FilterNodeRecording*>(aFilter)->mFinalFilterNode;
|
||||
}
|
||||
MOZ_ASSERT(mRecorder->HasStoredObject(aFilter));
|
||||
|
||||
mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
|
||||
mFinalFilterNode->SetInput(aIndex, finalNode);
|
||||
mFinalFilterNode->SetInput(aIndex, GetFilterNode(aFilter));
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +202,7 @@ public:
|
||||
FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
|
||||
FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
|
||||
FORWARD_SET_ATTRIBUTE(const Point&, POINT);
|
||||
FORWARD_SET_ATTRIBUTE(const Matrix&, MATRIX);
|
||||
FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
|
||||
FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
|
||||
FORWARD_SET_ATTRIBUTE(const Color&, COLOR);
|
||||
@@ -144,17 +220,6 @@ public:
|
||||
RefPtr<DrawEventRecorderPrivate> mRecorder;
|
||||
};
|
||||
|
||||
static FilterNode*
|
||||
GetFilterNode(FilterNode* aNode)
|
||||
{
|
||||
if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
|
||||
gfxWarning() << "Non recording filter node used with recording DrawTarget!";
|
||||
return aNode;
|
||||
}
|
||||
|
||||
return static_cast<FilterNodeRecording*>(aNode)->mFinalFilterNode;
|
||||
}
|
||||
|
||||
struct AdjustedPattern
|
||||
{
|
||||
explicit AdjustedPattern(const Pattern &aPattern)
|
||||
@@ -233,6 +298,16 @@ DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarge
|
||||
mFormat = mFinalDT->GetFormat();
|
||||
}
|
||||
|
||||
DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording *aDT,
|
||||
const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
: mRecorder(aDT->mRecorder)
|
||||
, mFinalDT(aDT->mFinalDT->CreateSimilarDrawTarget(aSize, aFormat))
|
||||
{
|
||||
mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(this, aSize, aFormat));
|
||||
mFormat = mFinalDT->GetFormat();
|
||||
}
|
||||
|
||||
DrawTargetRecording::~DrawTargetRecording()
|
||||
{
|
||||
mRecorder->RecordEvent(RecordedDrawTargetDestruction(this));
|
||||
@@ -243,6 +318,8 @@ DrawTargetRecording::FillRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
|
||||
mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions);
|
||||
}
|
||||
@@ -253,6 +330,8 @@ DrawTargetRecording::StrokeRect(const Rect &aRect,
|
||||
const StrokeOptions &aStrokeOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
|
||||
mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
|
||||
}
|
||||
@@ -264,29 +343,22 @@ DrawTargetRecording::StrokeLine(const Point &aBegin,
|
||||
const StrokeOptions &aStrokeOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
|
||||
mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
|
||||
}
|
||||
|
||||
Path*
|
||||
DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const
|
||||
{
|
||||
if (aPath->GetBackendType() != BackendType::RECORDING) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<const PathRecording*>(aPath)->mPath;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::Fill(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsureStored(aPath);
|
||||
RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
mRecorder->RecordEvent(RecordedFill(this, const_cast<Path*>(aPath), aPattern, aOptions));
|
||||
mFinalDT->Fill(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aOptions);
|
||||
mRecorder->RecordEvent(RecordedFill(this, pathRecording, aPattern, aOptions));
|
||||
mFinalDT->Fill(pathRecording->mPath, *AdjustedPattern(aPattern), aOptions);
|
||||
}
|
||||
|
||||
struct RecordingFontUserData
|
||||
@@ -315,10 +387,20 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
|
||||
const DrawOptions &aOptions,
|
||||
const GlyphRenderingOptions *aRenderingOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) {
|
||||
// TODO support font in b2g recordings
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont));
|
||||
RecordedFontData fontData(aFont);
|
||||
RecordedFontDetails fontDetails;
|
||||
if (fontData.GetFontDetails(fontDetails)) {
|
||||
if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
|
||||
mRecorder->RecordEvent(fontData);
|
||||
mRecorder->AddStoredFontData(fontDetails.fontDataKey);
|
||||
}
|
||||
mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, fontDetails));
|
||||
}
|
||||
#endif
|
||||
RecordingFontUserData *userData = new RecordingFontUserData;
|
||||
userData->refPtr = aFont;
|
||||
@@ -339,6 +421,9 @@ DrawTargetRecording::Mask(const Pattern &aSource,
|
||||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aSource);
|
||||
EnsurePatternDependenciesStored(aMask);
|
||||
|
||||
mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
|
||||
mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
|
||||
}
|
||||
@@ -349,6 +434,9 @@ DrawTargetRecording::MaskSurface(const Pattern &aSource,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsurePatternDependenciesStored(aSource);
|
||||
EnsureSurfaceStored(mRecorder, aMask, "MaskSurface");
|
||||
|
||||
mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
|
||||
mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
|
||||
}
|
||||
@@ -359,10 +447,11 @@ DrawTargetRecording::Stroke(const Path *aPath,
|
||||
const StrokeOptions &aStrokeOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsureStored(aPath);
|
||||
RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
mRecorder->RecordEvent(RecordedStroke(this, const_cast<Path*>(aPath), aPattern, aStrokeOptions, aOptions));
|
||||
mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
|
||||
mRecorder->RecordEvent(RecordedStroke(this, pathRecording, aPattern, aStrokeOptions, aOptions));
|
||||
mFinalDT->Stroke(pathRecording->mPath, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
@@ -384,6 +473,8 @@ DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
|
||||
const DrawSurfaceOptions &aSurfOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
EnsureSurfaceStored(mRecorder, aSurface, "DrawSurface");
|
||||
|
||||
mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
|
||||
mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource, aSurfOptions, aOptions);
|
||||
}
|
||||
@@ -396,6 +487,8 @@ DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
Float aSigma,
|
||||
CompositionOp aOp)
|
||||
{
|
||||
EnsureSurfaceStored(mRecorder, aSurface, "DrawSurfaceWithShadow");
|
||||
|
||||
mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
|
||||
mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor, aOffset, aSigma, aOp);
|
||||
}
|
||||
@@ -406,8 +499,10 @@ DrawTargetRecording::DrawFilter(FilterNode *aNode,
|
||||
const Point &aDestPoint,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
|
||||
|
||||
mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
|
||||
mFinalDT->DrawFilter(GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions);
|
||||
mFinalDT->DrawFilter(FilterNodeRecording::GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions);
|
||||
}
|
||||
|
||||
already_AddRefed<FilterNode>
|
||||
@@ -434,6 +529,8 @@ DrawTargetRecording::CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{
|
||||
EnsureSurfaceStored(mRecorder, aSurface, "CopySurface");
|
||||
|
||||
mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
|
||||
mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination);
|
||||
}
|
||||
@@ -441,10 +538,10 @@ DrawTargetRecording::CopySurface(SourceSurface *aSurface,
|
||||
void
|
||||
DrawTargetRecording::PushClip(const Path *aPath)
|
||||
{
|
||||
EnsureStored(aPath);
|
||||
RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
|
||||
|
||||
mRecorder->RecordEvent(RecordedPushClip(this, const_cast<Path*>(aPath)));
|
||||
mFinalDT->PushClip(GetPathForPathRecording(aPath));
|
||||
mRecorder->RecordEvent(RecordedPushClip(this, pathRecording));
|
||||
mFinalDT->PushClip(pathRecording->mPath);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -490,21 +587,7 @@ DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const
|
||||
dataSurf = aSurface->GetDataSurface();
|
||||
}
|
||||
|
||||
if (!dataSurf) {
|
||||
gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
|
||||
// Insert a bogus source surface.
|
||||
uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
|
||||
memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
|
||||
mRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(retSurf, sourceData,
|
||||
surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
|
||||
surf->GetSize(), surf->GetFormat()));
|
||||
delete [] sourceData;
|
||||
} else {
|
||||
mRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
|
||||
dataSurf->GetSize(), dataSurf->GetFormat()));
|
||||
}
|
||||
StoreSourceSurface(mRecorder, retSurf, dataSurf, "OptimizeSourceSurface");
|
||||
|
||||
return retSurf.forget();
|
||||
}
|
||||
@@ -517,22 +600,7 @@ DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &a
|
||||
RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
|
||||
|
||||
if (!dataSurf) {
|
||||
gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
|
||||
// Insert a bogus source surface.
|
||||
uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
|
||||
memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
|
||||
mRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(retSurf, sourceData,
|
||||
surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
|
||||
surf->GetSize(), surf->GetFormat()));
|
||||
delete [] sourceData;
|
||||
} else {
|
||||
mRecorder->RecordEvent(
|
||||
RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
|
||||
dataSurf->GetSize(), dataSurf->GetFormat()));
|
||||
}
|
||||
StoreSourceSurface(mRecorder, retSurf, dataSurf, "CreateSourceSurfaceFromNativeSurface");
|
||||
|
||||
return retSurf.forget();
|
||||
}
|
||||
@@ -540,8 +608,7 @@ DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &a
|
||||
already_AddRefed<DrawTarget>
|
||||
DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
|
||||
{
|
||||
RefPtr<DrawTarget> dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
|
||||
return MakeAndAddRef<DrawTargetRecording>(mRecorder.get(), dt);
|
||||
return MakeAndAddRef<DrawTargetRecording>(this, aSize, aFormat);
|
||||
}
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
@@ -573,17 +640,54 @@ DrawTargetRecording::SetTransform(const Matrix &aTransform)
|
||||
mFinalDT->SetTransform(aTransform);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::EnsureStored(const Path *aPath)
|
||||
already_AddRefed<PathRecording>
|
||||
DrawTargetRecording::EnsurePathStored(const Path *aPath)
|
||||
{
|
||||
if (!mRecorder->HasStoredPath(aPath)) {
|
||||
if (aPath->GetBackendType() != BackendType::RECORDING) {
|
||||
gfxWarning() << "Cannot record this fill path properly!";
|
||||
} else {
|
||||
PathRecording *recPath = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
|
||||
mRecorder->RecordEvent(RecordedPathCreation(recPath));
|
||||
mRecorder->AddStoredPath(aPath);
|
||||
recPath->mStoredRecorders.push_back(mRecorder);
|
||||
RefPtr<PathRecording> pathRecording;
|
||||
if (aPath->GetBackendType() == BackendType::RECORDING) {
|
||||
pathRecording = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
|
||||
if (mRecorder->HasStoredObject(aPath)) {
|
||||
return pathRecording.forget();
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
|
||||
FillRule fillRule = aPath->GetFillRule();
|
||||
RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
|
||||
RefPtr<PathBuilderRecording> builderRecording =
|
||||
new PathBuilderRecording(builder, fillRule);
|
||||
aPath->StreamToSink(builderRecording);
|
||||
pathRecording = builderRecording->Finish().downcast<PathRecording>();
|
||||
}
|
||||
|
||||
mRecorder->RecordEvent(RecordedPathCreation(pathRecording));
|
||||
mRecorder->AddStoredObject(pathRecording);
|
||||
pathRecording->mStoredRecorders.push_back(mRecorder);
|
||||
|
||||
return pathRecording.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::EnsurePatternDependenciesStored(const Pattern &aPattern)
|
||||
{
|
||||
switch (aPattern.GetType()) {
|
||||
case PatternType::COLOR:
|
||||
// No dependencies here.
|
||||
return;
|
||||
case PatternType::LINEAR_GRADIENT:
|
||||
{
|
||||
MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::RADIAL_GRADIENT:
|
||||
{
|
||||
MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE:
|
||||
{
|
||||
const SurfacePattern *pat = static_cast<const SurfacePattern*>(&aPattern);
|
||||
EnsureSurfaceStored(mRecorder, pat->mSurface, "EnsurePatternDependenciesStored");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
@@ -17,10 +18,22 @@ class DrawTargetRecording : public DrawTarget
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording, override)
|
||||
DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false);
|
||||
|
||||
/**
|
||||
* Used for creating a DrawTargetRecording for a CreateSimilarDrawTarget call.
|
||||
*
|
||||
* @param aDT DrawTargetRecording on which CreateSimilarDrawTarget was called
|
||||
* @param aSize size for the similar DrawTarget
|
||||
* @param aFormat format for the similar DrawTarget
|
||||
*/
|
||||
DrawTargetRecording(const DrawTargetRecording *aDT, const IntSize &aSize,
|
||||
SurfaceFormat aFormat);
|
||||
|
||||
~DrawTargetRecording();
|
||||
|
||||
virtual DrawTargetType GetType() const override { return mFinalDT->GetType(); }
|
||||
virtual BackendType GetBackendType() const override { return mFinalDT->GetBackendType(); }
|
||||
virtual bool IsRecording() const override { return true; }
|
||||
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
|
||||
@@ -275,7 +288,8 @@ public:
|
||||
|
||||
private:
|
||||
Path *GetPathForPathRecording(const Path *aPath) const;
|
||||
void EnsureStored(const Path *aPath);
|
||||
already_AddRefed<PathRecording> EnsurePathStored(const Path *aPath);
|
||||
void EnsurePatternDependenciesStored(const Pattern &aPattern);
|
||||
|
||||
RefPtr<DrawEventRecorderPrivate> mRecorder;
|
||||
RefPtr<DrawTarget> mFinalDT;
|
||||
|
||||
@@ -575,7 +575,8 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
||||
{
|
||||
if (aFont->GetType() != FontType::MAC &&
|
||||
aFont->GetType() != FontType::SKIA &&
|
||||
aFont->GetType() != FontType::GDI) {
|
||||
aFont->GetType() != FontType::GDI &&
|
||||
aFont->GetType() != FontType::DWRITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+37
-32
@@ -21,6 +21,7 @@
|
||||
|
||||
#if defined(WIN32)
|
||||
#include "ScaledFontWin.h"
|
||||
#include "NativeFontResourceGDI.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_DARWIN
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "DrawTargetD2D1.h"
|
||||
#include "ScaledFontDWrite.h"
|
||||
#include "NativeFontResourceDWrite.h"
|
||||
#include <d3d10_1.h>
|
||||
#include "HelpersD2D.h"
|
||||
#endif
|
||||
@@ -48,6 +50,7 @@
|
||||
|
||||
#include "DrawEventRecorder.h"
|
||||
|
||||
#include "Preferences.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
@@ -152,31 +155,9 @@ HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit)
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
// These values we initialize with should match those in
|
||||
// PreferenceAccess::RegisterAll method.
|
||||
int32_t PreferenceAccess::sGfxLogLevel = LOG_DEFAULT;
|
||||
|
||||
PreferenceAccess* PreferenceAccess::sAccess = nullptr;
|
||||
PreferenceAccess::~PreferenceAccess()
|
||||
{
|
||||
}
|
||||
|
||||
// Just a placeholder, the derived class will set the variable to default
|
||||
// if the preference doesn't exist.
|
||||
void PreferenceAccess::LivePref(const char* aName, int32_t* aVar, int32_t aDef)
|
||||
{
|
||||
*aVar = aDef;
|
||||
}
|
||||
|
||||
// This will be called with the derived class, so we will want to register
|
||||
// the callbacks with it.
|
||||
void PreferenceAccess::SetAccess(PreferenceAccess* aAccess) {
|
||||
sAccess = aAccess;
|
||||
if (sAccess) {
|
||||
RegisterAll();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t LoggingPrefs::sGfxLogLevel =
|
||||
PreferenceAccess::RegisterLivePref("gfx.logging.level", &sGfxLogLevel,
|
||||
LOG_DEFAULT);
|
||||
|
||||
#ifdef WIN32
|
||||
ID3D10Device1 *Factory::mD3D10Device;
|
||||
@@ -552,7 +533,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
#if defined(USE_CAIRO) || defined(USE_SKIA)
|
||||
case NativeFontType::GDI_FONT_FACE:
|
||||
{
|
||||
return MakeAndAddRef<ScaledFontWin>(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
|
||||
return MakeAndAddRef<ScaledFontWin>(static_cast<LOGFONTW*>(aNativeFont.mFont), aSize);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -574,20 +555,35 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize,
|
||||
uint32_t aFaceIndex, Float aGlyphSize,
|
||||
FontType aType)
|
||||
already_AddRefed<NativeFontResource>
|
||||
Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
|
||||
FontType aType)
|
||||
{
|
||||
switch (aType) {
|
||||
#ifdef WIN32
|
||||
case FontType::DWRITE:
|
||||
{
|
||||
return MakeAndAddRef<ScaledFontDWrite>(aData, aSize, aFaceIndex, aGlyphSize);
|
||||
return NativeFontResourceDWrite::Create(aData, aSize,
|
||||
/* aNeedsCairo = */ false);
|
||||
}
|
||||
#endif
|
||||
case FontType::CAIRO:
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (GetDirect3D11Device()) {
|
||||
return NativeFontResourceDWrite::Create(aData, aSize,
|
||||
/* aNeedsCairo = */ true);
|
||||
} else {
|
||||
return NativeFontResourceGDI::Create(aData, aSize,
|
||||
/* aNeedsCairo = */ true);
|
||||
}
|
||||
#else
|
||||
gfxWarning() << "Unable to create cairo scaled font from truetype data";
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
gfxWarning() << "Unable to create requested font type from truetype data";
|
||||
gfxWarning() << "Unable to create requested font resource from truetype data";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -803,6 +799,15 @@ Factory::D2DCleanup()
|
||||
DrawTargetD2D::CleanupD2D();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
Factory::CreateScaledFontForDWriteFont(IDWriteFont* aFont,
|
||||
IDWriteFontFamily* aFontFamily,
|
||||
IDWriteFontFace* aFontFace,
|
||||
float aSize)
|
||||
{
|
||||
return MakeAndAddRef<ScaledFontDWrite>(aFont, aFontFamily, aFontFace, aSize);
|
||||
}
|
||||
|
||||
#endif // XP_WIN
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
|
||||
+5
-29
@@ -62,24 +62,9 @@ inline mozilla::LogLevel PRLogLevelForLevel(int aLevel) {
|
||||
}
|
||||
#endif
|
||||
|
||||
class PreferenceAccess
|
||||
class LoggingPrefs
|
||||
{
|
||||
public:
|
||||
virtual ~PreferenceAccess();
|
||||
|
||||
// This should connect the variable aVar to be updated whenever a preference
|
||||
// aName is modified. aDefault would be used if the preference is undefined,
|
||||
// so that we always get the valid value for aVar.
|
||||
virtual void LivePref(const char* aName, int32_t* aVar, int32_t aDefault);
|
||||
|
||||
public:
|
||||
static void SetAccess(PreferenceAccess* aAccess);
|
||||
|
||||
public:
|
||||
// For each preference that needs to be accessed in Moz2D, add a variable
|
||||
// to hold it, as well as the call to LivePref in the RegisterAll() method
|
||||
// below.
|
||||
|
||||
// Used to choose the level of logging we get. The higher the number,
|
||||
// the more logging we get. Value of zero will give you no logging,
|
||||
// 1 just errors, 2 adds warnings and 3 adds logging/debug. 4 is used to
|
||||
@@ -88,15 +73,6 @@ public:
|
||||
// in addition to setting the value to 4, you will need to set an
|
||||
// environment variable NSPR_LOG_MODULES to gfx:4. See prlog.h for details.
|
||||
static int32_t sGfxLogLevel;
|
||||
|
||||
private:
|
||||
static void RegisterAll() {
|
||||
// The default values (last parameter) should match the initialization
|
||||
// values in Factory.cpp, otherwise the standalone Moz2D will get different
|
||||
// defaults.
|
||||
sAccess->LivePref("gfx.logging.level", &sGfxLogLevel, LOG_DEFAULT);
|
||||
}
|
||||
static PreferenceAccess* sAccess;
|
||||
};
|
||||
|
||||
/// Graphics logging is available in both debug and release builds and is
|
||||
@@ -164,7 +140,7 @@ struct BasicLogger
|
||||
// OutputMessage below. If making any changes here, also make it
|
||||
// in the appropriate places in that method.
|
||||
static bool ShouldOutputMessage(int aLevel) {
|
||||
if (PreferenceAccess::sGfxLogLevel >= aLevel) {
|
||||
if (LoggingPrefs::sGfxLogLevel >= aLevel) {
|
||||
#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
|
||||
return true;
|
||||
#else
|
||||
@@ -173,7 +149,7 @@ struct BasicLogger
|
||||
return true;
|
||||
} else
|
||||
#endif
|
||||
if ((PreferenceAccess::sGfxLogLevel >= LOG_DEBUG_PRLOG) ||
|
||||
if ((LoggingPrefs::sGfxLogLevel >= LOG_DEBUG_PRLOG) ||
|
||||
(aLevel < LOG_DEBUG)) {
|
||||
return true;
|
||||
}
|
||||
@@ -197,7 +173,7 @@ struct BasicLogger
|
||||
// If making any logic changes to this method, you should probably
|
||||
// make the corresponding change in the ShouldOutputMessage method
|
||||
// above.
|
||||
if (PreferenceAccess::sGfxLogLevel >= aLevel) {
|
||||
if (LoggingPrefs::sGfxLogLevel >= aLevel) {
|
||||
#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
|
||||
printf_stderr("%s%s", aString.c_str(), aNoNewline ? "" : "\n");
|
||||
#else
|
||||
@@ -206,7 +182,7 @@ struct BasicLogger
|
||||
PR_LogPrint("%s%s", aString.c_str(), aNoNewline ? "" : "\n");
|
||||
} else
|
||||
#endif
|
||||
if ((PreferenceAccess::sGfxLogLevel >= LOG_DEBUG_PRLOG) ||
|
||||
if ((LoggingPrefs::sGfxLogLevel >= LOG_DEBUG_PRLOG) ||
|
||||
(aLevel < LOG_DEBUG)) {
|
||||
printf("%s%s", aString.c_str(), aNoNewline ? "" : "\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "NativeFontResourceDWrite.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
|
||||
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
public:
|
||||
DWriteFontFileLoader()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileLoader)) {
|
||||
*ppObject = static_cast<IDWriteFontFileLoader*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IDWriteFontFileLoader methods
|
||||
/**
|
||||
* Important! Note the key here has to be a uint64_t that will have been
|
||||
* generated by incrementing sNextFontFileKey.
|
||||
*/
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
CreateStreamFromKey(void const* fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
OUT IDWriteFontFileStream** fontFileStream);
|
||||
|
||||
/**
|
||||
* Gets the singleton loader instance. Note that when using this font
|
||||
* loader, the key must be a uint64_t that has been generated by incrementing
|
||||
* sNextFontFileKey.
|
||||
* Also note that this is _not_ threadsafe.
|
||||
*/
|
||||
static IDWriteFontFileLoader* Instance()
|
||||
{
|
||||
if (!mInstance) {
|
||||
mInstance = new DWriteFontFileLoader();
|
||||
DrawTargetD2D::GetDWriteFactory()->
|
||||
RegisterFontFileLoader(mInstance);
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
static IDWriteFontFileLoader* mInstance;
|
||||
};
|
||||
|
||||
class DWriteFontFileStream : public IDWriteFontFileStream
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used by the FontFileLoader to create a new font stream,
|
||||
* this font stream is created from data in memory. The memory
|
||||
* passed may be released after object creation, it will be
|
||||
* copied internally.
|
||||
*
|
||||
* @param aData Font data
|
||||
*/
|
||||
DWriteFontFileStream(uint8_t *aData, uint32_t aSize, uint64_t aFontFileKey);
|
||||
~DWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
--mRefCnt;
|
||||
if (mRefCnt == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
// IDWriteFontFileStream methods
|
||||
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
OUT void** fragmentContext);
|
||||
|
||||
virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> mData;
|
||||
uint32_t mRefCnt;
|
||||
uint64_t mFontFileKey;
|
||||
};
|
||||
|
||||
IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = nullptr;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
IDWriteFontFileStream **fontFileStream)
|
||||
{
|
||||
if (!fontFileReferenceKey || !fontFileStream) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
|
||||
auto found = sFontFileStreams.find(fontFileKey);
|
||||
if (found == sFontFileStreams.end()) {
|
||||
*fontFileStream = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
found->second->AddRef();
|
||||
*fontFileStream = found->second;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWriteFontFileStream::DWriteFontFileStream(uint8_t *aData, uint32_t aSize,
|
||||
uint64_t aFontFileKey)
|
||||
: mRefCnt(0)
|
||||
, mFontFileKey(aFontFileKey)
|
||||
{
|
||||
mData.resize(aSize);
|
||||
memcpy(&mData.front(), aData, aSize);
|
||||
}
|
||||
|
||||
DWriteFontFileStream::~DWriteFontFileStream()
|
||||
{
|
||||
sFontFileStreams.erase(mFontFileKey);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > mData.size()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// truncate the 64 bit fileOffset to size_t sized index into mData
|
||||
size_t index = static_cast<size_t>(fileOffset);
|
||||
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[index];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<NativeFontResourceDWrite>
|
||||
NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
|
||||
bool aNeedsCairo)
|
||||
{
|
||||
IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
|
||||
if (!factory) {
|
||||
gfxWarning() << "Failed to get DWrite Factory.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t fontFileKey = sNextFontFileKey++;
|
||||
RefPtr<IDWriteFontFileStream> ffsRef =
|
||||
new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
|
||||
sFontFileStreams[fontFileKey] = ffsRef;
|
||||
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
HRESULT hr =
|
||||
factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey),
|
||||
DWriteFontFileLoader::Instance(),
|
||||
getter_AddRefs(fontFile));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to load font file from data!";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL isSupported;
|
||||
DWRITE_FONT_FILE_TYPE fileType;
|
||||
DWRITE_FONT_FACE_TYPE faceType;
|
||||
UINT32 numberOfFaces;
|
||||
hr = fontFile->Analyze(&isSupported, &fileType, &faceType, &numberOfFaces);
|
||||
if (FAILED(hr) || !isSupported) {
|
||||
gfxWarning() << "Font file is not supported.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<NativeFontResourceDWrite> fontResource =
|
||||
new NativeFontResourceDWrite(factory, fontFile.forget(), faceType,
|
||||
numberOfFaces, aNeedsCairo);
|
||||
return fontResource.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize)
|
||||
{
|
||||
if (aIndex >= mNumberOfFaces) {
|
||||
gfxWarning() << "Font face index is too high for font resource.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IDWriteFontFile *fontFile = mFontFile;
|
||||
RefPtr<IDWriteFontFace> fontFace;
|
||||
if (FAILED(mFactory->CreateFontFace(mFaceType, 1, &fontFile, aIndex,
|
||||
DWRITE_FONT_SIMULATIONS_NONE, getter_AddRefs(fontFace)))) {
|
||||
gfxWarning() << "Failed to create font face from font file data.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ScaledFontBase> scaledFont = new ScaledFontDWrite(fontFace, aGlyphSize);
|
||||
if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) {
|
||||
gfxWarning() << "Unable to create cairo scaled font DWrite font.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
@@ -0,0 +1,56 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_NativeFontResourceDWrite_h
|
||||
#define mozilla_gfx_NativeFontResourceDWrite_h
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
#include "2D.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class NativeFontResourceDWrite final : public NativeFontResource
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceDWrite)
|
||||
/**
|
||||
* Creates a NativeFontResourceDWrite if data is valid. Note aFontData will be
|
||||
* copied if required and so can be released after calling.
|
||||
*
|
||||
* @param aFontData the SFNT data.
|
||||
* @param aDataLength length of data.
|
||||
* @param aNeedsCairo whether the ScaledFont created needs a cairo scaled font
|
||||
* @return Referenced NativeFontResourceDWrite or nullptr if invalid.
|
||||
*/
|
||||
static already_AddRefed<NativeFontResourceDWrite>
|
||||
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceDWrite(IDWriteFactory *aFactory,
|
||||
already_AddRefed<IDWriteFontFile> aFontFile,
|
||||
DWRITE_FONT_FACE_TYPE aFaceType,
|
||||
uint32_t aNumberOfFaces, bool aNeedsCairo)
|
||||
: mFactory(aFactory), mFontFile(aFontFile), mFaceType(aFaceType)
|
||||
, mNumberOfFaces(aNumberOfFaces), mNeedsCairo(aNeedsCairo)
|
||||
{}
|
||||
|
||||
IDWriteFactory *mFactory;
|
||||
RefPtr<IDWriteFontFile> mFontFile;
|
||||
DWRITE_FONT_FACE_TYPE mFaceType;
|
||||
uint32_t mNumberOfFaces;
|
||||
bool mNeedsCairo;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceDWrite_h
|
||||
@@ -0,0 +1,112 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "NativeFontResourceGDI.h"
|
||||
|
||||
#include "Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "ScaledFontWin.h"
|
||||
#include "SFNTData.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
/* static */
|
||||
already_AddRefed<NativeFontResourceGDI>
|
||||
NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength,
|
||||
bool aNeedsCairo)
|
||||
{
|
||||
UniquePtr<SFNTData> sfntData = SFNTData::Create(aFontData, aDataLength);
|
||||
if (!sfntData) {
|
||||
gfxWarning() << "Failed to create SFNTData for ScaledFontWin.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Vector<mozilla::u16string> fontNames;
|
||||
if (!sfntData->GetU16FullNames(fontNames)) {
|
||||
gfxWarning() << "Failed to get font names from font.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// lfFaceName has a maximum length including null.
|
||||
for (size_t i = 0; i < fontNames.length(); ++i) {
|
||||
if (fontNames[i].size() > LF_FACESIZE - 1) {
|
||||
fontNames[i].resize(LF_FACESIZE - 1);
|
||||
}
|
||||
// Add null to end for easy copying later.
|
||||
fontNames[i].append(1, '\0');
|
||||
}
|
||||
|
||||
DWORD numberOfFontsAdded;
|
||||
HANDLE fontResourceHandle = ::AddFontMemResourceEx(aFontData, aDataLength,
|
||||
0, &numberOfFontsAdded);
|
||||
if (!fontResourceHandle) {
|
||||
gfxWarning() << "Failed to add memory font resource.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (numberOfFontsAdded != fontNames.length()) {
|
||||
gfxWarning() <<
|
||||
"Number of fonts added doesn't match number of names extracted.";
|
||||
}
|
||||
|
||||
RefPtr<NativeFontResourceGDI> fontResouce =
|
||||
new NativeFontResourceGDI(fontResourceHandle, Move(fontNames), aNeedsCairo);
|
||||
|
||||
return fontResouce.forget();
|
||||
}
|
||||
|
||||
NativeFontResourceGDI::~NativeFontResourceGDI()
|
||||
{
|
||||
::RemoveFontMemResourceEx(mFontResourceHandle);
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize)
|
||||
{
|
||||
if (aIndex >= mFontNames.length()) {
|
||||
gfxWarning() << "Font index is too high for font resource.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mFontNames[aIndex].empty()) {
|
||||
gfxWarning() << "Font name for index is empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LOGFONTW logFont;
|
||||
logFont.lfHeight = 0;
|
||||
logFont.lfWidth = 0;
|
||||
logFont.lfEscapement = 0;
|
||||
logFont.lfOrientation = 0;
|
||||
logFont.lfWeight = FW_DONTCARE;
|
||||
logFont.lfItalic = FALSE;
|
||||
logFont.lfUnderline = FALSE;
|
||||
logFont.lfStrikeOut = FALSE;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = DEFAULT_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
|
||||
// Copy name to mLogFont (null already included in font name). We cast here
|
||||
// because for VS2015 char16_t != wchar_t, even though they are both 16 bit.
|
||||
mFontNames[aIndex].copy(reinterpret_cast<char16_t*>(logFont.lfFaceName),
|
||||
mFontNames[aIndex].length());
|
||||
|
||||
// Constructor for ScaledFontWin dereferences and copies the LOGFONT, so we
|
||||
// are safe to pass this reference.
|
||||
RefPtr<ScaledFontBase> scaledFont = new ScaledFontWin(&logFont, aGlyphSize);
|
||||
if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) {
|
||||
gfxWarning() << "Unable to create cairo scaled font DWrite font.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
@@ -0,0 +1,57 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_NativeFontResourceGDI_h
|
||||
#define mozilla_gfx_NativeFontResourceGDI_h
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "2D.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "u16string.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class NativeFontResourceGDI final : public NativeFontResource
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceGDI)
|
||||
/**
|
||||
* Creates a NativeFontResourceGDI if data is valid. Note aFontData will be
|
||||
* copied if required and so can be released after calling.
|
||||
*
|
||||
* @param aFontData the SFNT data.
|
||||
* @param aDataLength length of data.
|
||||
* @param aNeedsCairo whether the ScaledFont created need a cairo scaled font
|
||||
* @return Referenced NativeFontResourceGDI or nullptr if invalid.
|
||||
*/
|
||||
static already_AddRefed<NativeFontResourceGDI>
|
||||
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
|
||||
|
||||
~NativeFontResourceGDI();
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceGDI(HANDLE aFontResourceHandle,
|
||||
Vector<mozilla::u16string>&& aFontNames,
|
||||
bool aNeedsCairo)
|
||||
: mFontResourceHandle(aFontResourceHandle), mFontNames(Move(aFontNames))
|
||||
, mNeedsCairo(aNeedsCairo)
|
||||
{}
|
||||
|
||||
HANDLE mFontResourceHandle;
|
||||
Vector<mozilla::u16string> mFontNames;
|
||||
bool mNeedsCairo;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceGDI_h
|
||||
@@ -79,7 +79,7 @@ PathBuilderRecording::Finish()
|
||||
PathRecording::~PathRecording()
|
||||
{
|
||||
for (size_t i = 0; i < mStoredRecorders.size(); i++) {
|
||||
mStoredRecorders[i]->RemoveStoredPath(this);
|
||||
mStoredRecorders[i]->RemoveStoredObject(this);
|
||||
mStoredRecorders[i]->RecordEvent(RecordedPathDestruction(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "Preferences.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static PreferenceAccess* sAccess = nullptr;
|
||||
|
||||
struct Int32Pref
|
||||
{
|
||||
const char* name;
|
||||
int32_t* varPtr;
|
||||
};
|
||||
|
||||
static Vector<Int32Pref>& Int32Prefs()
|
||||
{
|
||||
static Vector<Int32Pref>* sInt32Prefs = new Vector<Int32Pref>();
|
||||
return *sInt32Prefs;
|
||||
}
|
||||
|
||||
/* static */
|
||||
int32_t
|
||||
PreferenceAccess::RegisterLivePref(const char* aName, int32_t* aVar,
|
||||
int32_t aDefault)
|
||||
{
|
||||
Int32Prefs().append(Int32Pref{ aName, aVar });
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
PreferenceAccess::SetAccess(PreferenceAccess* aAccess)
|
||||
{
|
||||
sAccess = aAccess;
|
||||
if (!sAccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
static uint32_t sProvideAccessCount;
|
||||
MOZ_ASSERT(!sProvideAccessCount++,
|
||||
"ProvideAccess must only be called with non-nullptr once.");
|
||||
#endif
|
||||
|
||||
for (Int32Pref pref : Int32Prefs()) {
|
||||
sAccess->LivePref(pref.name, pref.varPtr, *pref.varPtr);
|
||||
}
|
||||
Int32Prefs().clearAndFree();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,34 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_Preferences_h
|
||||
#define mozilla_gfx_Preferences_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class PreferenceAccess
|
||||
{
|
||||
public:
|
||||
virtual ~PreferenceAccess() {};
|
||||
|
||||
// This will be called with the derived class, so we will can register the
|
||||
// callbacks with it.
|
||||
static void SetAccess(PreferenceAccess* aAccess);
|
||||
|
||||
static int32_t RegisterLivePref(const char* aName, int32_t* aVar,
|
||||
int32_t aDefault);
|
||||
protected:
|
||||
// This should connect the variable aVar to be updated whenever a preference
|
||||
// aName is modified. aDefault would be used if the preference is undefined,
|
||||
// so that we always get the valid value for aVar.
|
||||
virtual void LivePref(const char* aName, int32_t* aVar, int32_t aDefault) = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_gfx_Preferences_h
|
||||
+117
-24
@@ -4,11 +4,13 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RecordedEvent.h"
|
||||
#include "PathRecording.h"
|
||||
|
||||
#include "PathRecording.h"
|
||||
#include "RecordingTypes.h"
|
||||
#include "Tools.h"
|
||||
#include "Filters.h"
|
||||
#include "Logging.h"
|
||||
#include "SFNTData.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@@ -27,6 +29,16 @@ static std::string NameFromBackend(BackendType aType)
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
Translator::CreateDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
RefPtr<DrawTarget> newDT =
|
||||
GetReferenceDrawTarget()->CreateSimilarDrawTarget(aSize, aFormat);
|
||||
AddDrawTarget(aRefPtr, newDT);
|
||||
return newDT.forget();
|
||||
}
|
||||
|
||||
#define LOAD_EVENT_TYPE(_typeenum, _class) \
|
||||
case _typeenum: return new _class(aStream)
|
||||
|
||||
@@ -66,6 +78,8 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType)
|
||||
LOAD_EVENT_TYPE(MASKSURFACE, RecordedMaskSurface);
|
||||
LOAD_EVENT_TYPE(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute);
|
||||
LOAD_EVENT_TYPE(FILTERNODESETINPUT, RecordedFilterNodeSetInput);
|
||||
LOAD_EVENT_TYPE(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget);
|
||||
LOAD_EVENT_TYPE(FONTDATA, RecordedFontData);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -139,6 +153,10 @@ RecordedEvent::GetEventName(EventType aType)
|
||||
return "SetAttribute";
|
||||
case FILTERNODESETINPUT:
|
||||
return "SetInput";
|
||||
case CREATESIMILARDRAWTARGET:
|
||||
return "CreateSimilarDrawTarget";
|
||||
case FONTDATA:
|
||||
return "FontData";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -366,10 +384,9 @@ void
|
||||
RecordedDrawTargetCreation::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
RefPtr<DrawTarget> newDT =
|
||||
aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(mSize, mFormat);
|
||||
aTranslator->AddDrawTarget(mRefPtr, newDT);
|
||||
aTranslator->CreateDrawTarget(mRefPtr, mSize, mFormat);
|
||||
|
||||
if (mHasExistingData) {
|
||||
if (newDT && mHasExistingData) {
|
||||
Rect dataRect(0, 0, mExistingData->GetSize().width, mExistingData->GetSize().height);
|
||||
newDT->DrawSurface(mExistingData, dataRect, dataRect);
|
||||
}
|
||||
@@ -452,6 +469,36 @@ RecordedDrawTargetDestruction::OutputSimpleEventInfo(stringstream &aStringStream
|
||||
aStringStream << "[" << mRefPtr << "] DrawTarget Destruction";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedCreateSimilarDrawTarget::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
RefPtr<DrawTarget> newDT =
|
||||
aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(mSize, mFormat);
|
||||
aTranslator->AddDrawTarget(mRefPtr, newDT);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedCreateSimilarDrawTarget::RecordToStream(ostream &aStream) const
|
||||
{
|
||||
WriteElement(aStream, mRefPtr);
|
||||
WriteElement(aStream, mSize);
|
||||
WriteElement(aStream, mFormat);
|
||||
}
|
||||
|
||||
RecordedCreateSimilarDrawTarget::RecordedCreateSimilarDrawTarget(istream &aStream)
|
||||
: RecordedEvent(CREATESIMILARDRAWTARGET)
|
||||
{
|
||||
ReadElement(aStream, mRefPtr);
|
||||
ReadElement(aStream, mSize);
|
||||
ReadElement(aStream, mFormat);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedCreateSimilarDrawTarget::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mRefPtr << "] CreateSimilarDrawTarget (Size: " << mSize.width << "x" << mSize.height << ")";
|
||||
}
|
||||
|
||||
struct GenericPattern
|
||||
{
|
||||
GenericPattern(const PatternStorage &aStorage, Translator *aTranslator)
|
||||
@@ -1344,17 +1391,75 @@ RecordedSnapshot::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
aStringStream << "[" << mRefPtr << "] Snapshot Created (DT: " << mDT << ")";
|
||||
}
|
||||
|
||||
RecordedScaledFontCreation::~RecordedScaledFontCreation()
|
||||
RecordedFontData::~RecordedFontData()
|
||||
{
|
||||
delete [] mData;
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
void
|
||||
RecordedFontData::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
RefPtr<NativeFontResource> fontResource =
|
||||
Factory::CreateNativeFontResource(mData, mFontDetails.size,
|
||||
aTranslator->GetDesiredFontType());
|
||||
aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedFontData::RecordToStream(std::ostream &aStream) const
|
||||
{
|
||||
MOZ_ASSERT(mGetFontFileDataSucceeded);
|
||||
|
||||
WriteElement(aStream, mFontDetails.fontDataKey);
|
||||
WriteElement(aStream, mFontDetails.size);
|
||||
aStream.write((const char*)mData, mFontDetails.size);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedFontData::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "Font Data of size " << mFontDetails.size;
|
||||
}
|
||||
|
||||
void
|
||||
RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize)
|
||||
{
|
||||
mData = new uint8_t[aSize];
|
||||
memcpy(mData, aData, aSize);
|
||||
mFontDetails.fontDataKey = SFNTData::GetUniqueKey(aData, aSize);
|
||||
mFontDetails.size = aSize;
|
||||
mFontDetails.index = aIndex;
|
||||
mFontDetails.glyphSize = aGlyphSize;
|
||||
}
|
||||
|
||||
bool
|
||||
RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails)
|
||||
{
|
||||
if (!mGetFontFileDataSucceeded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fontDetails.fontDataKey = mFontDetails.fontDataKey;
|
||||
fontDetails.size = mFontDetails.size;
|
||||
fontDetails.glyphSize = mFontDetails.glyphSize;
|
||||
fontDetails.index = mFontDetails.index;
|
||||
return true;
|
||||
}
|
||||
|
||||
RecordedFontData::RecordedFontData(istream &aStream)
|
||||
: RecordedEvent(FONTDATA)
|
||||
{
|
||||
ReadElement(aStream, mFontDetails.fontDataKey);
|
||||
ReadElement(aStream, mFontDetails.size);
|
||||
mData = new uint8_t[mFontDetails.size];
|
||||
aStream.read((char*)mData, mFontDetails.size);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
Factory::CreateScaledFontForTrueTypeData(mData, mSize, mIndex, mGlyphSize,
|
||||
aTranslator->GetDesiredFontType());
|
||||
NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey);
|
||||
RefPtr<ScaledFont> scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize);
|
||||
aTranslator->AddScaledFont(mRefPtr, scaledFont);
|
||||
}
|
||||
|
||||
@@ -1362,10 +1467,9 @@ void
|
||||
RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const
|
||||
{
|
||||
WriteElement(aStream, mRefPtr);
|
||||
WriteElement(aStream, mFontDataKey);
|
||||
WriteElement(aStream, mIndex);
|
||||
WriteElement(aStream, mGlyphSize);
|
||||
WriteElement(aStream, mSize);
|
||||
aStream.write((const char*)mData, mSize);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1374,25 +1478,13 @@ RecordedScaledFontCreation::OutputSimpleEventInfo(stringstream &aStringStream) c
|
||||
aStringStream << "[" << mRefPtr << "] ScaledFont Created";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedScaledFontCreation::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize)
|
||||
{
|
||||
mData = new uint8_t[aSize];
|
||||
memcpy(mData, aData, aSize);
|
||||
mSize = aSize;
|
||||
mIndex = aIndex;
|
||||
mGlyphSize = aGlyphSize;
|
||||
}
|
||||
|
||||
RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream)
|
||||
: RecordedEvent(SCALEDFONTCREATION)
|
||||
{
|
||||
ReadElement(aStream, mRefPtr);
|
||||
ReadElement(aStream, mFontDataKey);
|
||||
ReadElement(aStream, mIndex);
|
||||
ReadElement(aStream, mGlyphSize);
|
||||
ReadElement(aStream, mSize);
|
||||
mData = new uint8_t[mSize];
|
||||
aStream.read((char*)mData, mSize);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1479,6 +1571,7 @@ RecordedFilterNodeSetAttribute::PlayEvent(Translator *aTranslator) const
|
||||
REPLAY_SET_ATTRIBUTE(Rect, RECT);
|
||||
REPLAY_SET_ATTRIBUTE(IntRect, INTRECT);
|
||||
REPLAY_SET_ATTRIBUTE(Point, POINT);
|
||||
REPLAY_SET_ATTRIBUTE(Matrix, MATRIX);
|
||||
REPLAY_SET_ATTRIBUTE(Matrix5x4, MATRIX5X4);
|
||||
REPLAY_SET_ATTRIBUTE(Point3D, POINT3D);
|
||||
REPLAY_SET_ATTRIBUTE(Color, COLOR);
|
||||
|
||||
+104
-18
@@ -10,20 +10,24 @@
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include "RecordingTypes.h"
|
||||
#include "PathRecording.h"
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
struct PathOp;
|
||||
class PathRecording;
|
||||
|
||||
const uint32_t kMagicInt = 0xc001feed;
|
||||
|
||||
// A change in major revision means a change in event binary format, causing
|
||||
// loss of backwards compatibility. Old streams will not work in a player
|
||||
// using a newer major revision. And new streams will not work in a player
|
||||
// using an older major revision.
|
||||
const uint16_t kMajorRevision = 3;
|
||||
const uint16_t kMajorRevision = 4;
|
||||
// A change in minor revision means additions of new events. New streams will
|
||||
// not play in older players.
|
||||
const uint16_t kMinorRevision = 2;
|
||||
const uint16_t kMinorRevision = 0;
|
||||
|
||||
struct ReferencePtr
|
||||
{
|
||||
@@ -58,6 +62,14 @@ struct ReferencePtr
|
||||
uint64_t mLongPtr;
|
||||
};
|
||||
|
||||
struct RecordedFontDetails
|
||||
{
|
||||
uint64_t fontDataKey;
|
||||
uint32_t size;
|
||||
uint32_t index;
|
||||
Float glyphSize;
|
||||
};
|
||||
|
||||
// Used by the Azure drawing debugger (player2d)
|
||||
inline std::string StringFromPtr(ReferencePtr aPtr)
|
||||
{
|
||||
@@ -77,6 +89,7 @@ public:
|
||||
virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0;
|
||||
virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0;
|
||||
virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0;
|
||||
virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0;
|
||||
virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0;
|
||||
virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
|
||||
virtual void AddPath(ReferencePtr aRefPtr, Path *aPath) = 0;
|
||||
@@ -89,7 +102,12 @@ public:
|
||||
virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0;
|
||||
virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0;
|
||||
virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0;
|
||||
virtual void AddNativeFontResource(uint64_t aKey,
|
||||
NativeFontResource *aNativeFontResource) = 0;
|
||||
|
||||
virtual already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
|
||||
const IntSize &aSize,
|
||||
SurfaceFormat aFormat);
|
||||
virtual DrawTarget *GetReferenceDrawTarget() = 0;
|
||||
virtual FontType GetDesiredFontType() = 0;
|
||||
};
|
||||
@@ -171,10 +189,14 @@ public:
|
||||
FILTERNODEDESTRUCTION,
|
||||
DRAWFILTER,
|
||||
FILTERNODESETATTRIBUTE,
|
||||
FILTERNODESETINPUT
|
||||
FILTERNODESETINPUT,
|
||||
CREATESIMILARDRAWTARGET,
|
||||
FONTDATA,
|
||||
};
|
||||
static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1;
|
||||
|
||||
virtual ~RecordedEvent() {}
|
||||
|
||||
static std::string GetEventName(EventType aType);
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const {}
|
||||
@@ -281,6 +303,34 @@ private:
|
||||
MOZ_IMPLICIT RecordedDrawTargetDestruction(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedCreateSimilarDrawTarget : public RecordedEvent
|
||||
{
|
||||
public:
|
||||
RecordedCreateSimilarDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
: RecordedEvent(CREATESIMILARDRAWTARGET)
|
||||
, mRefPtr(aRefPtr) , mSize(aSize), mFormat(aFormat)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
|
||||
|
||||
virtual std::string GetName() const { return "CreateSimilarDrawTarget"; }
|
||||
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
|
||||
|
||||
ReferencePtr mRefPtr;
|
||||
IntSize mSize;
|
||||
SurfaceFormat mFormat;
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
MOZ_IMPLICIT RecordedCreateSimilarDrawTarget(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedFillRect : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedFillRect(DrawTarget *aDT, const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
|
||||
@@ -899,21 +949,59 @@ private:
|
||||
MOZ_IMPLICIT RecordedSnapshot(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedFontData : public RecordedEvent {
|
||||
public:
|
||||
|
||||
static void FontDataProc(const uint8_t *aData, uint32_t aSize,
|
||||
uint32_t aIndex, Float aGlyphSize, void* aBaton)
|
||||
{
|
||||
auto recordedFontData = static_cast<RecordedFontData*>(aBaton);
|
||||
recordedFontData->SetFontData(aData, aSize, aIndex, aGlyphSize);
|
||||
}
|
||||
|
||||
explicit RecordedFontData(ScaledFont *aScaledFont)
|
||||
: RecordedEvent(FONTDATA), mData(nullptr)
|
||||
{
|
||||
mGetFontFileDataSucceeded = aScaledFont->GetFontFileData(&FontDataProc, this);
|
||||
}
|
||||
|
||||
~RecordedFontData();
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
|
||||
|
||||
virtual std::string GetName() const { return "Font Data"; }
|
||||
virtual ReferencePtr GetObjectRef() const { return nullptr; };
|
||||
|
||||
void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex,
|
||||
Float aGlyphSize);
|
||||
|
||||
bool GetFontDetails(RecordedFontDetails& fontDetails);
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
uint8_t *mData;
|
||||
RecordedFontDetails mFontDetails;
|
||||
|
||||
bool mGetFontFileDataSucceeded = false;
|
||||
|
||||
MOZ_IMPLICIT RecordedFontData(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedScaledFontCreation : public RecordedEvent {
|
||||
public:
|
||||
static void FontDataProc(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize, void* aBaton)
|
||||
{
|
||||
static_cast<RecordedScaledFontCreation*>(aBaton)->SetFontData(aData, aSize, aIndex, aGlyphSize);
|
||||
}
|
||||
|
||||
RecordedScaledFontCreation(ReferencePtr aRefPtr, ScaledFont *aScaledFont)
|
||||
: RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr), mData(nullptr)
|
||||
RecordedScaledFontCreation(ReferencePtr aRefPtr,
|
||||
RecordedFontDetails aFontDetails)
|
||||
: RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr)
|
||||
, mFontDataKey(aFontDetails.fontDataKey)
|
||||
, mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index)
|
||||
{
|
||||
aScaledFont->GetFontFileData(&FontDataProc, this);
|
||||
}
|
||||
|
||||
~RecordedScaledFontCreation();
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
@@ -922,14 +1010,11 @@ public:
|
||||
virtual std::string GetName() const { return "ScaledFont Creation"; }
|
||||
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
|
||||
|
||||
void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize);
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
ReferencePtr mRefPtr;
|
||||
uint8_t *mData;
|
||||
uint32_t mSize;
|
||||
uint64_t mFontDataKey;
|
||||
Float mGlyphSize;
|
||||
uint32_t mIndex;
|
||||
|
||||
@@ -998,6 +1083,7 @@ public:
|
||||
ARGTYPE_RECT,
|
||||
ARGTYPE_INTRECT,
|
||||
ARGTYPE_POINT,
|
||||
ARGTYPE_MATRIX,
|
||||
ARGTYPE_MATRIX5X4,
|
||||
ARGTYPE_POINT3D,
|
||||
ARGTYPE_COLOR,
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "SFNTData.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "BigEndianInts.h"
|
||||
#include "Logging.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "SFNTNameTable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
#define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct TTCHeader
|
||||
{
|
||||
BigEndianUint32 ttcTag; // Always 'ttcf'
|
||||
BigEndianUint32 version; // Fixed, 0x00010000
|
||||
BigEndianUint32 numFonts;
|
||||
};
|
||||
|
||||
struct OffsetTable
|
||||
{
|
||||
BigEndianUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0.
|
||||
BigEndianUint16 numTables;
|
||||
BigEndianUint16 searchRange; // (Maximum power of 2 <= numTables) x 16.
|
||||
BigEndianUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
|
||||
BigEndianUint16 rangeShift; // NumTables x 16-searchRange.
|
||||
};
|
||||
|
||||
struct TableDirEntry
|
||||
{
|
||||
BigEndianUint32 tag; // 4 -byte identifier.
|
||||
BigEndianUint32 checkSum; // CheckSum for this table.
|
||||
BigEndianUint32 offset; // Offset from beginning of TrueType font file.
|
||||
BigEndianUint32 length; // Length of this table.
|
||||
|
||||
friend bool operator<(const TableDirEntry& lhs, const uint32_t aTag)
|
||||
{
|
||||
return lhs.tag < aTag;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
class SFNTData::Font
|
||||
{
|
||||
public:
|
||||
Font(const OffsetTable *aOffsetTable, const uint8_t *aFontData,
|
||||
uint32_t aDataLength)
|
||||
: mFontData(aFontData)
|
||||
, mFirstDirEntry(reinterpret_cast<const TableDirEntry*>(aOffsetTable + 1))
|
||||
, mEndOfDirEntries(mFirstDirEntry + aOffsetTable->numTables)
|
||||
, mDataLength(aDataLength)
|
||||
{
|
||||
}
|
||||
|
||||
bool GetU16FullName(mozilla::u16string& aU16FullName)
|
||||
{
|
||||
const TableDirEntry* dirEntry =
|
||||
GetDirEntry(TRUETYPE_TAG('n', 'a', 'm', 'e'));
|
||||
if (!dirEntry) {
|
||||
gfxWarning() << "Name table entry not found.";
|
||||
return false;
|
||||
}
|
||||
|
||||
UniquePtr<SFNTNameTable> nameTable =
|
||||
SFNTNameTable::Create((mFontData + dirEntry->offset), dirEntry->length);
|
||||
if (!nameTable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nameTable->GetU16FullName(aU16FullName);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const TableDirEntry*
|
||||
GetDirEntry(const uint32_t aTag)
|
||||
{
|
||||
const TableDirEntry* foundDirEntry =
|
||||
std::lower_bound(mFirstDirEntry, mEndOfDirEntries, aTag);
|
||||
|
||||
if (foundDirEntry == mEndOfDirEntries || foundDirEntry->tag != aTag) {
|
||||
gfxWarning() << "Font data does not contain tag.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mDataLength < (foundDirEntry->offset + foundDirEntry->length)) {
|
||||
gfxWarning() << "Font data too short to contain table.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return foundDirEntry;
|
||||
}
|
||||
|
||||
const uint8_t *mFontData;
|
||||
const TableDirEntry *mFirstDirEntry;
|
||||
const TableDirEntry *mEndOfDirEntries;
|
||||
uint32_t mDataLength;
|
||||
};
|
||||
|
||||
/* static */
|
||||
UniquePtr<SFNTData>
|
||||
SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
{
|
||||
MOZ_ASSERT(aFontData);
|
||||
|
||||
// Check to see if this is a font collection.
|
||||
if (aDataLength < sizeof(TTCHeader)) {
|
||||
gfxWarning() << "Font data too short.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const TTCHeader *ttcHeader = reinterpret_cast<const TTCHeader*>(aFontData);
|
||||
if (ttcHeader->ttcTag == TRUETYPE_TAG('t', 't', 'c', 'f')) {
|
||||
uint32_t numFonts = ttcHeader->numFonts;
|
||||
if (aDataLength < sizeof(TTCHeader) + (numFonts * sizeof(BigEndianUint32))) {
|
||||
gfxWarning() << "Font data too short to contain full TTC Header.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UniquePtr<SFNTData> sfntData(new SFNTData);
|
||||
const BigEndianUint32* offset =
|
||||
reinterpret_cast<const BigEndianUint32*>(aFontData + sizeof(TTCHeader));
|
||||
const BigEndianUint32* endOfOffsets = offset + numFonts;
|
||||
while (offset != endOfOffsets) {
|
||||
if (!sfntData->AddFont(aFontData, aDataLength, *offset)) {
|
||||
return nullptr;
|
||||
}
|
||||
++offset;
|
||||
}
|
||||
|
||||
return Move(sfntData);
|
||||
}
|
||||
|
||||
UniquePtr<SFNTData> sfntData(new SFNTData);
|
||||
if (!sfntData->AddFont(aFontData, aDataLength, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Move(sfntData);
|
||||
}
|
||||
|
||||
/* static */
|
||||
uint64_t
|
||||
SFNTData::GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
{
|
||||
uint64_t hash;
|
||||
UniquePtr<SFNTData> sfntData = SFNTData::Create(aFontData, aDataLength);
|
||||
mozilla::u16string firstName;
|
||||
if (sfntData && sfntData->GetU16FullName(0, firstName)) {
|
||||
hash = HashString(firstName.c_str(), firstName.length());
|
||||
} else {
|
||||
gfxWarning() << "Failed to get name from font data hashing whole font.";
|
||||
hash = HashString(aFontData, aDataLength);
|
||||
}
|
||||
|
||||
return hash << 32 | aDataLength;;
|
||||
}
|
||||
|
||||
SFNTData::~SFNTData()
|
||||
{
|
||||
for (size_t i = 0; i < mFonts.length(); ++i) {
|
||||
delete mFonts[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTData::GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName)
|
||||
{
|
||||
if (aIndex >= mFonts.length()) {
|
||||
gfxWarning() << "aIndex to font data too high.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return mFonts[aIndex]->GetU16FullName(aU16FullName);
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTData::GetU16FullNames(Vector<mozilla::u16string>& aU16FullNames)
|
||||
{
|
||||
bool fontFound = false;
|
||||
for (size_t i = 0; i < mFonts.length(); ++i) {
|
||||
mozilla::u16string name;
|
||||
if (mFonts[i]->GetU16FullName(name)) {
|
||||
fontFound = true;
|
||||
}
|
||||
aU16FullNames.append(Move(name));
|
||||
}
|
||||
|
||||
return fontFound;
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTData::GetIndexForU16Name(const mozilla::u16string& aU16FullName,
|
||||
uint32_t* aIndex)
|
||||
{
|
||||
for (size_t i = 0; i < mFonts.length(); ++i) {
|
||||
mozilla::u16string name;
|
||||
if (mFonts[i]->GetU16FullName(name) && name == aU16FullName) {
|
||||
*aIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTData::AddFont(const uint8_t *aFontData, uint32_t aDataLength,
|
||||
uint32_t aOffset)
|
||||
{
|
||||
uint32_t remainingLength = aDataLength - aOffset;
|
||||
if (remainingLength < sizeof(OffsetTable)) {
|
||||
gfxWarning() << "Font data too short to contain OffsetTable " << aOffset;
|
||||
return false;
|
||||
}
|
||||
|
||||
const OffsetTable *offsetTable =
|
||||
reinterpret_cast<const OffsetTable*>(aFontData + aOffset);
|
||||
if (remainingLength <
|
||||
sizeof(OffsetTable) + (offsetTable->numTables * sizeof(TableDirEntry))) {
|
||||
gfxWarning() << "Font data too short to contain tables.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return mFonts.append(new Font(offsetTable, aFontData, aDataLength));
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
@@ -0,0 +1,93 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_SFNTData_h
|
||||
#define mozilla_gfx_SFNTData_h
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "u16string.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class SFNTData final
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates an SFNTData if the header is a format that we understand and
|
||||
* aDataLength is sufficient for the length information in the header data.
|
||||
* Note that the data is NOT copied, so must exist the SFNTData's lifetime.
|
||||
*
|
||||
* @param aFontData the SFNT data.
|
||||
* @param aDataLength length
|
||||
* @return UniquePtr to a SFNTData or nullptr if the header is invalid.
|
||||
*/
|
||||
static UniquePtr<SFNTData> Create(const uint8_t *aFontData,
|
||||
uint32_t aDataLength);
|
||||
|
||||
/**
|
||||
* Creates a unique key for the given font data.
|
||||
*
|
||||
* @param aFontData the SFNT data
|
||||
* @param aDataLength length
|
||||
* @return unique key to be used for caching
|
||||
*/
|
||||
static uint64_t GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength);
|
||||
|
||||
~SFNTData();
|
||||
|
||||
/**
|
||||
* Gets the full name from the name table of the font corresponding to the
|
||||
* index. If the full name string is not present it will use the family space
|
||||
* concatenated with the style.
|
||||
* This will only read names that are already UTF16.
|
||||
*
|
||||
* @param aFontData SFNT data.
|
||||
* @param aDataLength length of aFontData.
|
||||
* @param aU16FullName string to be populated with the full name.
|
||||
* @return true if the full name is successfully read.
|
||||
*/
|
||||
bool GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName);
|
||||
|
||||
/**
|
||||
* Populate a Vector with the first UTF16 full name from each name table of
|
||||
* the fonts. If the full name string is not present it will use the family
|
||||
* space concatenated with the style.
|
||||
* This will only read names that are already UTF16.
|
||||
*
|
||||
* @param aU16FullNames the Vector to be populated.
|
||||
* @return true if at least one name found otherwise false.
|
||||
*/
|
||||
bool GetU16FullNames(Vector<mozilla::u16string>& aU16FullNames);
|
||||
|
||||
/**
|
||||
* Returns the index for the first UTF16 name matching aU16FullName.
|
||||
*
|
||||
* @param aU16FullName full name to find.
|
||||
* @param aIndex out param for the index if found.
|
||||
* @return true if the full name is successfully read.
|
||||
*/
|
||||
bool GetIndexForU16Name(const mozilla::u16string& aU16FullName, uint32_t* aIndex);
|
||||
|
||||
private:
|
||||
|
||||
SFNTData() {}
|
||||
|
||||
bool AddFont(const uint8_t *aFontData, uint32_t aDataLength,
|
||||
uint32_t aOffset);
|
||||
|
||||
// Internal representation of single font in font file.
|
||||
class Font;
|
||||
|
||||
Vector<Font*> mFonts;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_SFNTData_h
|
||||
@@ -0,0 +1,257 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "SFNTNameTable.h"
|
||||
|
||||
#include "BigEndianInts.h"
|
||||
#include "Logging.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static const BigEndianUint16 FORMAT_0 = 0;
|
||||
|
||||
static const BigEndianUint16 NAME_ID_FAMILY = 1;
|
||||
static const BigEndianUint16 NAME_ID_STYLE = 2;
|
||||
static const BigEndianUint16 NAME_ID_FULL = 4;
|
||||
|
||||
static const BigEndianUint16 PLATFORM_ID_UNICODE = 0;
|
||||
static const BigEndianUint16 PLATFORM_ID_MAC = 1;
|
||||
static const BigEndianUint16 PLATFORM_ID_MICROSOFT = 3;
|
||||
|
||||
static const BigEndianUint16 ENCODING_ID_MICROSOFT_SYMBOL = 0;
|
||||
static const BigEndianUint16 ENCODING_ID_MICROSOFT_UNICODEBMP = 1;
|
||||
static const BigEndianUint16 ENCODING_ID_MICROSOFT_UNICODEFULL = 10;
|
||||
|
||||
static const BigEndianUint16 LANG_ID_MAC_ENGLISH = 0;
|
||||
|
||||
static const BigEndianUint16 LANG_ID_MICROSOFT_EN_US = 0x0409;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// Name table has a header, followed by name records, followed by string data.
|
||||
struct NameHeader
|
||||
{
|
||||
BigEndianUint16 format; // Format selector (=0).
|
||||
BigEndianUint16 count; // Number of name records.
|
||||
BigEndianUint16 stringOffset; // Offset to string storage from start of table.
|
||||
};
|
||||
|
||||
struct NameRecord
|
||||
{
|
||||
BigEndianUint16 platformID;
|
||||
BigEndianUint16 encodingID; // Platform-specific encoding ID
|
||||
BigEndianUint16 languageID;
|
||||
BigEndianUint16 nameID;
|
||||
BigEndianUint16 length; // String length in bytes.
|
||||
BigEndianUint16 offset; // String offset from start of storage in bytes.
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* static */
|
||||
UniquePtr<SFNTNameTable>
|
||||
SFNTNameTable::Create(const uint8_t *aNameData, uint32_t aDataLength)
|
||||
{
|
||||
MOZ_ASSERT(aNameData);
|
||||
|
||||
if (aDataLength < sizeof(NameHeader)) {
|
||||
gfxWarning() << "Name data too short to contain NameHeader.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(aNameData);
|
||||
if (nameHeader->format != FORMAT_0) {
|
||||
gfxWarning() << "Only Name Table Format 0 is supported.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t stringOffset = nameHeader->stringOffset;
|
||||
|
||||
if (stringOffset !=
|
||||
sizeof(NameHeader) + (nameHeader->count * sizeof(NameRecord))) {
|
||||
gfxWarning() << "Name table string offset is incorrect.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aDataLength < stringOffset) {
|
||||
gfxWarning() << "Name data too short to contain name records.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return UniquePtr<SFNTNameTable>(
|
||||
new SFNTNameTable(nameHeader, aNameData, aDataLength));
|
||||
}
|
||||
|
||||
SFNTNameTable::SFNTNameTable(const NameHeader *aNameHeader,
|
||||
const uint8_t *aNameData, uint32_t aDataLength)
|
||||
: mFirstRecord(reinterpret_cast<const NameRecord*>(aNameData
|
||||
+ sizeof(NameHeader)))
|
||||
, mEndOfRecords(mFirstRecord + aNameHeader->count)
|
||||
, mStringData(aNameData + aNameHeader->stringOffset)
|
||||
, mStringDataLength(aDataLength - aNameHeader->stringOffset)
|
||||
{
|
||||
MOZ_ASSERT(reinterpret_cast<const uint8_t*>(aNameHeader) == aNameData);
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
static const BigEndianUint16 CANONICAL_LANG_ID = LANG_ID_MAC_ENGLISH;
|
||||
static const BigEndianUint16 PLATFORM_ID = PLATFORM_ID_MAC;
|
||||
#else
|
||||
static const BigEndianUint16 CANONICAL_LANG_ID = LANG_ID_MICROSOFT_EN_US;
|
||||
static const BigEndianUint16 PLATFORM_ID = PLATFORM_ID_MICROSOFT;
|
||||
#endif
|
||||
|
||||
static bool
|
||||
IsUTF16Encoding(const NameRecord *aNameRecord)
|
||||
{
|
||||
if (aNameRecord->platformID == PLATFORM_ID_MICROSOFT &&
|
||||
(aNameRecord->encodingID == ENCODING_ID_MICROSOFT_UNICODEBMP ||
|
||||
aNameRecord->encodingID == ENCODING_ID_MICROSOFT_SYMBOL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aNameRecord->platformID == PLATFORM_ID_UNICODE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static NameRecordMatchers*
|
||||
CreateCanonicalU16Matchers(const BigEndianUint16& aNameID)
|
||||
{
|
||||
NameRecordMatchers *matchers = new NameRecordMatchers();
|
||||
|
||||
// First, look for the English name (this will normally succeed).
|
||||
matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->languageID == CANONICAL_LANG_ID &&
|
||||
aNameRecord->platformID == PLATFORM_ID &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
|
||||
// Second, look for all languages.
|
||||
matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->platformID == PLATFORM_ID &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// On Mac may be dealing with font that only has Microsoft name entries.
|
||||
matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->languageID == LANG_ID_MICROSOFT_EN_US &&
|
||||
aNameRecord->platformID == PLATFORM_ID_MICROSOFT &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->platformID == PLATFORM_ID_MICROSOFT &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
#endif
|
||||
|
||||
return matchers;
|
||||
}
|
||||
|
||||
static const NameRecordMatchers&
|
||||
FullNameMatchers()
|
||||
{
|
||||
static const NameRecordMatchers *sFullNameMatchers =
|
||||
CreateCanonicalU16Matchers(NAME_ID_FULL);
|
||||
return *sFullNameMatchers;
|
||||
}
|
||||
|
||||
static const NameRecordMatchers&
|
||||
FamilyMatchers()
|
||||
{
|
||||
static const NameRecordMatchers *sFamilyMatchers =
|
||||
CreateCanonicalU16Matchers(NAME_ID_FAMILY);
|
||||
return *sFamilyMatchers;
|
||||
}
|
||||
|
||||
static const NameRecordMatchers&
|
||||
StyleMatchers()
|
||||
{
|
||||
static const NameRecordMatchers *sStyleMatchers =
|
||||
CreateCanonicalU16Matchers(NAME_ID_STYLE);
|
||||
return *sStyleMatchers;
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTNameTable::GetU16FullName(mozilla::u16string& aU16FullName)
|
||||
{
|
||||
if (ReadU16Name(FullNameMatchers(), aU16FullName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the full name record doesn't exist create the name from the family space
|
||||
// concatenated with the style.
|
||||
mozilla::u16string familyName;
|
||||
if (!ReadU16Name(FamilyMatchers(), familyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::u16string styleName;
|
||||
if (!ReadU16Name(StyleMatchers(), styleName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aU16FullName.assign(Move(familyName));
|
||||
aU16FullName.append(MOZ_UTF16(" "));
|
||||
aU16FullName.append(styleName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTNameTable::ReadU16Name(const NameRecordMatchers& aMatchers,
|
||||
mozilla::u16string& aU16Name)
|
||||
{
|
||||
MOZ_ASSERT(!aMatchers.empty());
|
||||
|
||||
for (size_t i = 0; i < aMatchers.length(); ++i) {
|
||||
const NameRecord* record = mFirstRecord;
|
||||
while (record != mEndOfRecords) {
|
||||
if (aMatchers[i](record)) {
|
||||
return ReadU16NameFromRecord(record, aU16Name);
|
||||
}
|
||||
++record;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SFNTNameTable::ReadU16NameFromRecord(const NameRecord *aNameRecord,
|
||||
mozilla::u16string& aU16Name)
|
||||
{
|
||||
uint32_t offset = aNameRecord->offset;
|
||||
uint32_t length = aNameRecord->length;
|
||||
if (mStringDataLength < offset + length) {
|
||||
gfxWarning() << "Name data too short to contain name string.";
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t *startOfName = mStringData + offset;
|
||||
size_t actualLength = length / sizeof(char16_t);
|
||||
UniquePtr<char16_t[]> nameData(new char16_t[actualLength]);
|
||||
NativeEndian::copyAndSwapFromBigEndian(nameData.get(), startOfName,
|
||||
actualLength);
|
||||
|
||||
aU16Name.assign(nameData.get(), actualLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
@@ -0,0 +1,67 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_SFNTNameTable_h
|
||||
#define mozilla_gfx_SFNTNameTable_h
|
||||
|
||||
#include "mozilla/Function.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "u16string.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
struct NameHeader;
|
||||
struct NameRecord;
|
||||
|
||||
typedef Vector<Function<bool(const NameRecord*)>> NameRecordMatchers;
|
||||
|
||||
class SFNTNameTable final
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a SFNTNameTable if the header data is valid. Note that the data is
|
||||
* NOT copied, so must exist for the lifetime of the table.
|
||||
*
|
||||
* @param aNameData the Name Table data.
|
||||
* @param aDataLength length
|
||||
* @return UniquePtr to a SFNTNameTable or nullptr if the header is invalid.
|
||||
*/
|
||||
static UniquePtr<SFNTNameTable> Create(const uint8_t *aNameData,
|
||||
uint32_t aDataLength);
|
||||
|
||||
/**
|
||||
* Gets the full name from the name table. If the full name string is not
|
||||
* present it will use the family space concatenated with the style.
|
||||
* This will only read names that are already UTF16.
|
||||
*
|
||||
* @param aU16FullName string to be populated with the full name.
|
||||
* @return true if the full name is successfully read.
|
||||
*/
|
||||
bool GetU16FullName(mozilla::u16string& aU16FullName);
|
||||
|
||||
private:
|
||||
|
||||
SFNTNameTable(const NameHeader *aNameHeader, const uint8_t *aNameData,
|
||||
uint32_t aDataLength);
|
||||
|
||||
bool ReadU16Name(const NameRecordMatchers& aMatchers, mozilla::u16string& aU16Name);
|
||||
|
||||
bool ReadU16NameFromRecord(const NameRecord *aNameRecord,
|
||||
mozilla::u16string& aU16Name);
|
||||
|
||||
const NameRecord *mFirstRecord;
|
||||
const NameRecord *mEndOfRecords;
|
||||
const uint8_t *mStringData;
|
||||
const uint32_t mStringDataLength;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_SFNTNameTable_h
|
||||
@@ -45,6 +45,33 @@ ScaledFontBase::ScaledFontBase(Float aSize)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
bool
|
||||
ScaledFontBase::PopulateCairoScaledFont()
|
||||
{
|
||||
cairo_font_face_t* cairoFontFace = GetCairoFontFace();
|
||||
if (!cairoFontFace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cairo_matrix_t sizeMatrix;
|
||||
cairo_matrix_t identityMatrix;
|
||||
|
||||
cairo_matrix_init_scale(&sizeMatrix, mSize, mSize);
|
||||
cairo_matrix_init_identity(&identityMatrix);
|
||||
|
||||
cairo_font_options_t *fontOptions = cairo_font_options_create();
|
||||
|
||||
mScaledFont = cairo_scaled_font_create(cairoFontFace, &sizeMatrix,
|
||||
&identityMatrix, fontOptions);
|
||||
|
||||
cairo_font_options_destroy(fontOptions);
|
||||
cairo_font_face_destroy(cairoFontFace);
|
||||
|
||||
return (cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkPath
|
||||
ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer)
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
virtual FontType GetType() const { return FontType::SKIA; }
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
bool PopulateCairoScaledFont();
|
||||
cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; }
|
||||
void SetCairoScaledFont(cairo_scaled_font_t* font);
|
||||
#endif
|
||||
@@ -56,6 +57,8 @@ protected:
|
||||
SkPath GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer);
|
||||
#endif
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
// Overridders should ensure the cairo_font_face_t has been addrefed.
|
||||
virtual cairo_font_face_t* GetCairoFontFace() { return nullptr; }
|
||||
cairo_scaled_font_t* mScaledFont;
|
||||
#endif
|
||||
Float mSize;
|
||||
|
||||
+38
-222
@@ -3,143 +3,26 @@
|
||||
* 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 "DrawTargetD2D.h"
|
||||
#include "ScaledFontDWrite.h"
|
||||
#include "PathD2D.h"
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#ifdef USE_SKIA
|
||||
#include "PathSkia.h"
|
||||
#include "skia/include/core/SkPaint.h"
|
||||
#include "skia/include/core/SkPath.h"
|
||||
#include "skia/include/ports/SkTypeface_win.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
#include "cairo-win32.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
struct ffReferenceKey
|
||||
{
|
||||
uint8_t *mData;
|
||||
uint32_t mSize;
|
||||
};
|
||||
|
||||
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
public:
|
||||
DWriteFontFileLoader()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileLoader)) {
|
||||
*ppObject = static_cast<IDWriteFontFileLoader*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IDWriteFontFileLoader methods
|
||||
/**
|
||||
* Important! Note the key here -has- to be a pointer to an
|
||||
* ffReferenceKey object.
|
||||
*/
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
CreateStreamFromKey(void const* fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
OUT IDWriteFontFileStream** fontFileStream);
|
||||
|
||||
/**
|
||||
* Gets the singleton loader instance. Note that when using this font
|
||||
* loader, the key must be a pointer to an FallibleTArray<uint8_t>. This
|
||||
* array will be empty when the function returns.
|
||||
*/
|
||||
static IDWriteFontFileLoader* Instance()
|
||||
{
|
||||
if (!mInstance) {
|
||||
mInstance = new DWriteFontFileLoader();
|
||||
DrawTargetD2D::GetDWriteFactory()->
|
||||
RegisterFontFileLoader(mInstance);
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
static IDWriteFontFileLoader* mInstance;
|
||||
};
|
||||
|
||||
class DWriteFontFileStream : public IDWriteFontFileStream
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used by the FontFileLoader to create a new font stream,
|
||||
* this font stream is created from data in memory. The memory
|
||||
* passed may be released after object creation, it will be
|
||||
* copied internally.
|
||||
*
|
||||
* @param aData Font data
|
||||
*/
|
||||
DWriteFontFileStream(uint8_t *aData, uint32_t aSize);
|
||||
~DWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
--mRefCnt;
|
||||
if (mRefCnt == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
// IDWriteFontFileStream methods
|
||||
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
OUT void** fragmentContext);
|
||||
|
||||
virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> mData;
|
||||
uint32_t mRefCnt;
|
||||
};
|
||||
|
||||
static BYTE
|
||||
GetSystemTextQuality()
|
||||
{
|
||||
@@ -213,99 +96,6 @@ DoGrayscale(IDWriteFontFace *aDWFace, Float ppem)
|
||||
return true;
|
||||
}
|
||||
|
||||
IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = nullptr;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
IDWriteFontFileStream **fontFileStream)
|
||||
{
|
||||
if (!fontFileReferenceKey || !fontFileStream) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
const ffReferenceKey *key = static_cast<const ffReferenceKey*>(fontFileReferenceKey);
|
||||
*fontFileStream =
|
||||
new DWriteFontFileStream(key->mData, key->mSize);
|
||||
|
||||
if (!*fontFileStream) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
(*fontFileStream)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWriteFontFileStream::DWriteFontFileStream(uint8_t *aData, uint32_t aSize)
|
||||
: mRefCnt(0)
|
||||
{
|
||||
mData.resize(aSize);
|
||||
memcpy(&mData.front(), aData, aSize);
|
||||
}
|
||||
|
||||
DWriteFontFileStream::~DWriteFontFileStream()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > mData.size()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// truncate the 64 bit fileOffset to size_t sized index into mData
|
||||
size_t index = static_cast<size_t>(fileOffset);
|
||||
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[index];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
}
|
||||
|
||||
ScaledFontDWrite::ScaledFontDWrite(uint8_t *aData, uint32_t aSize,
|
||||
uint32_t aIndex, Float aGlyphSize)
|
||||
: ScaledFontBase(aGlyphSize)
|
||||
{
|
||||
IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
|
||||
|
||||
ffReferenceKey key;
|
||||
key.mData = aData;
|
||||
key.mSize = aSize;
|
||||
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
if (FAILED(factory->CreateCustomFontFileReference(&key, sizeof(ffReferenceKey), DWriteFontFileLoader::Instance(), getter_AddRefs(fontFile)))) {
|
||||
gfxWarning() << "Failed to load font file from data!";
|
||||
return;
|
||||
}
|
||||
|
||||
IDWriteFontFile *ff = fontFile;
|
||||
if (FAILED(factory->CreateFontFace(DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ff, aIndex, DWRITE_FONT_SIMULATIONS_NONE, getter_AddRefs(mFontFace)))) {
|
||||
gfxWarning() << "Failed to create font face from font file data!";
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Path>
|
||||
ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
|
||||
{
|
||||
@@ -323,6 +113,20 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget
|
||||
return pathBuilder->Finish();
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkTypeface*
|
||||
ScaledFontDWrite::GetSkTypeface()
|
||||
{
|
||||
MOZ_ASSERT(mFont);
|
||||
if (!mTypeface) {
|
||||
IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
|
||||
mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
|
||||
}
|
||||
return mTypeface;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint)
|
||||
{
|
||||
@@ -431,5 +235,17 @@ ScaledFontDWrite::GetDefaultAAMode()
|
||||
return defaultMode;
|
||||
}
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
cairo_font_face_t*
|
||||
ScaledFontDWrite::GetCairoFontFace()
|
||||
{
|
||||
if (!mFontFace) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cairo_dwrite_font_face_create_for_dwrite_fontface(nullptr, mFontFace);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,18 @@ public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite)
|
||||
ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize)
|
||||
: ScaledFontBase(aSize)
|
||||
, mFont(nullptr)
|
||||
, mFontFamily(nullptr)
|
||||
, mFontFace(aFont)
|
||||
{}
|
||||
ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize);
|
||||
|
||||
ScaledFontDWrite(IDWriteFont* aFont, IDWriteFontFamily* aFontFamily,
|
||||
IDWriteFontFace *aFontFace, Float aSize)
|
||||
: ScaledFontBase(aSize)
|
||||
, mFont(aFont)
|
||||
, mFontFamily(aFontFamily)
|
||||
, mFontFace(aFontFace)
|
||||
{}
|
||||
|
||||
virtual FontType GetType() const { return FontType::DWRITE; }
|
||||
|
||||
@@ -36,14 +45,17 @@ public:
|
||||
virtual AntialiasMode GetDefaultAAMode();
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface()
|
||||
{
|
||||
MOZ_ASSERT(false, "Skia and DirectWrite do not mix");
|
||||
return nullptr;
|
||||
}
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
#endif
|
||||
|
||||
RefPtr<IDWriteFont> mFont;
|
||||
RefPtr<IDWriteFontFamily> mFontFamily;
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
protected:
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
cairo_font_face_t* GetCairoFontFace() override;
|
||||
#endif
|
||||
};
|
||||
|
||||
class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
|
||||
|
||||
@@ -4,21 +4,77 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ScaledFontWin.h"
|
||||
#include "ScaledFontBase.h"
|
||||
|
||||
#include "AutoHelpersWin.h"
|
||||
#include "Logging.h"
|
||||
#include "SFNTData.h"
|
||||
|
||||
#ifdef USE_SKIA
|
||||
#include "skia/include/ports/SkTypeface_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
#include "cairo-win32.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
ScaledFontWin::ScaledFontWin(LOGFONT* aFont, Float aSize)
|
||||
ScaledFontWin::ScaledFontWin(LOGFONTW* aFont, Float aSize)
|
||||
: ScaledFontBase(aSize)
|
||||
, mLogFont(*aFont)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
|
||||
{
|
||||
AutoDC dc;
|
||||
AutoSelectFont font(dc.GetDC(), &mLogFont);
|
||||
|
||||
// Check for a font collection first.
|
||||
uint32_t table = 0x66637474; // 'ttcf'
|
||||
uint32_t tableSize = ::GetFontData(dc.GetDC(), table, 0, nullptr, 0);
|
||||
if (tableSize == GDI_ERROR) {
|
||||
// Try as if just a single font.
|
||||
table = 0;
|
||||
tableSize = ::GetFontData(dc.GetDC(), table, 0, nullptr, 0);
|
||||
if (tableSize == GDI_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UniquePtr<uint8_t[]> fontData(new uint8_t[tableSize]);
|
||||
|
||||
uint32_t sizeGot =
|
||||
::GetFontData(dc.GetDC(), table, 0, fontData.get(), tableSize);
|
||||
if (sizeGot != tableSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it's a font collection then attempt to get the index.
|
||||
uint32_t index = 0;
|
||||
if (table != 0) {
|
||||
UniquePtr<SFNTData> sfntData = SFNTData::Create(fontData.get(),
|
||||
tableSize);
|
||||
if (!sfntData) {
|
||||
gfxWarning() << "Failed to create SFNTData for GetFontFileData.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We cast here because for VS2015 char16_t != wchar_t, even though they are
|
||||
// both 16 bit.
|
||||
if (!sfntData->GetIndexForU16Name(
|
||||
reinterpret_cast<char16_t*>(mLogFont.lfFaceName), &index)) {
|
||||
gfxWarning() << "Failed to get index for face name.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aDataCallback(fontData.get(), tableSize, index, mSize, aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkTypeface* ScaledFontWin::GetSkTypeface()
|
||||
{
|
||||
@@ -29,6 +85,16 @@ SkTypeface* ScaledFontWin::GetSkTypeface()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
cairo_font_face_t*
|
||||
ScaledFontWin::GetCairoFontFace()
|
||||
{
|
||||
if (mLogFont.lfFaceName[0] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return cairo_win32_font_face_create_for_logfontw(&mLogFont);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -16,17 +16,26 @@ class ScaledFontWin : public ScaledFontBase
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin)
|
||||
ScaledFontWin(LOGFONT* aFont, Float aSize);
|
||||
ScaledFontWin(LOGFONTW* aFont, Float aSize);
|
||||
|
||||
virtual FontType GetType() const { return FontType::GDI; }
|
||||
|
||||
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
cairo_font_face_t* GetCairoFontFace() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef USE_SKIA
|
||||
friend class DrawTargetSkia;
|
||||
#endif
|
||||
LOGFONT mLogFont;
|
||||
LOGFONTW mLogFont;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+9
-7
@@ -22,6 +22,7 @@ EXPORTS.mozilla.gfx += [
|
||||
'Coord.h',
|
||||
'CriticalSection.h',
|
||||
'DataSurfaceHelpers.h',
|
||||
'DrawEventRecorder.h',
|
||||
'DrawTargetTiled.h',
|
||||
'Filters.h',
|
||||
'Helpers.h',
|
||||
@@ -37,7 +38,10 @@ EXPORTS.mozilla.gfx += [
|
||||
'PathHelpers.h',
|
||||
'PatternHelpers.h',
|
||||
'Point.h',
|
||||
'Preferences.h',
|
||||
'Quaternion.h',
|
||||
'RecordedEvent.h',
|
||||
'RecordingTypes.h',
|
||||
'Rect.h',
|
||||
'Scale.h',
|
||||
'ScaleFactor.h',
|
||||
@@ -67,6 +71,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'ExtendInputEffectD2D1.cpp',
|
||||
'FilterNodeD2D1.cpp',
|
||||
'JobScheduler_win32.cpp',
|
||||
'NativeFontResourceDWrite.cpp',
|
||||
'NativeFontResourceGDI.cpp',
|
||||
'PathD2D.cpp',
|
||||
'RadialGradientEffectD2D1.cpp',
|
||||
'ScaledFontDWrite.cpp',
|
||||
@@ -154,11 +160,14 @@ UNIFIED_SOURCES += [
|
||||
'PathCairo.cpp',
|
||||
'PathHelpers.cpp',
|
||||
'PathRecording.cpp',
|
||||
'Preferences.cpp',
|
||||
'Quaternion.cpp',
|
||||
'RecordedEvent.cpp',
|
||||
'Scale.cpp',
|
||||
'ScaledFontBase.cpp',
|
||||
'ScaledFontCairo.cpp',
|
||||
'SFNTData.cpp',
|
||||
'SFNTNameTable.cpp',
|
||||
'SourceSurfaceCairo.cpp',
|
||||
'SourceSurfaceRawData.cpp',
|
||||
]
|
||||
@@ -195,10 +204,3 @@ if CONFIG['MOZ_X11']:
|
||||
CXXFLAGS += CONFIG['XCFLAGS']
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# Due to bug 796023, we can't have -DUNICODE and -D_UNICODE; defining those
|
||||
# macros changes the type of LOGFONT to LOGFONTW instead of LOGFONTA. This
|
||||
# changes the symbol names of exported C++ functions that use LOGFONT.
|
||||
del DEFINES['UNICODE']
|
||||
del DEFINES['_UNICODE']
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_u16string_h
|
||||
#define mozilla_gfx_u16string_h
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mozilla/Char16.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef std::u16string u16string;
|
||||
#else
|
||||
typedef std::basic_string<char16_t> u16string;
|
||||
#endif
|
||||
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_u16string_h
|
||||
@@ -170,8 +170,5 @@ CFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
del DEFINES['UNICODE']
|
||||
|
||||
if CONFIG['CLANG_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
||||
@@ -73,6 +73,10 @@ if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['SKIA_DLL'] = 1
|
||||
DEFINES['GR_DLL'] = 1
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
|
||||
# We should autogenerate these SSE related flags.
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
@@ -83,6 +87,7 @@ if CONFIG['_MSC_VER']:
|
||||
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
|
||||
SOURCES['skia/src/opts/SkOpts_sse2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
|
||||
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
|
||||
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
|
||||
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['/arch:AVX -DSK_CPU_SSE_LEVEL=51']
|
||||
@@ -92,6 +97,7 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC']:
|
||||
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
|
||||
SOURCES['skia/src/opts/SkOpts_sse2.cpp'].flags += CONFIG['SSE2_FLAGS']
|
||||
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
|
||||
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
|
||||
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
|
||||
@@ -222,6 +228,7 @@ def generate_separated_sources(platform_sources):
|
||||
'intel': {
|
||||
# There is currently no x86-specific opt for SkTextureCompression
|
||||
'skia/src/opts/opts_check_x86.cpp',
|
||||
'skia/src/opts/SkOpts_sse2.cpp',
|
||||
'skia/src/opts/SkOpts_ssse3.cpp',
|
||||
'skia/src/opts/SkOpts_sse41.cpp',
|
||||
'skia/src/opts/SkOpts_avx.cpp',
|
||||
|
||||
@@ -603,6 +603,7 @@ if CONFIG['INTEL_ARCHITECTURE']:
|
||||
'skia/src/opts/SkBlitRow_opts_SSE2.cpp',
|
||||
'skia/src/opts/SkBlitRow_opts_SSE4.cpp',
|
||||
'skia/src/opts/SkOpts_avx.cpp',
|
||||
'skia/src/opts/SkOpts_sse2.cpp',
|
||||
'skia/src/opts/SkOpts_sse41.cpp',
|
||||
'skia/src/opts/SkOpts_ssse3.cpp',
|
||||
]
|
||||
@@ -690,6 +691,10 @@ if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['SKIA_DLL'] = 1
|
||||
DEFINES['GR_DLL'] = 1
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
|
||||
# We should autogenerate these SSE related flags.
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
@@ -700,6 +705,7 @@ if CONFIG['_MSC_VER']:
|
||||
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
|
||||
SOURCES['skia/src/opts/SkOpts_sse2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
|
||||
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
|
||||
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
|
||||
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['/arch:AVX -DSK_CPU_SSE_LEVEL=51']
|
||||
@@ -709,6 +715,7 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC']:
|
||||
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
|
||||
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
|
||||
SOURCES['skia/src/opts/SkOpts_sse2.cpp'].flags += CONFIG['SSE2_FLAGS']
|
||||
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
|
||||
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
|
||||
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define SkTypeface_win_DEFINED
|
||||
|
||||
#include "SkTypeface.h"
|
||||
#include <dwrite.h>
|
||||
|
||||
#ifdef SK_BUILD_FOR_WIN
|
||||
|
||||
@@ -41,6 +42,16 @@ class SkFontMgr;
|
||||
class SkRemotableFontMgr;
|
||||
struct IDWriteFactory;
|
||||
|
||||
/**
|
||||
* Like the other Typeface create methods, this returns a new reference to the
|
||||
* corresponding typeface for the specified dwrite font. The caller is responsible
|
||||
* for calling unref() when it is finished.
|
||||
*/
|
||||
SK_API SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory,
|
||||
IDWriteFontFace* aFontFace,
|
||||
IDWriteFont* aFont,
|
||||
IDWriteFontFamily* aFontFamily);
|
||||
|
||||
SK_API SkFontMgr* SkFontMgr_New_GDI();
|
||||
SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory = NULL);
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ namespace SkOpts {
|
||||
decltype(matrix_affine) matrix_affine = sk_default::matrix_affine;
|
||||
|
||||
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
|
||||
void Init_sse2();
|
||||
void Init_ssse3();
|
||||
void Init_sse41();
|
||||
void Init_sse42() {}
|
||||
@@ -97,6 +98,7 @@ namespace SkOpts {
|
||||
#if defined(SK_CPU_X86) && !defined(SK_BUILD_FOR_IOS)
|
||||
uint32_t abcd[] = {0,0,0,0};
|
||||
cpuid(abcd);
|
||||
if (abcd[3] & (1<<26)) { Init_sse2(); }
|
||||
if (abcd[2] & (1<< 9)) { Init_ssse3(); }
|
||||
if (abcd[2] & (1<<19)) { Init_sse41(); }
|
||||
if (abcd[2] & (1<<20)) { Init_sse42(); }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
class AutoLibraryUnload {
|
||||
public:
|
||||
AutoLibraryUnload(const char* moduleName) {
|
||||
fModule = LoadLibrary(moduleName);
|
||||
fModule = LoadLibraryA(moduleName);
|
||||
}
|
||||
~AutoLibraryUnload() {
|
||||
if (fModule) {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkOpts.h"
|
||||
#define SK_OPTS_NS sk_sse2
|
||||
#include "SkBlitMask_opts.h"
|
||||
#include "SkBlitRow_opts.h"
|
||||
#include "SkBlurImageFilter_opts.h"
|
||||
#include "SkColorCubeFilter_opts.h"
|
||||
#include "SkMatrix_opts.h"
|
||||
#include "SkMorphologyImageFilter_opts.h"
|
||||
#include "SkUtils_opts.h"
|
||||
#include "SkXfermode_opts.h"
|
||||
|
||||
namespace SkOpts {
|
||||
void Init_sse2() {
|
||||
memset16 = sk_sse2::memset16;
|
||||
memset32 = sk_sse2::memset32;
|
||||
create_xfermode = sk_sse2::create_xfermode;
|
||||
color_cube_filter_span = sk_sse2::color_cube_filter_span;
|
||||
|
||||
box_blur_xx = sk_sse2::box_blur_xx;
|
||||
box_blur_xy = sk_sse2::box_blur_xy;
|
||||
box_blur_yx = sk_sse2::box_blur_yx;
|
||||
|
||||
dilate_x = sk_sse2::dilate_x;
|
||||
dilate_y = sk_sse2::dilate_y;
|
||||
erode_x = sk_sse2::erode_x;
|
||||
erode_y = sk_sse2::erode_y;
|
||||
|
||||
blit_mask_d32_a8 = sk_sse2::blit_mask_d32_a8;
|
||||
|
||||
blit_row_color32 = sk_sse2::blit_row_color32;
|
||||
|
||||
matrix_translate = sk_sse2::matrix_translate;
|
||||
matrix_scale_translate = sk_sse2::matrix_scale_translate;
|
||||
matrix_affine = sk_sse2::matrix_affine;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace {
|
||||
|
||||
// Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit fixed point.
|
||||
#define XFERMODE(Name) static Sk4px SK_VECTORCALL Name(Sk4px s, Sk4px d)
|
||||
#define XFERMODE(Name) inline Sk4px Name(const Sk4px& d, const Sk4px& s)
|
||||
|
||||
XFERMODE(Clear) { return Sk4px::DupPMColor(0); }
|
||||
XFERMODE(Src) { return s; }
|
||||
@@ -23,13 +23,13 @@ XFERMODE(Dst) { return d; }
|
||||
XFERMODE(SrcIn) { return s.approxMulDiv255(d.alphas() ); }
|
||||
XFERMODE(SrcOut) { return s.approxMulDiv255(d.alphas().inv()); }
|
||||
XFERMODE(SrcOver) { return s + d.approxMulDiv255(s.alphas().inv()); }
|
||||
XFERMODE(DstIn) { return SrcIn (d,s); }
|
||||
XFERMODE(DstOut) { return SrcOut (d,s); }
|
||||
XFERMODE(DstOver) { return SrcOver(d,s); }
|
||||
XFERMODE(DstIn) { return SrcIn (s,d); }
|
||||
XFERMODE(DstOut) { return SrcOut (s,d); }
|
||||
XFERMODE(DstOver) { return SrcOver(s,d); }
|
||||
|
||||
// [ S * Da + (1 - Sa) * D]
|
||||
XFERMODE(SrcATop) { return (s * d.alphas() + d * s.alphas().inv()).div255(); }
|
||||
XFERMODE(DstATop) { return SrcATop(d,s); }
|
||||
XFERMODE(DstATop) { return SrcATop(s,d); }
|
||||
//[ S * (1 - Da) + (1 - Sa) * D ]
|
||||
XFERMODE(Xor) { return (s * d.alphas().inv() + d * s.alphas().inv()).div255(); }
|
||||
// [S + D ]
|
||||
@@ -79,7 +79,7 @@ XFERMODE(HardLight) {
|
||||
auto colors = (both + isLite.thenElse(lite, dark)).div255();
|
||||
return alphas.zeroColors() + colors.zeroAlphas();
|
||||
}
|
||||
XFERMODE(Overlay) { return HardLight(d,s); }
|
||||
XFERMODE(Overlay) { return HardLight(s,d); }
|
||||
|
||||
XFERMODE(Darken) {
|
||||
auto sa = s.alphas(),
|
||||
@@ -110,7 +110,7 @@ XFERMODE(Lighten) {
|
||||
#undef XFERMODE
|
||||
|
||||
// Some xfermodes use math like divide or sqrt that's best done in floats 1 pixel at a time.
|
||||
#define XFERMODE(Name) static Sk4f SK_VECTORCALL Name(Sk4f d, Sk4f s)
|
||||
#define XFERMODE(Name) inline Sk4f Name(const Sk4f& d, const Sk4f& s)
|
||||
|
||||
static inline Sk4f a_rgb(const Sk4f& a, const Sk4f& rgb) {
|
||||
static_assert(SK_A32_SHIFT == 24, "");
|
||||
@@ -181,15 +181,15 @@ XFERMODE(SoftLight) {
|
||||
|
||||
// A reasonable fallback mode for doing AA is to simply apply the transfermode first,
|
||||
// then linearly interpolate the AA.
|
||||
template <Sk4px (SK_VECTORCALL *Mode)(Sk4px, Sk4px)>
|
||||
static Sk4px SK_VECTORCALL xfer_aa(Sk4px s, Sk4px d, Sk4px aa) {
|
||||
Sk4px bw = Mode(s, d);
|
||||
template <Sk4px (*Mode)(const Sk4px&, const Sk4px&)>
|
||||
inline Sk4px xfer_aa(const Sk4px& d, const Sk4px& s, const Sk4px& aa) {
|
||||
Sk4px bw = Mode(d, s);
|
||||
return (bw * aa + d * aa.inv()).div255();
|
||||
}
|
||||
|
||||
// For some transfermodes we specialize AA, either for correctness or performance.
|
||||
#define XFERMODE_AA(Name) \
|
||||
template <> Sk4px SK_VECTORCALL xfer_aa<Name>(Sk4px s, Sk4px d, Sk4px aa)
|
||||
template <> inline Sk4px xfer_aa<Name>(const Sk4px& d, const Sk4px& s, const Sk4px& aa)
|
||||
|
||||
// Plus' clamp needs to happen after AA. skia:3852
|
||||
XFERMODE_AA(Plus) { // [ clamp( (1-AA)D + (AA)(S+D) ) == clamp(D + AA*S) ]
|
||||
@@ -198,54 +198,38 @@ XFERMODE_AA(Plus) { // [ clamp( (1-AA)D + (AA)(S+D) ) == clamp(D + AA*S) ]
|
||||
|
||||
#undef XFERMODE_AA
|
||||
|
||||
template <Sk4px (*Proc4)(const Sk4px&, const Sk4px&),
|
||||
Sk4px (*AAProc4)(const Sk4px&, const Sk4px&, const Sk4px&)>
|
||||
class Sk4pxXfermode : public SkProcCoeffXfermode {
|
||||
public:
|
||||
typedef Sk4px (SK_VECTORCALL *Proc4)(Sk4px, Sk4px);
|
||||
typedef Sk4px (SK_VECTORCALL *AAProc4)(Sk4px, Sk4px, Sk4px);
|
||||
|
||||
Sk4pxXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, Proc4 proc4, AAProc4 aaproc4)
|
||||
: INHERITED(rec, mode)
|
||||
, fProc4(proc4)
|
||||
, fAAProc4(aaproc4) {}
|
||||
Sk4pxXfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
|
||||
: INHERITED(rec, mode) {}
|
||||
|
||||
void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
|
||||
if (nullptr == aa) {
|
||||
Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
|
||||
return fProc4(src4, dst4);
|
||||
});
|
||||
Sk4px::MapDstSrc(n, dst, src, Proc4);
|
||||
} else {
|
||||
Sk4px::MapDstSrcAlpha(n, dst, src, aa,
|
||||
[&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha) {
|
||||
return fAAProc4(src4, dst4, alpha);
|
||||
});
|
||||
Sk4px::MapDstSrcAlpha(n, dst, src, aa, AAProc4);
|
||||
}
|
||||
}
|
||||
|
||||
void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
|
||||
if (nullptr == aa) {
|
||||
Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
|
||||
return fProc4(src4, dst4);
|
||||
});
|
||||
Sk4px::MapDstSrc(n, dst, src, Proc4);
|
||||
} else {
|
||||
Sk4px::MapDstSrcAlpha(n, dst, src, aa,
|
||||
[&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha) {
|
||||
return fAAProc4(src4, dst4, alpha);
|
||||
});
|
||||
Sk4px::MapDstSrcAlpha(n, dst, src, aa, AAProc4);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Proc4 fProc4;
|
||||
AAProc4 fAAProc4;
|
||||
typedef SkProcCoeffXfermode INHERITED;
|
||||
};
|
||||
|
||||
template <Sk4f (*ProcF)(const Sk4f&, const Sk4f&)>
|
||||
class Sk4fXfermode : public SkProcCoeffXfermode {
|
||||
public:
|
||||
typedef Sk4f (SK_VECTORCALL *ProcF)(Sk4f, Sk4f);
|
||||
Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, ProcF procf)
|
||||
: INHERITED(rec, mode)
|
||||
, fProcF(procf) {}
|
||||
Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
|
||||
: INHERITED(rec, mode) {}
|
||||
|
||||
void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -273,20 +257,19 @@ private:
|
||||
return c;
|
||||
}
|
||||
inline SkPMColor xfer32(SkPMColor dst, SkPMColor src) const {
|
||||
return Round(fProcF(Load(dst), Load(src)));
|
||||
return Round(ProcF(Load(dst), Load(src)));
|
||||
}
|
||||
|
||||
inline SkPMColor xfer32(SkPMColor dst, SkPMColor src, SkAlpha aa) const {
|
||||
Sk4f s(Load(src)),
|
||||
d(Load(dst)),
|
||||
b(fProcF(d,s));
|
||||
b(ProcF(d,s));
|
||||
// We do aa in full float precision before going back down to bytes, because we can!
|
||||
Sk4f a = Sk4f(aa) * Sk4f(1.0f/255);
|
||||
b = b*a + d*(Sk4f(1)-a);
|
||||
return Round(b);
|
||||
}
|
||||
|
||||
ProcF fProcF;
|
||||
typedef SkProcCoeffXfermode INHERITED;
|
||||
};
|
||||
|
||||
@@ -297,7 +280,7 @@ namespace SK_OPTS_NS {
|
||||
static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode) {
|
||||
switch (mode) {
|
||||
#define CASE(Mode) \
|
||||
case SkXfermode::k##Mode##_Mode: return new Sk4pxXfermode(rec, mode, &Mode, &xfer_aa<Mode>)
|
||||
case SkXfermode::k##Mode##_Mode: return new Sk4pxXfermode<Mode, xfer_aa<Mode> >(rec, mode)
|
||||
CASE(Clear);
|
||||
CASE(Src);
|
||||
CASE(Dst);
|
||||
@@ -323,7 +306,7 @@ static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
|
||||
#undef CASE
|
||||
|
||||
#define CASE(Mode) \
|
||||
case SkXfermode::k##Mode##_Mode: return new Sk4fXfermode(rec, mode, &Mode)
|
||||
case SkXfermode::k##Mode##_Mode: return new Sk4fXfermode<Mode>(rec, mode)
|
||||
CASE(ColorDodge);
|
||||
CASE(ColorBurn);
|
||||
CASE(SoftLight);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "SkString.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkTypeface_win.h"
|
||||
#include "SkTypeface_win_dw.h"
|
||||
#include "SkTypefaceCache.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
@@ -330,6 +331,18 @@ SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
|
||||
return face;
|
||||
}
|
||||
|
||||
/***
|
||||
* This guy is public.
|
||||
*/
|
||||
|
||||
SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory,
|
||||
IDWriteFontFace* aFontFace,
|
||||
IDWriteFont* aFont,
|
||||
IDWriteFontFamily* aFontFamily)
|
||||
{
|
||||
return DWriteFontTypeface::Create(aFactory, aFontFace, aFont, aFontFamily);
|
||||
}
|
||||
|
||||
/**
|
||||
* The created SkTypeface takes ownership of fontMemResource.
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
void* DynamicLoadLibrary(const char* libraryName) {
|
||||
return LoadLibrary(libraryName);
|
||||
return LoadLibraryA(libraryName);
|
||||
}
|
||||
|
||||
void* GetProcedureAddress(void* library, const char* functionName) {
|
||||
|
||||
+17
-62
@@ -314,30 +314,10 @@ nsDeviceContext::SetDPI()
|
||||
{
|
||||
float dpi = -1.0f;
|
||||
|
||||
// PostScript, PDF and Mac (when printing) all use 72 dpi
|
||||
// Use a printing DC to determine the other dpi values
|
||||
if (mPrintingSurface) {
|
||||
switch (mPrintingSurface->GetType()) {
|
||||
case gfxSurfaceType::PDF:
|
||||
case gfxSurfaceType::PS:
|
||||
case gfxSurfaceType::Quartz:
|
||||
dpi = 72.0f;
|
||||
break;
|
||||
#ifdef XP_WIN
|
||||
case gfxSurfaceType::Win32:
|
||||
case gfxSurfaceType::Win32Printing: {
|
||||
HDC dc = reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
|
||||
int32_t OSVal = GetDeviceCaps(dc, LOGPIXELSY);
|
||||
dpi = 144.0f;
|
||||
mPrintingScale = float(OSVal) / dpi;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
NS_NOTREACHED("Unexpected printing surface type");
|
||||
break;
|
||||
}
|
||||
|
||||
// Use the printing DC to determine DPI values, if we have one.
|
||||
if (mDeviceContextSpec) {
|
||||
dpi = mDeviceContextSpec->GetDPI();
|
||||
mPrintingScale = mDeviceContextSpec->GetPrintingScale();
|
||||
mAppUnitsPerDevPixelAtUnitFullZoom =
|
||||
NS_lround((AppUnitsPerCSSPixel() * 96) / dpi);
|
||||
} else {
|
||||
@@ -420,6 +400,12 @@ nsDeviceContext::CreateRenderingContext()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DrawEventRecorder> recorder;
|
||||
nsresult rv = mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder));
|
||||
if (NS_SUCCEEDED(rv) && recorder) {
|
||||
dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dt);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
|
||||
#endif
|
||||
@@ -526,18 +512,16 @@ nsDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice)
|
||||
|
||||
nsresult
|
||||
nsDeviceContext::BeginDocument(const nsAString& aTitle,
|
||||
char16_t* aPrintToFileName,
|
||||
const nsAString& aPrintToFileName,
|
||||
int32_t aStartPage,
|
||||
int32_t aEndPage)
|
||||
{
|
||||
static const char16_t kEmpty[] = { '\0' };
|
||||
nsresult rv;
|
||||
nsresult rv = mPrintingSurface->BeginPrinting(aTitle, aPrintToFileName);
|
||||
|
||||
rv = mPrintingSurface->BeginPrinting(aTitle,
|
||||
nsDependentString(aPrintToFileName ? aPrintToFileName : kEmpty));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mDeviceContextSpec)
|
||||
rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName, aStartPage, aEndPage);
|
||||
if (NS_SUCCEEDED(rv) && mDeviceContextSpec) {
|
||||
rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName,
|
||||
aStartPage, aEndPage);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -698,34 +682,7 @@ nsDeviceContext::CalcPrintingSize()
|
||||
|
||||
gfxSize size(0, 0);
|
||||
switch (mPrintingSurface->GetType()) {
|
||||
case gfxSurfaceType::Image:
|
||||
inPoints = false;
|
||||
size = reinterpret_cast<gfxImageSurface*>(mPrintingSurface.get())->GetSize();
|
||||
break;
|
||||
|
||||
#if defined(MOZ_PDF_PRINTING)
|
||||
case gfxSurfaceType::PDF:
|
||||
inPoints = true;
|
||||
size = reinterpret_cast<gfxPDFSurface*>(mPrintingSurface.get())->GetSize();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
case gfxSurfaceType::PS:
|
||||
inPoints = true;
|
||||
size = reinterpret_cast<gfxPSSurface*>(mPrintingSurface.get())->GetSize();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case gfxSurfaceType::Quartz:
|
||||
inPoints = true; // this is really only true when we're printing
|
||||
size = reinterpret_cast<gfxQuartzSurface*>(mPrintingSurface.get())->GetSize();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
case gfxSurfaceType::Win32:
|
||||
case gfxSurfaceType::Win32Printing:
|
||||
{
|
||||
inPoints = false;
|
||||
@@ -740,10 +697,8 @@ nsDeviceContext::CalcPrintingSize()
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
gfxCriticalError() << "Printing to unknown surface type " << (int)mPrintingSurface->GetType();
|
||||
NS_ERROR("trying to print to unknown surface type");
|
||||
size = mPrintingSurface->GetSize();
|
||||
}
|
||||
|
||||
if (inPoints) {
|
||||
|
||||
@@ -182,8 +182,8 @@ public:
|
||||
* EndDocument() or AbortDocument().
|
||||
*
|
||||
* @param aTitle - title of Document
|
||||
* @param aPrintToFileName - name of file to print to, if nullptr
|
||||
* then don't print to file
|
||||
* @param aPrintToFileName - name of file to print to, if empty then don't
|
||||
* print to file
|
||||
* @param aStartPage - starting page number (must be greater than zero)
|
||||
* @param aEndPage - ending page number (must be less than or
|
||||
* equal to number of pages)
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
* @return error status
|
||||
*/
|
||||
nsresult BeginDocument(const nsAString& aTitle,
|
||||
char16_t* aPrintToFileName,
|
||||
const nsAString& aPrintToFileName,
|
||||
int32_t aStartPage,
|
||||
int32_t aEndPage);
|
||||
|
||||
|
||||
+28
-18
@@ -68,7 +68,6 @@ PatternFromState::operator mozilla::gfx::Pattern&()
|
||||
gfxContext::gfxContext(DrawTarget *aTarget, const Point& aDeviceOffset)
|
||||
: mPathIsRect(false)
|
||||
, mTransformChanged(false)
|
||||
, mRefCairo(nullptr)
|
||||
, mDT(aTarget)
|
||||
, mOriginalDT(aTarget)
|
||||
{
|
||||
@@ -98,9 +97,6 @@ gfxContext::ContextForDrawTarget(DrawTarget* aTarget)
|
||||
|
||||
gfxContext::~gfxContext()
|
||||
{
|
||||
if (mRefCairo) {
|
||||
cairo_destroy(mRefCairo);
|
||||
}
|
||||
for (int i = mStateStack.Length() - 1; i >= 0; i--) {
|
||||
for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
|
||||
mDT->PopClip();
|
||||
@@ -136,25 +132,38 @@ gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cairo_t *
|
||||
gfxContext::GetCairo()
|
||||
static void
|
||||
DestroyRefCairo(void* aData)
|
||||
{
|
||||
if (mDT->GetBackendType() == BackendType::CAIRO) {
|
||||
cairo_t *ctx =
|
||||
(cairo_t*)mDT->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT);
|
||||
if (ctx) {
|
||||
return ctx;
|
||||
cairo_t* refCairo = static_cast<cairo_t*>(aData);
|
||||
MOZ_ASSERT(refCairo);
|
||||
cairo_destroy(refCairo);
|
||||
}
|
||||
|
||||
/* static */ cairo_t *
|
||||
gfxContext::RefCairo(DrawTarget* aDT)
|
||||
{
|
||||
// DrawTargets that don't use a Cairo backend can be given a 1x1 "reference"
|
||||
// |cairo_t*|, stored in the DrawTarget's user data, for doing font-related
|
||||
// operations.
|
||||
static UserDataKey sRefCairo;
|
||||
|
||||
cairo_t* refCairo = nullptr;
|
||||
if (aDT->GetBackendType() == BackendType::CAIRO) {
|
||||
refCairo = static_cast<cairo_t*>
|
||||
(aDT->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
|
||||
if (refCairo) {
|
||||
return refCairo;
|
||||
}
|
||||
}
|
||||
|
||||
if (mRefCairo) {
|
||||
// Set transform!
|
||||
return mRefCairo;
|
||||
refCairo = static_cast<cairo_t*>(aDT->GetUserData(&sRefCairo));
|
||||
if (!refCairo) {
|
||||
refCairo = cairo_create(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->CairoSurface());
|
||||
aDT->AddUserData(&sRefCairo, refCairo, DestroyRefCairo);
|
||||
}
|
||||
|
||||
mRefCairo = cairo_create(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->CairoSurface());
|
||||
|
||||
return mRefCairo;
|
||||
return refCairo;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -212,6 +221,7 @@ already_AddRefed<Path> gfxContext::GetPath()
|
||||
void gfxContext::SetPath(Path* path)
|
||||
{
|
||||
MOZ_ASSERT(path->GetBackendType() == mDT->GetBackendType() ||
|
||||
path->GetBackendType() == BackendType::RECORDING ||
|
||||
(mDT->GetBackendType() == BackendType::DIRECT2D1_1 && path->GetBackendType() == BackendType::DIRECT2D));
|
||||
mPath = path;
|
||||
mPathBuilder = nullptr;
|
||||
@@ -1373,7 +1383,7 @@ gfxContext::GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY)
|
||||
// Print backends set CAIRO_HINT_METRICS_OFF.
|
||||
*aRoundY = true;
|
||||
|
||||
cairo_t *cr = GetCairo();
|
||||
cairo_t *cr = gfxContext::RefCairo(GetDrawTarget());
|
||||
cairo_scaled_font_t *scaled_font = cairo_get_scaled_font(cr);
|
||||
|
||||
// bug 1198921 - this sometimes fails under Windows for whatver reason
|
||||
|
||||
@@ -85,10 +85,10 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the raw cairo_t object.
|
||||
* XXX this should go away at some point.
|
||||
* Return the reference cairo_t object from aDT.
|
||||
* XXX this should be moved into gfxFont at some point.
|
||||
*/
|
||||
cairo_t *GetCairo();
|
||||
static cairo_t* RefCairo(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; }
|
||||
|
||||
|
||||
+148
-42
@@ -5,8 +5,128 @@
|
||||
|
||||
#include "gfxDWriteCommon.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
static mozilla::Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
|
||||
IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr;
|
||||
|
||||
class gfxDWriteFontFileStream final : public IDWriteFontFileStream
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used by the FontFileLoader to create a new font stream,
|
||||
* this font stream is created from data in memory. The memory
|
||||
* passed may be released after object creation, it will be
|
||||
* copied internally.
|
||||
*
|
||||
* @param aData Font data
|
||||
*/
|
||||
gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData,
|
||||
uint64_t aFontFileKey);
|
||||
~gfxDWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
if (mRefCnt == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
// IDWriteFontFileStream methods
|
||||
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
OUT void** fragmentContext);
|
||||
|
||||
virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
|
||||
|
||||
private:
|
||||
FallibleTArray<uint8_t> mData;
|
||||
nsAutoRefCnt mRefCnt;
|
||||
uint64_t mFontFileKey;
|
||||
};
|
||||
|
||||
gfxDWriteFontFileStream::gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData,
|
||||
uint64_t aFontFileKey)
|
||||
: mFontFileKey(aFontFileKey)
|
||||
{
|
||||
mData.SwapElements(*aData);
|
||||
}
|
||||
|
||||
gfxDWriteFontFileStream::~gfxDWriteFontFileStream()
|
||||
{
|
||||
sFontFileStreams.erase(mFontFileKey);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.Length();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[fileOffset];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
@@ -16,56 +136,42 @@ gfxDWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
*fontFileStream =
|
||||
new gfxDWriteFontFileStream(
|
||||
static_cast<const ffReferenceKey*>(fontFileReferenceKey)->mArray);
|
||||
|
||||
if (!*fontFileStream) {
|
||||
return E_OUTOFMEMORY;
|
||||
uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
|
||||
auto found = sFontFileStreams.find(fontFileKey);
|
||||
if (found == sFontFileStreams.end()) {
|
||||
*fontFileStream = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
(*fontFileStream)->AddRef();
|
||||
|
||||
found->second->AddRef();
|
||||
*fontFileStream = found->second;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
gfxDWriteFontFileStream::gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData)
|
||||
/* static */
|
||||
HRESULT
|
||||
gfxDWriteFontFileLoader::CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData,
|
||||
IDWriteFontFile** aFontFile,
|
||||
IDWriteFontFileStream** aFontFileStream)
|
||||
{
|
||||
mData.SwapElements(*aData);
|
||||
}
|
||||
MOZ_ASSERT(aFontFile);
|
||||
MOZ_ASSERT(aFontFileStream);
|
||||
|
||||
gfxDWriteFontFileStream::~gfxDWriteFontFileStream()
|
||||
{
|
||||
}
|
||||
IDWriteFactory *factory = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.Length();
|
||||
return S_OK;
|
||||
}
|
||||
uint64_t fontFileKey = sNextFontFileKey++;
|
||||
RefPtr<IDWriteFontFileStream> ffsRef = new gfxDWriteFontFileStream(&aFontData, fontFileKey);
|
||||
sFontFileStreams[fontFileKey] = ffsRef;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
HRESULT hr = factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to load font file from data!");
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[fileOffset];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
fontFile.forget(aFontFile);
|
||||
ffsRef.forget(aFontFileStream);
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -113,8 +113,7 @@ public:
|
||||
|
||||
// IDWriteFontFileLoader methods
|
||||
/**
|
||||
* Important! Note the key here -has- to be a pointer to an
|
||||
* FallibleTArray<uint8_t>.
|
||||
* Important! Note the key here -has- to be a pointer to a uint64_t.
|
||||
*/
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
CreateStreamFromKey(void const* fontFileReferenceKey,
|
||||
@@ -123,8 +122,7 @@ public:
|
||||
|
||||
/**
|
||||
* Gets the singleton loader instance. Note that when using this font
|
||||
* loader, the key must be a pointer to an FallibleTArray<uint8_t>. This
|
||||
* array will be empty when the function returns.
|
||||
* loader, the key must be a pointer to a unint64_t.
|
||||
*/
|
||||
static IDWriteFontFileLoader* Instance()
|
||||
{
|
||||
@@ -136,71 +134,21 @@ public:
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a IDWriteFontFile and IDWriteFontFileStream from aFontData.
|
||||
* aFontData will be empty on return as it swaps out the data.
|
||||
*
|
||||
* @param aFontData the font data for the custom font file
|
||||
* @param aFontFile out param for the created font file
|
||||
* @param aFontFileStream out param for the corresponding stream
|
||||
* @return HRESULT of internal calls
|
||||
*/
|
||||
static HRESULT CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData,
|
||||
IDWriteFontFile** aFontFile,
|
||||
IDWriteFontFileStream** aFontFileStream);
|
||||
|
||||
private:
|
||||
static IDWriteFontFileLoader* mInstance;
|
||||
};
|
||||
|
||||
class gfxDWriteFontFileStream final : public IDWriteFontFileStream
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used by the FontFileLoader to create a new font stream,
|
||||
* this font stream is created from data in memory. The memory
|
||||
* passed may be released after object creation, it will be
|
||||
* copied internally.
|
||||
*
|
||||
* @param aData Font data
|
||||
*/
|
||||
gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData);
|
||||
~gfxDWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
if (mRefCnt == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
// IDWriteFontFileStream methods
|
||||
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
OUT void** fragmentContext);
|
||||
|
||||
virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
|
||||
|
||||
private:
|
||||
FallibleTArray<uint8_t> mData;
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
#endif /* GFX_DWRITECOMMON_H */
|
||||
|
||||
@@ -342,6 +342,24 @@ gfxDWriteFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
||||
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
already_AddRefed<IDWriteFont>
|
||||
gfxDWriteFontFamily::GetDefaultFont()
|
||||
{
|
||||
RefPtr<IDWriteFont> font;
|
||||
for (UINT32 i = 0; i < mDWFamily->GetFontCount(); i++) {
|
||||
HRESULT hr = mDWFamily->GetFont(i, getter_AddRefs(font));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to get default font from existing family");
|
||||
continue;
|
||||
}
|
||||
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
NS_WARNING("No available DWrite fonts. Returning null");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// gfxDWriteFontEntry
|
||||
|
||||
@@ -792,35 +810,12 @@ gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteFontFileStream> fontFileStream;
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
HRESULT hr;
|
||||
|
||||
/**
|
||||
* We pass in a pointer to a structure containing a pointer to the array
|
||||
* containing the font data and a unique identifier. DWrite will
|
||||
* internally copy what is at that pointer, and pass that to
|
||||
* CreateStreamFromKey. The array will be empty when the function
|
||||
* succesfully returns since it swaps out the data.
|
||||
*/
|
||||
ffReferenceKey key;
|
||||
key.mArray = &newFontData;
|
||||
nsCOMPtr<nsIUUIDGenerator> uuidgen =
|
||||
do_GetService("@mozilla.org/uuid-generator;1");
|
||||
if (!uuidgen) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = uuidgen->GenerateUUIDInPlace(&key.mGUID);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateCustomFontFileReference(&key,
|
||||
sizeof(key),
|
||||
gfxDWriteFontFileLoader::Instance(),
|
||||
getter_AddRefs(fontFile));
|
||||
HRESULT hr =
|
||||
gfxDWriteFontFileLoader::CreateCustomFontFile(newFontData,
|
||||
getter_AddRefs(fontFile),
|
||||
getter_AddRefs(fontFileStream));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create custom font file reference.");
|
||||
@@ -834,6 +829,7 @@ gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
gfxDWriteFontEntry *entry =
|
||||
new gfxDWriteFontEntry(uniqueName,
|
||||
fontFile,
|
||||
fontFileStream,
|
||||
aWeight,
|
||||
aStretch,
|
||||
aStyle);
|
||||
@@ -863,9 +859,9 @@ gfxDWriteFontList::InitFontList()
|
||||
char nowTime[256], nowDate[256];
|
||||
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT,
|
||||
GetTimeFormatA(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT,
|
||||
nullptr, nullptr, nowTime, 256);
|
||||
GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256);
|
||||
GetDateFormatA(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256);
|
||||
upTime = (double) GetTickCount();
|
||||
}
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
already_AddRefed<IDWriteFont> GetDefaultFont();
|
||||
protected:
|
||||
/** This font family's directwrite fontfamily object */
|
||||
RefPtr<IDWriteFontFamily> mDWFamily;
|
||||
@@ -126,17 +127,19 @@ public:
|
||||
*
|
||||
* \param aFaceName The name of the corresponding font face.
|
||||
* \param aFontFile DirectWrite fontfile object
|
||||
* \param aFontFileStream DirectWrite fontfile stream object
|
||||
* \param aWeight Weight of the font
|
||||
* \param aStretch Stretch of the font
|
||||
* \param aStyle italic or oblique of font
|
||||
*/
|
||||
gfxDWriteFontEntry(const nsAString& aFaceName,
|
||||
IDWriteFontFile *aFontFile,
|
||||
IDWriteFontFileStream *aFontFileStream,
|
||||
uint16_t aWeight,
|
||||
int16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFont(nullptr), mFontFile(aFontFile),
|
||||
mForceGDIClassic(false)
|
||||
mFontFileStream(aFontFileStream), mForceGDIClassic(false)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
mStretch = aStretch;
|
||||
@@ -163,6 +166,10 @@ public:
|
||||
virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
IDWriteFont* GetFont() {
|
||||
return mFont;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class gfxDWriteFont;
|
||||
friend class gfxDWriteFontList;
|
||||
@@ -186,6 +193,10 @@ protected:
|
||||
RefPtr<IDWriteFont> mFont;
|
||||
RefPtr<IDWriteFontFile> mFontFile;
|
||||
|
||||
// For custom fonts, we hold a reference to the IDWriteFontFileStream for
|
||||
// for the IDWriteFontFile, so that the data is available.
|
||||
RefPtr<IDWriteFontFileStream> mFontFileStream;
|
||||
|
||||
// font face corresponding to the mFont/mFontFile *without* any DWrite
|
||||
// style simulations applied
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
@@ -82,7 +82,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||
, mAllowManualShowGlyphs(true)
|
||||
{
|
||||
gfxDWriteFontEntry *fe =
|
||||
static_cast<gfxDWriteFontEntry*>(aFontEntry);
|
||||
static_cast<gfxDWriteFontEntry*>(aFontEntry);
|
||||
nsresult rv;
|
||||
DWRITE_FONT_SIMULATIONS sims = DWRITE_FONT_SIMULATIONS_NONE;
|
||||
if ((GetStyle()->style != NS_FONT_STYLE_NORMAL) &&
|
||||
@@ -103,6 +103,21 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||
return;
|
||||
}
|
||||
|
||||
mFont = fe->GetFont();
|
||||
if (!mFont) {
|
||||
gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
gfxDWriteFontFamily* defaultFontFamily =
|
||||
static_cast<gfxDWriteFontFamily*>(fontList->GetDefaultFont(aFontStyle));
|
||||
|
||||
mFont = defaultFontFamily->GetDefaultFont();
|
||||
NS_WARNING("Using default font");
|
||||
}
|
||||
|
||||
HRESULT hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily));
|
||||
if (FAILED(hr)) {
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
|
||||
ComputeMetrics(anAAOption);
|
||||
}
|
||||
|
||||
@@ -232,7 +247,7 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
|
||||
UINT32 ucs = L' ';
|
||||
UINT16 glyph;
|
||||
HRESULT hr = mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph);
|
||||
HRESULT hr = mFontFace->GetGlyphIndices(&ucs, 1, &glyph);
|
||||
if (FAILED(hr)) {
|
||||
mMetrics->spaceWidth = 0;
|
||||
} else {
|
||||
@@ -262,7 +277,7 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
|
||||
if (mMetrics->aveCharWidth < 1) {
|
||||
ucs = L'x';
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph))) {
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndices(&ucs, 1, &glyph))) {
|
||||
mMetrics->aveCharWidth = MeasureGlyphWidth(glyph);
|
||||
}
|
||||
if (mMetrics->aveCharWidth < 1) {
|
||||
@@ -272,7 +287,7 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
}
|
||||
|
||||
ucs = L'0';
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph))) {
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndices(&ucs, 1, &glyph))) {
|
||||
mMetrics->zeroOrAveCharWidth = MeasureGlyphWidth(glyph);
|
||||
}
|
||||
if (mMetrics->zeroOrAveCharWidth < 1) {
|
||||
@@ -462,7 +477,8 @@ gfxDWriteFont::SetupCairoFont(gfxContext *aContext)
|
||||
// the cairo_t, precluding any further drawing.
|
||||
return false;
|
||||
}
|
||||
cairo_set_scaled_font(aContext->GetCairo(), scaledFont);
|
||||
cairo_set_scaled_font(gfxContext::RefCairo(aContext->GetDrawTarget()),
|
||||
scaledFont);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -687,6 +703,10 @@ gfxDWriteFont::GetScaledFont(mozilla::gfx::DrawTarget *aTarget)
|
||||
mAzureScaledFont = Factory::CreateScaledFontWithCairo(nativeFont,
|
||||
GetAdjustedSize(),
|
||||
GetCairoScaledFont());
|
||||
} else if (aTarget->GetBackendType() == BackendType::SKIA) {
|
||||
mAzureScaledFont =
|
||||
Factory::CreateScaledFontForDWriteFont(mFont, mFontFamily,
|
||||
mFontFace, GetAdjustedSize());
|
||||
} else {
|
||||
mAzureScaledFont = Factory::CreateScaledFontForNativeFont(nativeFont,
|
||||
GetAdjustedSize());
|
||||
|
||||
@@ -91,6 +91,8 @@ protected:
|
||||
bool GetForceGDIClassic();
|
||||
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
RefPtr<IDWriteFont> mFont;
|
||||
RefPtr<IDWriteFontFamily> mFontFamily;
|
||||
cairo_font_face_t *mCairoFontFace;
|
||||
|
||||
Metrics *mMetrics;
|
||||
|
||||
@@ -178,8 +178,6 @@ gfxFT2FontBase::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID)
|
||||
bool
|
||||
gfxFT2FontBase::SetupCairoFont(gfxContext *aContext)
|
||||
{
|
||||
cairo_t *cr = aContext->GetCairo();
|
||||
|
||||
// The scaled font ctm is not relevant right here because
|
||||
// cairo_set_scaled_font does not record the scaled font itself, but
|
||||
// merely the font_face, font_matrix, font_options. The scaled_font used
|
||||
@@ -212,6 +210,7 @@ gfxFT2FontBase::SetupCairoFont(gfxContext *aContext)
|
||||
// what is set here. It's too late to change things here as measuring has
|
||||
// already taken place. We should really be measuring with a different
|
||||
// font for pdf and ps surfaces (bug 403513).
|
||||
cairo_set_scaled_font(cr, cairoFont);
|
||||
cairo_set_scaled_font(gfxContext::RefCairo(aContext->GetDrawTarget()),
|
||||
cairoFont);
|
||||
return true;
|
||||
}
|
||||
|
||||
+13
-5
@@ -549,9 +549,9 @@ gfxFontShaper::MergeFontFeatures(
|
||||
}
|
||||
|
||||
void
|
||||
gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
|
||||
gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
|
||||
const char16_t *aString,
|
||||
uint32_t aLength)
|
||||
uint32_t aLength)
|
||||
{
|
||||
CompressedGlyph *glyphs = GetCharacterGlyphs() + aOffset;
|
||||
|
||||
@@ -562,8 +562,15 @@ gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
|
||||
|
||||
// the ClusterIterator won't be able to tell us if the string
|
||||
// _begins_ with a cluster-extender, so we handle that here
|
||||
if (aLength && IsClusterExtender(*aString)) {
|
||||
*glyphs = extendCluster;
|
||||
if (aLength) {
|
||||
uint32_t ch = *aString;
|
||||
if (aLength > 1 && NS_IS_HIGH_SURROGATE(ch) &&
|
||||
NS_IS_LOW_SURROGATE(aString[1])) {
|
||||
ch = SURROGATE_TO_UCS4(ch, aString[1]);
|
||||
}
|
||||
if (IsClusterExtender(ch)) {
|
||||
*glyphs = extendCluster;
|
||||
}
|
||||
}
|
||||
|
||||
while (!iter.AtEnd()) {
|
||||
@@ -3217,7 +3224,8 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext,
|
||||
glyph.x = 0;
|
||||
glyph.y = 0;
|
||||
cairo_text_extents_t extents;
|
||||
cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents);
|
||||
cairo_glyph_extents(gfxContext::RefCairo(aContext->GetDrawTarget()),
|
||||
&glyph, 1, &extents);
|
||||
|
||||
const Metrics& fontMetrics = GetMetrics(eHorizontal);
|
||||
int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit();
|
||||
|
||||
@@ -645,8 +645,10 @@ public:
|
||||
void* aHandleFeatureData);
|
||||
|
||||
protected:
|
||||
// the font this shaper is working with
|
||||
gfxFont * mFont;
|
||||
// the font this shaper is working with. The font owns a nsAutoPtr reference
|
||||
// to this object, and will destroy it before it dies. Thus, mFont will always
|
||||
// be valid.
|
||||
gfxFont* MOZ_NON_OWNING_REF mFont;
|
||||
};
|
||||
|
||||
|
||||
@@ -1802,7 +1804,9 @@ public:
|
||||
{
|
||||
mFont->AddGlyphChangeObserver(this);
|
||||
}
|
||||
gfxFont* mFont;
|
||||
// This pointer is nulled by ForgetFont in the gfxFont's
|
||||
// destructor. Before the gfxFont dies.
|
||||
gfxFont* MOZ_NON_OWNING_REF mFont;
|
||||
};
|
||||
friend class GlyphChangeObserver;
|
||||
|
||||
|
||||
@@ -342,7 +342,8 @@ gfxFontEntry::GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
|
||||
"font has invalid unitsPerEm");
|
||||
|
||||
cairo_matrix_t fontMatrix;
|
||||
cairo_get_font_matrix(aContext->GetCairo(), &fontMatrix);
|
||||
cairo_get_font_matrix(gfxContext::RefCairo(aContext->GetDrawTarget()),
|
||||
&fontMatrix);
|
||||
|
||||
gfxMatrix svgToAppSpace(fontMatrix.xx, fontMatrix.yx,
|
||||
fontMatrix.xy, fontMatrix.yy,
|
||||
|
||||
@@ -136,7 +136,7 @@ gfxGDIFont::SetupCairoFont(gfxContext *aContext)
|
||||
// the cairo_t, precluding any further drawing.
|
||||
return false;
|
||||
}
|
||||
cairo_set_scaled_font(aContext->GetCairo(), mScaledFont);
|
||||
cairo_set_scaled_font(gfxContext::RefCairo(aContext->GetDrawTarget()), mScaledFont);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1180,11 +1180,11 @@ gfxGDIFontList::ActivateBundledFonts()
|
||||
if (!file) {
|
||||
continue;
|
||||
}
|
||||
nsCString path;
|
||||
if (NS_FAILED(file->GetNativePath(path))) {
|
||||
nsAutoString path;
|
||||
if (NS_FAILED(file->GetPath(path))) {
|
||||
continue;
|
||||
}
|
||||
AddFontResourceEx(path.get(), FR_PRIVATE, nullptr);
|
||||
AddFontResourceExW(path.get(), FR_PRIVATE, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,9 +197,13 @@ gfxGradientCache::GetGradientStops(const DrawTarget *aDT, nsTArray<GradientStop>
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GradientStops *
|
||||
already_AddRefed<GradientStops>
|
||||
gfxGradientCache::GetOrCreateGradientStops(const DrawTarget *aDT, nsTArray<GradientStop>& aStops, ExtendMode aExtend)
|
||||
{
|
||||
if (aDT->IsRecording()) {
|
||||
return aDT->CreateGradientStops(aStops.Elements(), aStops.Length(), aExtend);
|
||||
}
|
||||
|
||||
RefPtr<GradientStops> gs = GetGradientStops(aDT, aStops, aExtend);
|
||||
if (!gs) {
|
||||
gs = aDT->CreateGradientStops(aStops.Elements(), aStops.Length(), aExtend);
|
||||
@@ -213,7 +217,7 @@ gfxGradientCache::GetOrCreateGradientStops(const DrawTarget *aDT, nsTArray<Gradi
|
||||
delete cached;
|
||||
}
|
||||
}
|
||||
return gs;
|
||||
return gs.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
nsTArray<gfx::GradientStop>& aStops,
|
||||
gfx::ExtendMode aExtend);
|
||||
|
||||
static gfx::GradientStops*
|
||||
static already_AddRefed<gfx::GradientStops>
|
||||
GetOrCreateGradientStops(const gfx::DrawTarget *aDT,
|
||||
nsTArray<gfx::GradientStop>& aStops,
|
||||
gfx::ExtendMode aExtend);
|
||||
|
||||
@@ -160,7 +160,8 @@ gfxMacFont::SetupCairoFont(gfxContext *aContext)
|
||||
// the cairo_t, precluding any further drawing.
|
||||
return false;
|
||||
}
|
||||
cairo_set_scaled_font(aContext->GetCairo(), mScaledFont);
|
||||
cairo_set_scaled_font(gfxContext::RefCairo(aContext->GetDrawTarget()),
|
||||
mScaledFont);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -545,6 +545,10 @@ gfxPlatform::Init()
|
||||
#error "No gfxPlatform implementation available"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkGraphics::Init();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GL_DEBUG
|
||||
GLContext::StaticInit();
|
||||
#endif
|
||||
|
||||
@@ -619,24 +619,6 @@ gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
|
||||
return data.mBestMatch;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
|
||||
// crude hack for using when monitoring process
|
||||
static void LogRegistryEvent(const wchar_t *msg)
|
||||
{
|
||||
HKEY dummyKey;
|
||||
HRESULT hr;
|
||||
wchar_t buf[512];
|
||||
|
||||
wsprintfW(buf, L" log %s", msg);
|
||||
hr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
|
||||
if (SUCCEEDED(hr)) {
|
||||
RegCloseKey(dummyKey);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gfxFontFamily*
|
||||
gfxPlatformFontList::CheckFamily(gfxFontFamily *aFamily)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
||||
@@ -201,6 +201,7 @@ private:
|
||||
DECL_GFX_PREF(Once, "dom.vr.cardboard.enabled", VRCardboardEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "dom.vr.add-test-devices", VRAddTestDevices, int32_t, 1);
|
||||
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "dom.w3c_touch_events.enabled", TouchEventsEnabled, int32_t, 0);
|
||||
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll", SmoothScrollEnabled, bool, true);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio",
|
||||
@@ -255,11 +256,11 @@ private:
|
||||
DECL_GFX_PREF(Live, "gfx.SurfaceTexture.detach.enabled", SurfaceTextureDetachEnabled, bool, true);
|
||||
DECL_GFX_PREF(Live, "gfx.testing.device-reset", DeviceResetForTesting, int32_t, 0);
|
||||
DECL_GFX_PREF(Live, "gfx.testing.device-fail", DeviceFailForTesting, bool, false);
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample", TouchResampling, bool, false);
|
||||
|
||||
// These times should be in milliseconds
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold", TouchResampleVsyncDelayThreshold, int32_t, 20);
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict", TouchResampleMaxPredict, int32_t, 8);
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample.min-delta", TouchResampleMinDelta, int32_t, 2);
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17);
|
||||
DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust", TouchVsyncSampleAdjust, int32_t, 5);
|
||||
|
||||
@@ -439,6 +440,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
|
||||
DECL_GFX_PREF(Live, "webgl.allow-immediate-queries", WebGLImmediateQueries, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.webgl2-compat-mode", WebGL2CompatMode, bool, false);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
|
||||
nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
|
||||
|
||||
nsAutoCString mSVGGlyphsDocumentURI;
|
||||
nsCString mSVGGlyphsDocumentURI;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
#include "gfxAlphaRecovery.h"
|
||||
#include "gfxPattern.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Helpers.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-win32.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@@ -43,12 +47,21 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
|
||||
{
|
||||
if (mRenderState == RENDER_STATE_INIT) {
|
||||
RefPtr<gfxASurface> surf;
|
||||
|
||||
if (mContext->GetCairo()) {
|
||||
surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y);
|
||||
DrawTarget* drawTarget = mContext->GetDrawTarget();
|
||||
cairo_t* cairo = nullptr;
|
||||
if (drawTarget->GetBackendType() == BackendType::CAIRO) {
|
||||
cairo = static_cast<cairo_t*>
|
||||
(drawTarget->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
|
||||
if (cairo) {
|
||||
cairo_surface_t* s = cairo_get_target(cairo);
|
||||
if (s) {
|
||||
mDeviceOffset = mContext->GetDeviceOffset();
|
||||
surf = gfxASurface::Wrap(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (surf && surf->CairoStatus())
|
||||
if (surf && surf->CairoStatus() != 0)
|
||||
return nullptr;
|
||||
|
||||
gfxMatrix m = mContext->CurrentMatrix();
|
||||
@@ -72,7 +85,7 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
|
||||
// grab the DC. This can fail if there is a complex clipping path,
|
||||
// in which case we'll have to fall back.
|
||||
mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
|
||||
mDC = mWinSurface->GetDCWithClip(mContext);
|
||||
mDC = cairo_win32_get_dc_with_clip(cairo);
|
||||
|
||||
if (mDC) {
|
||||
if (mTransformType == TRANSLATION_ONLY) {
|
||||
@@ -149,8 +162,8 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
|
||||
}
|
||||
GetViewportOrgEx(mDC, &mOrigViewportOrigin);
|
||||
SetViewportOrgEx(mDC,
|
||||
mOrigViewportOrigin.x + (int)mDeviceOffset.x,
|
||||
mOrigViewportOrigin.y + (int)mDeviceOffset.y,
|
||||
mOrigViewportOrigin.x - (int)mDeviceOffset.x,
|
||||
mOrigViewportOrigin.y - (int)mDeviceOffset.y,
|
||||
nullptr);
|
||||
|
||||
return mDC;
|
||||
@@ -252,26 +265,22 @@ gfxWindowsNativeDrawing::PaintToContext()
|
||||
black->Stride(),
|
||||
black->GetSize(),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
{
|
||||
DrawTarget* dt = mContext->GetDrawTarget();
|
||||
AutoRestoreTransform autoRestoreTransform(dt);
|
||||
|
||||
mContext->Save();
|
||||
mContext->SetMatrix(
|
||||
mContext->CurrentMatrix().Translate(mNativeRect.TopLeft()));
|
||||
mContext->NewPath();
|
||||
mContext->Rectangle(gfxRect(gfxPoint(0.0, 0.0), mNativeRect.Size()));
|
||||
Matrix newTransform = dt->GetTransform();
|
||||
newTransform.PreTranslate(ToPoint(mNativeRect.TopLeft()));
|
||||
dt->SetTransform(newTransform);
|
||||
|
||||
RefPtr<gfxPattern> pat = new gfxPattern(source, Matrix());
|
||||
|
||||
gfxMatrix m;
|
||||
m.Scale(mScale.width, mScale.height);
|
||||
pat->SetMatrix(m);
|
||||
|
||||
if (mNativeDrawFlags & DO_NEAREST_NEIGHBOR_FILTERING)
|
||||
pat->SetFilter(Filter::LINEAR);
|
||||
|
||||
pat->SetExtend(ExtendMode::CLAMP);
|
||||
mContext->SetPattern(pat);
|
||||
mContext->Fill();
|
||||
mContext->Restore();
|
||||
Rect rect(Point(0.0, 0.0), ToSize(mNativeRect.Size()));
|
||||
Matrix m = Matrix::Scaling(1.0 / mScale.width, 1.0 / mScale.height);
|
||||
Filter filter = (mNativeDrawFlags & DO_NEAREST_NEIGHBOR_FILTERING)
|
||||
? Filter::LINEAR
|
||||
: Filter::GOOD;
|
||||
SurfacePattern pat(source, ExtendMode::CLAMP, m, filter);
|
||||
dt->FillRect(rect, pat);
|
||||
}
|
||||
|
||||
mRenderState = RENDER_STATE_DONE;
|
||||
} else {
|
||||
|
||||
@@ -91,7 +91,7 @@ private:
|
||||
// what state the rendering is in
|
||||
uint8_t mRenderState;
|
||||
|
||||
gfxPoint mDeviceOffset;
|
||||
mozilla::gfx::Point mDeviceOffset;
|
||||
RefPtr<gfxPattern> mBlackPattern, mWhitePattern;
|
||||
|
||||
enum TransformType {
|
||||
|
||||
@@ -690,9 +690,7 @@ gfxWindowsPlatform::CreatePlatformFontList()
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
// bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
|
||||
// crashers so blacklist them altogether
|
||||
if (IsNotWin7PreRTM() && GetDWriteFactory() &&
|
||||
// Skia doesn't support DirectWrite fonts yet.
|
||||
(gfxPlatform::GetDefaultContentBackend() != BackendType::SKIA)) {
|
||||
if (IsNotWin7PreRTM() && GetDWriteFactory()) {
|
||||
pfl = new gfxDWriteFontList();
|
||||
if (NS_SUCCEEDED(pfl->InitFontList())) {
|
||||
return pfl;
|
||||
@@ -2996,7 +2994,7 @@ gfxWindowsPlatform::CreateHardwareVsyncSource()
|
||||
bool
|
||||
gfxWindowsPlatform::SupportsApzTouchInput() const
|
||||
{
|
||||
int value = Preferences::GetInt("dom.w3c_touch_events.enabled", 0);
|
||||
int value = gfxPrefs::TouchEventsEnabled();
|
||||
return value == 1 || value == 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,12 +172,6 @@ gfxWindowsSurface::~gfxWindowsSurface()
|
||||
}
|
||||
}
|
||||
|
||||
HDC
|
||||
gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
|
||||
{
|
||||
return cairo_win32_get_dc_with_clip (ctx->GetCairo());
|
||||
}
|
||||
|
||||
HDC
|
||||
gfxWindowsSurface::GetDC()
|
||||
{
|
||||
@@ -214,6 +208,10 @@ gfxWindowsSurface::BeginPrinting(const nsAString& aTitle,
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
#define DOC_TITLE_LENGTH (MAX_PATH-1)
|
||||
if (!mForPrinting) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DOCINFOW docinfo;
|
||||
|
||||
nsString titleStr(aTitle);
|
||||
@@ -241,6 +239,10 @@ nsresult
|
||||
gfxWindowsSurface::EndPrinting()
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
if (!mForPrinting) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int result = ::EndDoc(mDC);
|
||||
if (result <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -255,6 +257,10 @@ nsresult
|
||||
gfxWindowsSurface::AbortPrinting()
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
if (!mForPrinting) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int result = ::AbortDoc(mDC);
|
||||
if (result <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -268,6 +274,10 @@ nsresult
|
||||
gfxWindowsSurface::BeginPage()
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
if (!mForPrinting) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int result = ::StartPage(mDC);
|
||||
if (result <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -281,8 +291,11 @@ nsresult
|
||||
gfxWindowsSurface::EndPage()
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
if (mForPrinting)
|
||||
cairo_surface_show_page(CairoSurface());
|
||||
if (!mForPrinting) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
cairo_surface_show_page(CairoSurface());
|
||||
int result = ::EndPage(mDC);
|
||||
if (result <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@@ -53,8 +53,6 @@ public:
|
||||
|
||||
HDC GetDC();
|
||||
|
||||
HDC GetDCWithClip(gfxContext *);
|
||||
|
||||
already_AddRefed<gfxImageSurface> GetAsImageSurface();
|
||||
|
||||
nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
|
||||
|
||||
@@ -310,6 +310,3 @@ DEFINES['GRAPHITE2_STATIC'] = True
|
||||
|
||||
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['OTS_DLL'] = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
del DEFINES['UNICODE']
|
||||
|
||||
@@ -24,8 +24,26 @@
|
||||
#pragma push_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
|
||||
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
// Suppress -Wshadow warnings from stlport headers.
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 9, 0)
|
||||
# pragma GCC diagnostic ignored "-Wshadow-local"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <hash_map>
|
||||
#include <hash_set>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 9, 0)
|
||||
# pragma GCC diagnostic pop // -Wshadow-local
|
||||
# endif
|
||||
# pragma GCC diagnostic pop // -Wshadow
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER_MSVC
|
||||
#pragma pop_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
|
||||
#endif
|
||||
|
||||
@@ -436,7 +436,8 @@ Histogram::Histogram(const std::string& name, Sample minimum,
|
||||
bucket_count_(bucket_count),
|
||||
flags_(kNoFlags),
|
||||
ranges_(bucket_count + 1, 0),
|
||||
range_checksum_(0) {
|
||||
range_checksum_(0),
|
||||
recording_enabled_(true) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
@@ -449,7 +450,8 @@ Histogram::Histogram(const std::string& name, TimeDelta minimum,
|
||||
bucket_count_(bucket_count),
|
||||
flags_(kNoFlags),
|
||||
ranges_(bucket_count + 1, 0),
|
||||
range_checksum_(0) {
|
||||
range_checksum_(0),
|
||||
recording_enabled_(true) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
@@ -558,8 +560,7 @@ const std::string Histogram::GetAsciiBucketRange(size_t i) const {
|
||||
// Update histogram data with new sample.
|
||||
void Histogram::Accumulate(Sample value, Count count, size_t index) {
|
||||
// Note locking not done in this version!!!
|
||||
sample_.AccumulateWithExponentialStats(value, count, index,
|
||||
flags_ & kExtendedStatisticsFlag);
|
||||
sample_.AccumulateWithLinearStats(value, count, index);
|
||||
}
|
||||
|
||||
void Histogram::SetBucketRange(size_t i, Sample value) {
|
||||
@@ -741,19 +742,6 @@ void Histogram::SampleSet::AccumulateWithLinearStats(Sample value,
|
||||
sum_squares_ += static_cast<int64_t>(count) * value * value;
|
||||
}
|
||||
|
||||
void Histogram::SampleSet::AccumulateWithExponentialStats(Sample value,
|
||||
Count count,
|
||||
size_t index,
|
||||
bool computeExtendedStatistics) {
|
||||
Accumulate(value, count, index);
|
||||
if (computeExtendedStatistics) {
|
||||
DCHECK_GE(value, 0);
|
||||
float value_log = logf(static_cast<float>(value) + 1.0f);
|
||||
log_sum_ += count * value_log;
|
||||
log_sum_squares_ += count * value_log * value_log;
|
||||
}
|
||||
}
|
||||
|
||||
Count Histogram::SampleSet::TotalCount() const {
|
||||
Count total = 0;
|
||||
for (Counts::const_iterator it = counts_.begin();
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define BASE_METRICS_HISTOGRAM_H_
|
||||
#pragma once
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include <map>
|
||||
@@ -292,7 +293,6 @@ class Histogram {
|
||||
enum Flags {
|
||||
kNoFlags = 0,
|
||||
kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded.
|
||||
kExtendedStatisticsFlag = 0x2, // OK to gather extended statistics on histograms.
|
||||
|
||||
// Indicate that the histogram was pickled to be sent across an IPC Channel.
|
||||
// If we observe this flag on a histogram being aggregated into after IPC,
|
||||
@@ -335,10 +335,6 @@ class Histogram {
|
||||
|
||||
// Accessor for histogram to make routine additions.
|
||||
void AccumulateWithLinearStats(Sample value, Count count, size_t index);
|
||||
// Alternate routine for exponential histograms.
|
||||
// computeExpensiveStatistics should be true if we want to compute log sums.
|
||||
void AccumulateWithExponentialStats(Sample value, Count count, size_t index,
|
||||
bool computeExtendedStatistics);
|
||||
|
||||
// Accessor methods.
|
||||
Count counts(size_t i) const { return counts_[i]; }
|
||||
@@ -405,6 +401,12 @@ class Histogram {
|
||||
void Add(int value);
|
||||
void Subtract(int value);
|
||||
|
||||
// TODO: Currently recording_enabled_ is not used by any Histogram class, but
|
||||
// rather examined only by the telemetry code (via IsRecordingEnabled).
|
||||
// Move handling to Histogram's Add() etc after simplifying Histogram.
|
||||
void SetRecordingEnabled(bool aEnabled) { recording_enabled_ = aEnabled; };
|
||||
bool IsRecordingEnabled() const { return recording_enabled_; };
|
||||
|
||||
// This method is an interface, used only by BooleanHistogram.
|
||||
virtual void AddBoolean(bool value);
|
||||
|
||||
@@ -589,6 +591,9 @@ class Histogram {
|
||||
// have been corrupted.
|
||||
uint32_t range_checksum_;
|
||||
|
||||
// When false, new samples are completely ignored.
|
||||
mozilla::Atomic<bool, mozilla::Relaxed> recording_enabled_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Histogram);
|
||||
};
|
||||
|
||||
|
||||
@@ -233,9 +233,9 @@ public:
|
||||
int32_t id() const { return id_; }
|
||||
|
||||
// Optional call to connect the thread name with this loop.
|
||||
void set_thread_name(const std::string& thread_name) {
|
||||
void set_thread_name(const std::string& aThreadName) {
|
||||
DCHECK(thread_name_.empty()) << "Should not rename this thread!";
|
||||
thread_name_ = thread_name;
|
||||
thread_name_ = aThreadName;
|
||||
}
|
||||
const std::string& thread_name() const { return thread_name_; }
|
||||
|
||||
@@ -324,8 +324,8 @@ public:
|
||||
int sequence_num; // Secondary sort key for run time.
|
||||
bool nestable; // OK to dispatch from a nested loop.
|
||||
|
||||
PendingTask(Task* task, bool nestable)
|
||||
: task(task), sequence_num(0), nestable(nestable) {
|
||||
PendingTask(Task* aTask, bool aNestable)
|
||||
: task(aTask), sequence_num(0), nestable(aNestable) {
|
||||
}
|
||||
|
||||
// Used to support sorting.
|
||||
@@ -463,7 +463,7 @@ public:
|
||||
//
|
||||
class MessageLoopForUI : public MessageLoop {
|
||||
public:
|
||||
explicit MessageLoopForUI(Type type=TYPE_UI) : MessageLoop(type) {
|
||||
explicit MessageLoopForUI(Type aType=TYPE_UI) : MessageLoop(aType) {
|
||||
}
|
||||
|
||||
// Returns the MessageLoopForUI of the current thread.
|
||||
|
||||
@@ -29,8 +29,8 @@ typedef pid_t ProcessId;
|
||||
class Process {
|
||||
public:
|
||||
Process() : process_(0), last_working_set_size_(0) {}
|
||||
explicit Process(ProcessHandle handle) :
|
||||
process_(handle), last_working_set_size_(0) {}
|
||||
explicit Process(ProcessHandle aHandle) :
|
||||
process_(aHandle), last_working_set_size_(0) {}
|
||||
|
||||
// A handle to the current process.
|
||||
static Process Current();
|
||||
@@ -38,7 +38,7 @@ class Process {
|
||||
// Get/Set the handle for this process. The handle will be 0 if the process
|
||||
// is no longer running.
|
||||
ProcessHandle handle() const { return process_; }
|
||||
void set_handle(ProcessHandle handle) { process_ = handle; }
|
||||
void set_handle(ProcessHandle aHandle) { process_ = aHandle; }
|
||||
|
||||
// Get the PID for this process.
|
||||
ProcessId pid() const;
|
||||
|
||||
@@ -129,6 +129,7 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
||||
break;
|
||||
case PROCESS_ARCH_PPC:
|
||||
cpu_types[0] = CPU_TYPE_POWERPC;
|
||||
break;
|
||||
default:
|
||||
cpu_types[0] = CPU_TYPE_ANY;
|
||||
break;
|
||||
|
||||
@@ -20,9 +20,9 @@ class RevocableStore {
|
||||
class StoreRef final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StoreRef)
|
||||
explicit StoreRef(RevocableStore* store) : store_(store) { }
|
||||
explicit StoreRef(RevocableStore* aStore) : store_(aStore) { }
|
||||
|
||||
void set_store(RevocableStore* store) { store_ = store; }
|
||||
void set_store(RevocableStore* aStore) { store_ = aStore; }
|
||||
RevocableStore* store() const { return store_; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -54,14 +54,14 @@ class StringPiece {
|
||||
bool empty() const { return length_ == 0; }
|
||||
|
||||
void clear() { ptr_ = NULL; length_ = 0; }
|
||||
void set(const char* data, size_type len) { ptr_ = data; length_ = len; }
|
||||
void set(const char* aData, size_type aLen) { ptr_ = aData; length_ = aLen; }
|
||||
void set(const char* str) {
|
||||
ptr_ = str;
|
||||
length_ = str ? strlen(str) : 0;
|
||||
}
|
||||
void set(const void* data, size_type len) {
|
||||
ptr_ = reinterpret_cast<const char*>(data);
|
||||
length_ = len;
|
||||
void set(const void* aData, size_type aLen) {
|
||||
ptr_ = reinterpret_cast<const char*>(aData);
|
||||
length_ = aLen;
|
||||
}
|
||||
|
||||
char operator[](size_type i) const { return ptr_[i]; }
|
||||
|
||||
@@ -39,10 +39,10 @@ class Location {
|
||||
// Constructor should be called with a long-lived char*, such as __FILE__.
|
||||
// It assumes the provided value will persist as a global constant, and it
|
||||
// will not make a copy of it.
|
||||
Location(const char* function_name, const char* file_name, int line_number)
|
||||
: function_name_(function_name),
|
||||
file_name_(file_name),
|
||||
line_number_(line_number) { }
|
||||
Location(const char* aFunctionName, const char* aFilename, int aLineNumber)
|
||||
: function_name_(aFunctionName),
|
||||
file_name_(aFilename),
|
||||
line_number_(aLineNumber) { }
|
||||
|
||||
// Provide a default constructor for easy of debugging.
|
||||
Location()
|
||||
|
||||
@@ -79,10 +79,10 @@ class ChildProcessInfo {
|
||||
}
|
||||
|
||||
protected:
|
||||
void set_type(ProcessType type) { type_ = type; }
|
||||
void set_name(const std::wstring& name) { name_ = name; }
|
||||
void set_handle(base::ProcessHandle handle) {
|
||||
process_.set_handle(handle);
|
||||
void set_type(ProcessType aType) { type_ = aType; }
|
||||
void set_name(const std::wstring& aName) { name_ = aName; }
|
||||
void set_handle(base::ProcessHandle aHandle) {
|
||||
process_.set_handle(aHandle);
|
||||
pid_ = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@ namespace IPC {
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Message::~Message() {
|
||||
MOZ_COUNT_DTOR(IPC::Message);
|
||||
}
|
||||
|
||||
Message::Message()
|
||||
: Pickle(sizeof(Header)) {
|
||||
MOZ_COUNT_CTOR(IPC::Message);
|
||||
header()->routing = header()->type = header()->flags = 0;
|
||||
#if defined(OS_POSIX)
|
||||
header()->num_fds = 0;
|
||||
@@ -42,8 +44,9 @@ Message::Message()
|
||||
}
|
||||
|
||||
Message::Message(int32_t routing_id, msgid_t type, PriorityValue priority,
|
||||
MessageCompression compression, const char* const name)
|
||||
MessageCompression compression, const char* const aName)
|
||||
: Pickle(sizeof(Header)) {
|
||||
MOZ_COUNT_CTOR(IPC::Message);
|
||||
header()->routing = routing_id;
|
||||
header()->type = type;
|
||||
header()->flags = priority;
|
||||
@@ -65,14 +68,16 @@ Message::Message(int32_t routing_id, msgid_t type, PriorityValue priority,
|
||||
header()->parent_task_id = 0;
|
||||
header()->source_event_type = SourceEventType::Unknown;
|
||||
#endif
|
||||
InitLoggingVariables(name);
|
||||
InitLoggingVariables(aName);
|
||||
}
|
||||
|
||||
Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
|
||||
MOZ_COUNT_CTOR(IPC::Message);
|
||||
InitLoggingVariables();
|
||||
}
|
||||
|
||||
Message::Message(const Message& other) : Pickle(other) {
|
||||
MOZ_COUNT_CTOR(IPC::Message);
|
||||
InitLoggingVariables(other.name_);
|
||||
#if defined(OS_POSIX)
|
||||
file_descriptor_set_ = other.file_descriptor_set_;
|
||||
@@ -85,6 +90,7 @@ Message::Message(const Message& other) : Pickle(other) {
|
||||
}
|
||||
|
||||
Message::Message(Message&& other) : Pickle(mozilla::Move(other)) {
|
||||
MOZ_COUNT_CTOR(IPC::Message);
|
||||
InitLoggingVariables(other.name_);
|
||||
#if defined(OS_POSIX)
|
||||
file_descriptor_set_ = other.file_descriptor_set_.forget();
|
||||
@@ -96,8 +102,8 @@ Message::Message(Message&& other) : Pickle(mozilla::Move(other)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void Message::InitLoggingVariables(const char* const name) {
|
||||
name_ = name;
|
||||
void Message::InitLoggingVariables(const char* const aName) {
|
||||
name_ = aName;
|
||||
}
|
||||
|
||||
Message& Message::operator=(const Message& other) {
|
||||
|
||||
@@ -190,16 +190,16 @@ class Message : public Pickle {
|
||||
return header()->seqno;
|
||||
}
|
||||
|
||||
void set_seqno(int32_t seqno) {
|
||||
header()->seqno = seqno;
|
||||
void set_seqno(int32_t aSeqno) {
|
||||
header()->seqno = aSeqno;
|
||||
}
|
||||
|
||||
const char* const name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
void set_name(const char* const name) {
|
||||
name_ = name;
|
||||
void set_name(const char* const aName) {
|
||||
name_ = aName;
|
||||
}
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
|
||||
@@ -443,8 +443,11 @@ private:
|
||||
#ifndef ANDROID /* bug 1142079 */
|
||||
if (XRE_IsParentProcess()) {
|
||||
TimeDuration vsyncLatency = TimeStamp::Now() - aVsyncTimestamp;
|
||||
uint32_t sample = (uint32_t)vsyncLatency.ToMilliseconds();
|
||||
Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_CHROME_FRAME_DELAY_MS,
|
||||
vsyncLatency.ToMilliseconds());
|
||||
sample);
|
||||
Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS,
|
||||
sample);
|
||||
} else if (mVsyncRate != TimeDuration::Forever()) {
|
||||
TimeDuration contentDelay = (TimeStamp::Now() - mLastChildTick) - mVsyncRate;
|
||||
if (contentDelay.ToMilliseconds() < 0 ){
|
||||
@@ -452,8 +455,11 @@ private:
|
||||
// the reported hardware rate. In those cases, consider that we have 0 delay.
|
||||
contentDelay = TimeDuration::FromMilliseconds(0);
|
||||
}
|
||||
uint32_t sample = (uint32_t)contentDelay.ToMilliseconds();
|
||||
Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_CONTENT_FRAME_DELAY_MS,
|
||||
contentDelay.ToMilliseconds());
|
||||
sample);
|
||||
Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS,
|
||||
sample);
|
||||
} else {
|
||||
// Request the vsync rate from the parent process. Might be a few vsyncs
|
||||
// until the parent responds.
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include <stdint.h>
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "nsSMILKeySpline.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
@@ -1510,6 +1511,8 @@ public:
|
||||
, mCallee(nullptr)
|
||||
, mOneDevicePixelInAppUnits(aPresContext->DevPixelsToAppUnits(1))
|
||||
{
|
||||
Telemetry::SetHistogramRecordingEnabled(
|
||||
Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, true);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(AsyncSmoothMSDScroll, override)
|
||||
@@ -1598,6 +1601,8 @@ private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~AsyncSmoothMSDScroll() {
|
||||
RemoveObserver();
|
||||
Telemetry::SetHistogramRecordingEnabled(
|
||||
Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, false);
|
||||
}
|
||||
|
||||
nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) {
|
||||
@@ -1634,12 +1639,17 @@ public:
|
||||
explicit AsyncScroll(nsPoint aStartPos)
|
||||
: AsyncScrollBase(aStartPos)
|
||||
, mCallee(nullptr)
|
||||
{}
|
||||
{
|
||||
Telemetry::SetHistogramRecordingEnabled(
|
||||
Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, true);
|
||||
}
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~AsyncScroll() {
|
||||
RemoveObserver();
|
||||
Telemetry::SetHistogramRecordingEnabled(
|
||||
Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, false);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -521,6 +521,7 @@ _moz_cairo_transform
|
||||
_moz_cairo_translate
|
||||
_moz_cairo_user_to_device
|
||||
_moz_cairo_user_to_device_distance
|
||||
_moz_cairo_win32_font_face_create_for_logfontw
|
||||
_moz_cairo_win32_font_face_create_for_logfontw_hfont
|
||||
_moz_cairo_win32_get_dc_with_clip
|
||||
_moz_cairo_win32_get_system_text_quality
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "PrintTranslator.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "mozilla/gfx/RecordedEvent.h"
|
||||
#include "mozilla/gfx/RecordingTypes.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
|
||||
PrintTranslator::PrintTranslator(nsDeviceContext* aDeviceContext)
|
||||
: mDeviceContext(aDeviceContext)
|
||||
{
|
||||
RefPtr<gfxContext> context = mDeviceContext->CreateRenderingContext();
|
||||
mBaseDT = context->GetDrawTarget();
|
||||
}
|
||||
|
||||
bool
|
||||
PrintTranslator::TranslateRecording(std::istream& aRecording)
|
||||
{
|
||||
uint32_t magicInt;
|
||||
ReadElement(aRecording, magicInt);
|
||||
if (magicInt != mozilla::gfx::kMagicInt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t majorRevision;
|
||||
ReadElement(aRecording, majorRevision);
|
||||
if (majorRevision != kMajorRevision) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t minorRevision;
|
||||
ReadElement(aRecording, minorRevision);
|
||||
if (minorRevision > kMinorRevision) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t eventType;
|
||||
ReadElement(aRecording, eventType);
|
||||
while (aRecording.good()) {
|
||||
UniquePtr<RecordedEvent> recordedEvent(
|
||||
RecordedEvent::LoadEventFromStream(aRecording,
|
||||
static_cast<RecordedEvent::EventType>(eventType)));
|
||||
|
||||
// Make sure that the whole event was read from the stream successfully.
|
||||
if (!aRecording.good() || !recordedEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
recordedEvent->PlayEvent(this);
|
||||
ReadElement(aRecording, eventType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
PrintTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
|
||||
const gfx::IntSize &aSize,
|
||||
gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
RefPtr<gfxContext> context = mDeviceContext->CreateRenderingContext();
|
||||
if (!context) {
|
||||
NS_WARNING("Failed to create rendering context for print.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> drawTarget = context->GetDrawTarget();
|
||||
AddDrawTarget(aRefPtr, drawTarget);
|
||||
return drawTarget.forget();
|
||||
}
|
||||
|
||||
FontType
|
||||
PrintTranslator::GetDesiredFontType()
|
||||
{
|
||||
switch (mBaseDT->GetBackendType()) {
|
||||
case BackendType::DIRECT2D:
|
||||
return FontType::DWRITE;
|
||||
case BackendType::CAIRO:
|
||||
return FontType::CAIRO;
|
||||
case BackendType::SKIA:
|
||||
return FontType::SKIA;
|
||||
case BackendType::COREGRAPHICS:
|
||||
case BackendType::COREGRAPHICS_ACCELERATED:
|
||||
return FontType::COREGRAPHICS;
|
||||
default:
|
||||
return FontType::CAIRO;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user