mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
153a6ea11e
2
CLOBBER
2
CLOBBER
@ -17,7 +17,7 @@
|
||||
#
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 549861 backout, on Windows due to bug 873809, tests due to...
|
||||
Landing bug 865806
|
||||
|
||||
Alternative to clobber is to run ./config.status from the objdir and to
|
||||
touch the CLOBBER file in the objdir.
|
||||
|
@ -77,11 +77,7 @@ backend.RecursiveMakeBackend.built:
|
||||
@echo "Updating build backend because of moz.build changes."
|
||||
@$(PYTHON) ./config.status
|
||||
|
||||
ifdef .PYMAKE
|
||||
includedeps backend.RecursiveMakeBackend.built.pp
|
||||
else
|
||||
include backend.RecursiveMakeBackend.built.pp
|
||||
endif
|
||||
|
||||
export MOZBUILD_BACKEND_CHECKED=1
|
||||
|
||||
|
@ -383,10 +383,11 @@ private:
|
||||
|
||||
// Returns null if a principal cannot be found; generally callers
|
||||
// should error out at that point.
|
||||
static nsIPrincipal* doGetObjectPrincipal(JSObject *obj);
|
||||
static nsIPrincipal* doGetObjectPrincipal(JS::Handle<JSObject*> obj);
|
||||
#ifdef DEBUG
|
||||
static nsIPrincipal*
|
||||
old_doGetObjectPrincipal(JSObject *obj, bool aAllowShortCircuit = true);
|
||||
old_doGetObjectPrincipal(JS::Handle<JSObject*> obj,
|
||||
bool aAllowShortCircuit = true);
|
||||
#endif
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
|
@ -1633,7 +1633,7 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
|
||||
/*
|
||||
** Get origin of subject and object and compare.
|
||||
*/
|
||||
JSObject* obj = (JSObject*)aTargetObj;
|
||||
JS::Rooted<JSObject*> obj(aCx, (JSObject*)aTargetObj);
|
||||
nsIPrincipal* object = doGetObjectPrincipal(obj);
|
||||
|
||||
if (!object)
|
||||
@ -2023,7 +2023,8 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
|
||||
nsIPrincipal **result)
|
||||
{
|
||||
*result = doGetObjectPrincipal(aObj);
|
||||
JS::Rooted<JSObject*> obj(aCx, aObj);
|
||||
*result = doGetObjectPrincipal(obj);
|
||||
if (!*result)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ADDREF(*result);
|
||||
@ -2032,7 +2033,7 @@ nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
||||
nsScriptSecurityManager::doGetObjectPrincipal(JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
JSCompartment *compartment = js::GetObjectCompartment(aObj);
|
||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
||||
@ -2052,14 +2053,15 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
||||
#ifdef DEBUG
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
||||
nsScriptSecurityManager::old_doGetObjectPrincipal(JS::Handle<JSObject*> aObj,
|
||||
bool aAllowShortCircuit)
|
||||
{
|
||||
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
|
||||
nsIPrincipal* result = nullptr;
|
||||
|
||||
JS::RootedObject obj(sXPConnect->GetCurrentJSContext(), aObj);
|
||||
JSObject* origObj = obj;
|
||||
JSContext* cx = sXPConnect->GetCurrentJSContext();
|
||||
JS::RootedObject obj(cx, aObj);
|
||||
JS::RootedObject origObj(cx, obj);
|
||||
js::Class *jsClass = js::GetObjectClass(obj);
|
||||
|
||||
// A common case seen in this code is that we enter this function
|
||||
@ -2292,8 +2294,8 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
|
||||
do_QueryInterface(aObj);
|
||||
if (xpcwrappedjs)
|
||||
{
|
||||
rv = xpcwrappedjs->GetJSObject(jsObject.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
jsObject = xpcwrappedjs->GetJSObject();
|
||||
NS_ENSURE_STATE(jsObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ new
|
||||
# unsafely in Gecko, so we might as well prevent them from
|
||||
# throwing exceptions
|
||||
algorithm
|
||||
atomic
|
||||
deque
|
||||
iostream
|
||||
iterator
|
||||
@ -38,3 +39,4 @@ cstdlib
|
||||
cstring
|
||||
cwchar
|
||||
tuple
|
||||
xutility
|
||||
|
@ -2204,7 +2204,7 @@ public:
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
|
||||
mm->ReceiveMessage(static_cast<EventTarget*>(tabChild), mMessage,
|
||||
false, &data, nullptr, nullptr, nullptr);
|
||||
false, &data, JS::NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -626,7 +626,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
const nsAString& aMessage,
|
||||
bool aSync,
|
||||
const StructuredCloneData* aCloneData,
|
||||
JSObject* aObjectsArray,
|
||||
JS::Handle<JSObject*> aObjectsArray,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext)
|
||||
{
|
||||
@ -646,8 +646,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
if (!wrappedJS) {
|
||||
continue;
|
||||
}
|
||||
JS::Rooted<JSObject*> object(ctx);
|
||||
wrappedJS->GetJSObject(object.address());
|
||||
JS::Rooted<JSObject*> object(ctx, wrappedJS->GetJSObject());
|
||||
if (!object) {
|
||||
continue;
|
||||
}
|
||||
@ -1009,8 +1008,7 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JS::Rooted<JSObject*> global(mCx);
|
||||
mGlobal->GetJSObject(global.address());
|
||||
JS::Rooted<JSObject*> global(mCx, mGlobal->GetJSObject());
|
||||
if (global) {
|
||||
(void) JS_ExecuteScript(mCx, global, holder->mScript, nullptr);
|
||||
}
|
||||
@ -1068,8 +1066,7 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JS::Rooted<JSObject*> global(mCx);
|
||||
mGlobal->GetJSObject(global.address());
|
||||
JS::Rooted<JSObject*> global(mCx, mGlobal->GetJSObject());
|
||||
if (global) {
|
||||
JSAutoCompartment ac(mCx, global);
|
||||
JS::CompileOptions options(mCx);
|
||||
@ -1138,9 +1135,8 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope,
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
|
||||
JS::Rooted<JSObject*> global(cx);
|
||||
rv = mGlobal->GetJSObject(global.address());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
|
||||
NS_ENSURE_TRUE(global, false);
|
||||
|
||||
JS_SetGlobalObject(cx, global);
|
||||
|
||||
@ -1206,7 +1202,7 @@ public:
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage,
|
||||
false, &data, nullptr, nullptr, nullptr);
|
||||
false, &data, JS::NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1336,7 +1332,7 @@ public:
|
||||
nsRefPtr<nsFrameMessageManager> ppm =
|
||||
nsFrameMessageManager::sSameProcessParentManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
mMessage, false, &data, nullptr, nullptr, nullptr);
|
||||
mMessage, false, &data, JS::NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1376,7 +1372,7 @@ public:
|
||||
if (nsFrameMessageManager::sSameProcessParentManager) {
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage,
|
||||
true, &aData, nullptr, aJSONRetVal);
|
||||
true, &aData, JS::NullPtr(), aJSONRetVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ public:
|
||||
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
|
||||
bool aSync, const StructuredCloneData* aCloneData,
|
||||
JSObject* aObjectsArray,
|
||||
JS::Handle<JSObject*> aObjectsArray,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext = nullptr);
|
||||
|
||||
|
@ -38,7 +38,8 @@ nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage,
|
||||
}
|
||||
if (mChromeMessageManager) {
|
||||
nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
|
||||
mm->ReceiveMessage(mOwner, aMessage, true, &aData, nullptr, aJSONRetVal);
|
||||
mm->ReceiveMessage(mOwner, aMessage, true, &aData, JS::NullPtr(),
|
||||
aJSONRetVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -73,7 +74,7 @@ public:
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
|
||||
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data,
|
||||
nullptr, nullptr, nullptr);
|
||||
JS::NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -121,10 +121,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* global;
|
||||
mGlobal->GetJSObject(&global);
|
||||
|
||||
return global;
|
||||
return mGlobal->GetJSObject();
|
||||
}
|
||||
protected:
|
||||
nsresult Init();
|
||||
|
@ -4292,13 +4292,10 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
||||
int compileOptions = SH_ATTRIBUTES_UNIFORMS |
|
||||
SH_ENFORCE_PACKING_RESTRICTIONS;
|
||||
|
||||
// we want to do this everywhere, but:
|
||||
//TODO: Enable on windows:
|
||||
#ifndef XP_WIN // to do this on Windows, we need ANGLE r1719, 1733, 1734.
|
||||
#ifndef XP_MACOSX // to do this on Mac, we need to do it only on Mac OSX > 10.6 as this
|
||||
// We want to do this everywhere, but:
|
||||
#ifndef XP_MACOSX // To do this on Mac, we need to do it only on Mac OSX > 10.6 as this
|
||||
// causes the shader compiler in 10.6 to crash
|
||||
compileOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (useShaderSourceTranslation) {
|
||||
|
@ -84,8 +84,8 @@ nsEventListenerInfo::GetJSVal(JSContext* aCx,
|
||||
*aJSVal = JSVAL_NULL;
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
|
||||
if (wrappedJS) {
|
||||
JS::Rooted<JSObject*> object(aCx, nullptr);
|
||||
if (NS_FAILED(wrappedJS->GetJSObject(object.address()))) {
|
||||
JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject());
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
aAc.construct(aCx, object);
|
||||
|
@ -26,8 +26,10 @@ public:
|
||||
|
||||
IUnknown* GetDXVADeviceManager() MOZ_OVERRIDE;
|
||||
|
||||
// Copies a region (aRegion) of the video frame stored in aVideoSample
|
||||
// into an image which is returned by aOutImage.
|
||||
HRESULT CopyToImage(IMFSample* aVideoSample,
|
||||
const nsIntSize& aSize,
|
||||
const nsIntRect& aRegion,
|
||||
ImageContainer* aContainer,
|
||||
Image** aOutImage) MOZ_OVERRIDE;
|
||||
|
||||
@ -137,7 +139,7 @@ D3D9DXVA2Manager::Init()
|
||||
|
||||
HRESULT
|
||||
D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
|
||||
const nsIntSize& aSize,
|
||||
const nsIntRect& aRegion,
|
||||
ImageContainer* aImageContainer,
|
||||
Image** aOutImage)
|
||||
{
|
||||
@ -159,7 +161,7 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
|
||||
"Wrong format?");
|
||||
|
||||
D3D9SurfaceImage* videoImage = static_cast<D3D9SurfaceImage*>(image.get());
|
||||
hr = videoImage->SetData(D3D9SurfaceImage::Data(surface, aSize));
|
||||
hr = videoImage->SetData(D3D9SurfaceImage::Data(surface, aRegion));
|
||||
|
||||
image.forget(aOutImage);
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "WMF.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class nsIntSize;
|
||||
|
||||
@ -35,7 +36,7 @@ public:
|
||||
|
||||
// Creates an Image for the video frame stored in aVideoSample.
|
||||
virtual HRESULT CopyToImage(IMFSample* aVideoSample,
|
||||
const nsIntSize& aSize,
|
||||
const nsIntRect& aRegion,
|
||||
layers::ImageContainer* aContainer,
|
||||
layers::Image** aOutImage) = 0;
|
||||
|
||||
|
@ -791,7 +791,7 @@ WMFReader::CreateD3DVideoFrame(IMFSample* aSample,
|
||||
|
||||
nsRefPtr<Image> image;
|
||||
hr = mDXVA2Manager->CopyToImage(aSample,
|
||||
nsIntSize(mPictureRegion.width, mPictureRegion.height),
|
||||
mPictureRegion,
|
||||
mDecoder->GetImageContainer(),
|
||||
getter_AddRefs(image));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
@ -35,19 +35,15 @@ SVGAnimatedRect::~SVGAnimatedRect()
|
||||
}
|
||||
|
||||
already_AddRefed<SVGIRect>
|
||||
SVGAnimatedRect::GetBaseVal(ErrorResult& aRv)
|
||||
SVGAnimatedRect::GetBaseVal()
|
||||
{
|
||||
nsRefPtr<SVGIRect> rect;
|
||||
aRv = mVal->ToDOMBaseVal(getter_AddRefs(rect), mSVGElement);
|
||||
return rect.forget();
|
||||
return mVal->ToDOMBaseVal(mSVGElement);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGIRect>
|
||||
SVGAnimatedRect::GetAnimVal(ErrorResult& aRv)
|
||||
SVGAnimatedRect::GetAnimVal()
|
||||
{
|
||||
nsRefPtr<SVGIRect> rect;
|
||||
aRv = mVal->ToDOMAnimVal(getter_AddRefs(rect), mSVGElement);
|
||||
return rect.forget();
|
||||
return mVal->ToDOMAnimVal(mSVGElement);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -37,9 +37,9 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<SVGIRect> GetBaseVal(ErrorResult& aRv);
|
||||
already_AddRefed<SVGIRect> GetBaseVal();
|
||||
|
||||
already_AddRefed<SVGIRect> GetAnimVal(ErrorResult& aRv);
|
||||
already_AddRefed<SVGIRect> GetAnimVal();
|
||||
|
||||
private:
|
||||
nsSVGViewBox* mVal; // kept alive because it belongs to content
|
||||
|
@ -109,9 +109,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement)
|
||||
already_AddRefed<SVGAnimatedRect>
|
||||
SVGMarkerElement::ViewBox()
|
||||
{
|
||||
nsRefPtr<SVGAnimatedRect> rect;
|
||||
mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
|
||||
return rect.forget();
|
||||
return mViewBox.ToSVGAnimatedRect(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
|
@ -67,9 +67,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPatternElement)
|
||||
already_AddRefed<SVGAnimatedRect>
|
||||
SVGPatternElement::ViewBox()
|
||||
{
|
||||
nsRefPtr<SVGAnimatedRect> rect;
|
||||
mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
|
||||
return rect.forget();
|
||||
return mViewBox.ToSVGAnimatedRect(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
|
@ -445,9 +445,7 @@ SVGSVGElement::GetElementById(const nsAString& elementId, ErrorResult& rv)
|
||||
already_AddRefed<SVGAnimatedRect>
|
||||
SVGSVGElement::ViewBox()
|
||||
{
|
||||
nsRefPtr<SVGAnimatedRect> rect;
|
||||
mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
|
||||
return rect.forget();
|
||||
return mViewBox.ToSVGAnimatedRect(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
|
@ -43,9 +43,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSymbolElement)
|
||||
already_AddRefed<SVGAnimatedRect>
|
||||
SVGSymbolElement::ViewBox()
|
||||
{
|
||||
nsRefPtr<SVGAnimatedRect> rect;
|
||||
mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
|
||||
return rect.forget();
|
||||
return mViewBox.ToSVGAnimatedRect(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
|
@ -67,9 +67,7 @@ SVGViewElement::SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv)
|
||||
already_AddRefed<SVGAnimatedRect>
|
||||
SVGViewElement::ViewBox()
|
||||
{
|
||||
nsRefPtr<SVGAnimatedRect> box;
|
||||
mViewBox.ToDOMAnimatedRect(getter_AddRefs(box), this);
|
||||
return box.forget();
|
||||
return mViewBox.ToSVGAnimatedRect(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
|
@ -57,7 +57,7 @@ static nsSVGAttrTearoffTable<nsSVGViewBox, nsSVGViewBox::DOMBaseVal>
|
||||
sBaseSVGViewBoxTearoffTable;
|
||||
static nsSVGAttrTearoffTable<nsSVGViewBox, nsSVGViewBox::DOMAnimVal>
|
||||
sAnimSVGViewBoxTearoffTable;
|
||||
nsSVGAttrTearoffTable<nsSVGViewBox, mozilla::dom::SVGAnimatedRect>
|
||||
nsSVGAttrTearoffTable<nsSVGViewBox, dom::SVGAnimatedRect>
|
||||
nsSVGViewBox::sSVGAnimatedRectTearoffTable;
|
||||
|
||||
|
||||
@ -198,9 +198,9 @@ nsSVGViewBox::GetBaseValueString(nsAString& aValue) const
|
||||
aValue.Assign(buf);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGViewBox::ToDOMAnimatedRect(dom::SVGAnimatedRect **aResult,
|
||||
nsSVGElement* aSVGElement)
|
||||
|
||||
already_AddRefed<dom::SVGAnimatedRect>
|
||||
nsSVGViewBox::ToSVGAnimatedRect(nsSVGElement* aSVGElement)
|
||||
{
|
||||
nsRefPtr<dom::SVGAnimatedRect> domAnimatedRect =
|
||||
sSVGAnimatedRectTearoffTable.GetTearoff(this);
|
||||
@ -209,18 +209,16 @@ nsSVGViewBox::ToDOMAnimatedRect(dom::SVGAnimatedRect **aResult,
|
||||
sSVGAnimatedRectTearoffTable.AddTearoff(this, domAnimatedRect);
|
||||
}
|
||||
|
||||
domAnimatedRect.forget(aResult);
|
||||
return NS_OK;
|
||||
return domAnimatedRect.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGViewBox::ToDOMBaseVal(dom::SVGIRect **aResult,
|
||||
nsSVGElement *aSVGElement)
|
||||
already_AddRefed<dom::SVGIRect>
|
||||
nsSVGViewBox::ToDOMBaseVal(nsSVGElement *aSVGElement)
|
||||
{
|
||||
if (!mHasBaseVal || mBaseVal.none) {
|
||||
*aResult = nullptr;
|
||||
return NS_OK;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<DOMBaseVal> domBaseVal =
|
||||
sBaseSVGViewBoxTearoffTable.GetTearoff(this);
|
||||
if (!domBaseVal) {
|
||||
@ -228,8 +226,7 @@ nsSVGViewBox::ToDOMBaseVal(dom::SVGIRect **aResult,
|
||||
sBaseSVGViewBoxTearoffTable.AddTearoff(this, domBaseVal);
|
||||
}
|
||||
|
||||
domBaseVal.forget(aResult);
|
||||
return NS_OK;
|
||||
return domBaseVal.forget();
|
||||
}
|
||||
|
||||
nsSVGViewBox::DOMBaseVal::~DOMBaseVal()
|
||||
@ -237,15 +234,14 @@ nsSVGViewBox::DOMBaseVal::~DOMBaseVal()
|
||||
sBaseSVGViewBoxTearoffTable.RemoveTearoff(mVal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGViewBox::ToDOMAnimVal(dom::SVGIRect **aResult,
|
||||
nsSVGElement *aSVGElement)
|
||||
already_AddRefed<dom::SVGIRect>
|
||||
nsSVGViewBox::ToDOMAnimVal(nsSVGElement *aSVGElement)
|
||||
{
|
||||
if ((mAnimVal && mAnimVal->none) ||
|
||||
(!mAnimVal && (!mHasBaseVal || mBaseVal.none))) {
|
||||
*aResult = nullptr;
|
||||
return NS_OK;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<DOMAnimVal> domAnimVal =
|
||||
sAnimSVGViewBoxTearoffTable.GetTearoff(this);
|
||||
if (!domAnimVal) {
|
||||
@ -253,8 +249,7 @@ nsSVGViewBox::ToDOMAnimVal(dom::SVGIRect **aResult,
|
||||
sAnimSVGViewBoxTearoffTable.AddTearoff(this, domAnimVal);
|
||||
}
|
||||
|
||||
domAnimVal.forget(aResult);
|
||||
return NS_OK;
|
||||
return domAnimVal.forget();
|
||||
}
|
||||
|
||||
nsSVGViewBox::DOMAnimVal::~DOMAnimVal()
|
||||
|
@ -80,12 +80,15 @@ public:
|
||||
bool aDoSetAttr);
|
||||
void GetBaseValueString(nsAString& aValue) const;
|
||||
|
||||
nsresult ToDOMAnimatedRect(mozilla::dom::SVGAnimatedRect **aResult,
|
||||
nsSVGElement *aSVGElement);
|
||||
nsresult ToDOMBaseVal(mozilla::dom::SVGIRect **aResult,
|
||||
nsSVGElement* aSVGElement);
|
||||
nsresult ToDOMAnimVal(mozilla::dom::SVGIRect **aResult,
|
||||
nsSVGElement* aSVGElement);
|
||||
already_AddRefed<mozilla::dom::SVGAnimatedRect>
|
||||
ToSVGAnimatedRect(nsSVGElement *aSVGElement);
|
||||
|
||||
already_AddRefed<mozilla::dom::SVGIRect>
|
||||
ToDOMBaseVal(nsSVGElement* aSVGElement);
|
||||
|
||||
already_AddRefed<mozilla::dom::SVGIRect>
|
||||
ToDOMAnimVal(nsSVGElement* aSVGElement);
|
||||
|
||||
// Returns a new nsISMILAttr object that the caller must delete
|
||||
nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
|
||||
|
||||
|
@ -83,8 +83,8 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding,
|
||||
if (!targetObjectIsNew)
|
||||
return NS_OK;
|
||||
|
||||
JS::Rooted<JSObject*> targetScriptObject(context->GetNativeContext());
|
||||
holder->GetJSObject(targetScriptObject.address());
|
||||
JS::Rooted<JSObject*> targetScriptObject(context->GetNativeContext(),
|
||||
holder->GetJSObject());
|
||||
|
||||
AutoPushJSContext cx(context->GetNativeContext());
|
||||
JSAutoRequest ar(cx);
|
||||
|
@ -264,7 +264,8 @@ nsXBLProtoImplMethod::Write(nsIScriptContext* aContext,
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return XBL_SerializeFunction(aContext, aStream, mJSMethodObject);
|
||||
return XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSMethodObject));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -369,7 +370,8 @@ nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
|
||||
nsresult rv = aStream->Write8(aType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSMethodObject);
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSMethodObject));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -373,12 +373,14 @@ nsXBLProtoImplProperty::Write(nsIScriptContext* aContext,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mJSAttributes & JSPROP_GETTER) {
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSGetterObject);
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSGetterObject));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mJSAttributes & JSPROP_SETTER) {
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSSetterObject);
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSSetterObject));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,10 @@ using namespace mozilla;
|
||||
nsresult
|
||||
XBL_SerializeFunction(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
JSObject* aFunctionObject)
|
||||
JS::Handle<JSObject*> aFunction)
|
||||
{
|
||||
AutoPushJSContext cx(aContext->GetNativeContext());
|
||||
JS::RootedObject function(cx, aFunctionObject);
|
||||
return nsContentUtils::XPConnect()->WriteFunction(aStream, cx, function);
|
||||
return nsContentUtils::XPConnect()->WriteFunction(aStream, cx, aFunction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -79,7 +79,7 @@ PR_STATIC_ASSERT(XBLBinding_Serialize_CustomNamespace >= kNameSpaceID_LastBuilti
|
||||
nsresult
|
||||
XBL_SerializeFunction(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
JSObject* aFunctionObject);
|
||||
JS::Handle<JSObject*> aFunctionObject);
|
||||
|
||||
nsresult
|
||||
XBL_DeserializeFunction(nsIScriptContext* aContext,
|
||||
|
@ -1438,9 +1438,8 @@ txVariable::Convert(nsIVariant *aValue, txAExprResult** aResult)
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
JS::RootedObject jsobj(cx);
|
||||
rv = holder->GetJSObject(jsobj.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JS::RootedObject jsobj(cx, holder->GetJSObject());
|
||||
NS_ENSURE_STATE(jsobj);
|
||||
|
||||
JS::RootedString str(cx, JS_ValueToString(cx, OBJECT_TO_JSVAL(jsobj)));
|
||||
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
|
||||
|
@ -2526,7 +2526,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
bool isChrome = false;
|
||||
mSrcURI->SchemeIs("chrome", &isChrome);
|
||||
if (isChrome)
|
||||
cache->PutScript(mSrcURI, mScriptObject);
|
||||
cache->PutScript(mSrcURI, GetScriptObject());
|
||||
}
|
||||
cache->FinishInputStream(mSrcURI);
|
||||
} else {
|
||||
@ -2628,9 +2628,9 @@ nsXULPrototypeScript::Set(JSScript* aObject)
|
||||
return;
|
||||
}
|
||||
|
||||
mScriptObject = aObject;
|
||||
nsContentUtils::HoldJSObjects(
|
||||
this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
|
||||
mScriptObject = aObject;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -236,9 +236,13 @@ public:
|
||||
|
||||
void Set(JSScript* aObject);
|
||||
|
||||
JSScript *GetScriptObject()
|
||||
// It's safe to return a handle because we trace mScriptObject, no one ever
|
||||
// uses the handle (or the script object) past the point at which the
|
||||
// nsXULPrototypeScript dies, and we can't get memmoved so the
|
||||
// &mScriptObject pointer can't go stale.
|
||||
JS::Handle<JSScript*> GetScriptObject()
|
||||
{
|
||||
return mScriptObject;
|
||||
return JS::Handle<JSScript*>::fromMarkedLocation(&mScriptObject);
|
||||
}
|
||||
|
||||
void TraceScriptObject(JSTracer* aTrc)
|
||||
|
@ -3644,7 +3644,8 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
|
||||
|
||||
nsresult
|
||||
XULDocument::ExecuteScript(nsIScriptContext * aContext, JSScript* aScriptObject)
|
||||
XULDocument::ExecuteScript(nsIScriptContext * aContext,
|
||||
JS::Handle<JSScript*> aScriptObject)
|
||||
{
|
||||
NS_PRECONDITION(aScriptObject != nullptr && aContext != nullptr, "null ptr");
|
||||
if (! aScriptObject || ! aContext)
|
||||
@ -3653,9 +3654,8 @@ XULDocument::ExecuteScript(nsIScriptContext * aContext, JSScript* aScriptObject)
|
||||
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// Execute the precompiled script with the given version
|
||||
JS::Rooted<JSScript*> script(aContext->GetNativeContext(), aScriptObject);
|
||||
JSObject* global = mScriptGlobalObject->GetGlobalJSObject();
|
||||
return aContext->ExecuteScript(script, global);
|
||||
return aContext->ExecuteScript(aScriptObject, global);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -403,7 +403,8 @@ protected:
|
||||
* Execute the precompiled script object scoped by this XUL document's
|
||||
* containing window object, and using its associated script context.
|
||||
*/
|
||||
nsresult ExecuteScript(nsIScriptContext *aContext, JSScript* aScriptObject);
|
||||
nsresult ExecuteScript(nsIScriptContext *aContext,
|
||||
JS::Handle<JSScript*> aScriptObject);
|
||||
|
||||
/**
|
||||
* Helper method for the above that uses aScript to find the appropriate
|
||||
|
@ -205,7 +205,8 @@ nsXULPrototypeCache::GetScript(nsIURI* aURI)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULPrototypeCache::PutScript(nsIURI* aURI, JSScript* aScriptObject)
|
||||
nsXULPrototypeCache::PutScript(nsIURI* aURI,
|
||||
JS::Handle<JSScript*> aScriptObject)
|
||||
{
|
||||
CacheScriptEntry existingEntry;
|
||||
if (mScriptTable.Get(aURI, &existingEntry)) {
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
nsresult PutPrototype(nsXULPrototypeDocument* aDocument);
|
||||
|
||||
JSScript* GetScript(nsIURI* aURI);
|
||||
nsresult PutScript(nsIURI* aURI, JSScript* aScriptObject);
|
||||
nsresult PutScript(nsIURI* aURI, JS::Handle<JSScript*> aScriptObject);
|
||||
|
||||
nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURL) {
|
||||
return mXBLDocTable.GetWeak(aURL);
|
||||
|
@ -1854,8 +1854,16 @@ this.DOMApplicationRegistry = {
|
||||
app.etag = xhr.getResponseHeader("Etag");
|
||||
app.manifestHash = this.computeManifestHash(manifest);
|
||||
debug("at install package got app etag=" + app.etag);
|
||||
Services.obs.notifyObservers(aMm, "webapps-ask-install",
|
||||
JSON.stringify(aData));
|
||||
// We allow bypassing the install confirmation process to facilitate
|
||||
// automation.
|
||||
let prefName = "dom.mozApps.auto_confirm_install";
|
||||
if (Services.prefs.prefHasUserValue(prefName) &&
|
||||
Services.prefs.getBoolPref(prefName)) {
|
||||
this.confirmInstall(aData);
|
||||
} else {
|
||||
Services.obs.notifyObservers(aMm, "webapps-ask-install",
|
||||
JSON.stringify(aData));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -2011,19 +2019,18 @@ this.DOMApplicationRegistry = {
|
||||
offlineCacheObserver: aOfflineCacheObserver
|
||||
}
|
||||
|
||||
let postFirstInstallTask = (function () {
|
||||
// Only executed on install not involving sync.
|
||||
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
||||
this.broadcastMessage("Webapps:Install:Return:OK", aData);
|
||||
Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
|
||||
}).bind(this);
|
||||
// We notify about the successful installation via mgmt.oninstall and the
|
||||
// corresponging DOMRequest.onsuccess event as soon as the app is properly
|
||||
// saved in the registry.
|
||||
if (!aFromSync) {
|
||||
this._saveApps((function() {
|
||||
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
||||
this.broadcastMessage("Webapps:Install:Return:OK", aData);
|
||||
Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
if (!aData.isPackage) {
|
||||
if (!aFromSync) {
|
||||
this._saveApps((function() {
|
||||
postFirstInstallTask();
|
||||
}).bind(this));
|
||||
}
|
||||
this.updateAppHandlers(null, app.manifest, app);
|
||||
if (aInstallSuccessCallback) {
|
||||
aInstallSuccessCallback(manifest);
|
||||
@ -2067,9 +2074,6 @@ this.DOMApplicationRegistry = {
|
||||
manifestURL: appObject.manifestURL,
|
||||
app: app,
|
||||
manifest: aManifest });
|
||||
if (!aFromSync) {
|
||||
postFirstInstallTask();
|
||||
}
|
||||
if (aInstallSuccessCallback) {
|
||||
aInstallSuccessCallback(aManifest);
|
||||
}
|
||||
|
@ -12,14 +12,23 @@ relativesrcdir = @relativesrcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test_app_update.html \
|
||||
file_app.sjs \
|
||||
file_app.template.html \
|
||||
file_hosted_app.template.webapp \
|
||||
file_cached_app.template.webapp \
|
||||
file_cached_app.template.appcache \
|
||||
file_hosted_app.template.webapp \
|
||||
test_app_update.html \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G
|
||||
MOCHITEST_FILES += \
|
||||
file_packaged_app.sjs \
|
||||
file_packaged_app.template.webapp \
|
||||
file_packaged_app.template.html \
|
||||
test_packaged_app_install.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_apps_service.xul \
|
||||
$(NULL)
|
||||
|
@ -40,7 +40,10 @@ function cbError() {
|
||||
function go() {
|
||||
ok(true, "Launched app");
|
||||
var request = window.navigator.mozApps.getSelf();
|
||||
request.onsuccess = function() { var app = request.result; checkApp(app); }
|
||||
request.onsuccess = function() {
|
||||
var app = request.result;
|
||||
checkApp(app);
|
||||
}
|
||||
request.onerror = cbError;
|
||||
}
|
||||
|
||||
|
166
dom/apps/tests/file_packaged_app.sjs
Normal file
166
dom/apps/tests/file_packaged_app.sjs
Normal file
@ -0,0 +1,166 @@
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
|
||||
// From prio.h
|
||||
const PR_RDWR = 0x04;
|
||||
const PR_CREATE_FILE = 0x08;
|
||||
const PR_TRUNCATE = 0x20;
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
var gBasePath = "tests/dom/apps/tests/";
|
||||
var gMiniManifestTemplate = "file_packaged_app.template.webapp";
|
||||
var gAppTemplate = "file_packaged_app.template.html";
|
||||
var gAppName = "appname";
|
||||
var gDevName = "devname";
|
||||
var gDevUrl = "http://dev.url";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
||||
|
||||
var packageSize = ("packageSize" in query) ? query.packageSize : 0;
|
||||
var appName = ("appName" in query) ? query.appName : gAppName;
|
||||
var devName = ("devName" in query) ? query.devName : gDevName;
|
||||
var devUrl = ("devUrl" in query) ? query.devUrl : gDevUrl;
|
||||
|
||||
// If this is a version update, update state, prepare the manifest,
|
||||
// the application package and return.
|
||||
if ("setVersion" in query) {
|
||||
var version = query.setVersion;
|
||||
setState("version", version);
|
||||
|
||||
var packageName = "test_packaged_app_" + version + ".zip";
|
||||
setState("packageName", packageName);
|
||||
var packagePath = "/" + gBasePath + "file_packaged_app.sjs?getPackage=" +
|
||||
packageName;
|
||||
setState("packagePath", packagePath);
|
||||
|
||||
// Create the application package.
|
||||
var zipWriter = Cc["@mozilla.org/zipwriter;1"]
|
||||
.createInstance(Ci.nsIZipWriter);
|
||||
var zipFile = FileUtils.getFile("TmpD", [packageName]);
|
||||
zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
|
||||
// We want to run some tests without the manifest included in the zip.
|
||||
if (version != "0") {
|
||||
var manifestTemplate = gBasePath + gMiniManifestTemplate;
|
||||
var manifest = makeResource(manifestTemplate, version, packagePath,
|
||||
packageSize, appName, devName, devUrl);
|
||||
addZipEntry(zipWriter, manifest, "manifest.webapp");
|
||||
}
|
||||
|
||||
var appTemplate = gBasePath + gAppTemplate;
|
||||
var app = makeResource(appTemplate, version, packagePath, packageSize,
|
||||
appName, devName, devUrl);
|
||||
addZipEntry(zipWriter, app, "index.html");
|
||||
|
||||
zipWriter.close();
|
||||
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the version from server state
|
||||
var version = Number(getState("version"));
|
||||
var packageName = String(getState("packageName"));
|
||||
var packagePath = String(getState("packagePath"));
|
||||
|
||||
var etag = getEtag(request, version);
|
||||
|
||||
if (etagMatches(request, etag)) {
|
||||
dump("Etags Match. Sending 304\n");
|
||||
response.setStatusLine(request.httpVersion, "304", "Not modified");
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Etag", etag, false);
|
||||
|
||||
// Serve the application package corresponding to the requested app version.
|
||||
if ("getPackage" in query) {
|
||||
var resource = readFile(packageName, true);
|
||||
response.setHeader("Content-Type",
|
||||
"Content-Type: application/java-archive", false);
|
||||
response.write(resource);
|
||||
return;
|
||||
}
|
||||
|
||||
// Serve the mini-manifest corresponding to the requested app version.
|
||||
if ("getManifest" in query) {
|
||||
var template = gBasePath + gMiniManifestTemplate;
|
||||
if (!("noManifestContentType" in query)) {
|
||||
response.setHeader("Content-Type",
|
||||
"application/x-web-app-manifest+json", false);
|
||||
}
|
||||
packagePath = "wrongPackagePath" in query ? "" : packagePath;
|
||||
var manifest = makeResource(template, version, packagePath, packageSize,
|
||||
appName, devName, devUrl);
|
||||
response.write(manifest);
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-type", "text-html", false);
|
||||
response.write("KO");
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
||||
|
||||
function getEtag(request, version) {
|
||||
return request.queryString.replace(/&/g, '-').replace(/=/g, '-') +
|
||||
'-' + version;
|
||||
}
|
||||
|
||||
function etagMatches(request, etag) {
|
||||
return request.hasHeader("If-None-Match") &&
|
||||
request.getHeader("If-None-Match") == etag;
|
||||
}
|
||||
|
||||
// File and resources helpers
|
||||
|
||||
function addZipEntry(zipWriter, entry, entryName) {
|
||||
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
|
||||
.createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(entry, entry.length);
|
||||
zipWriter.addEntryStream(entryName, Date.now(),
|
||||
Ci.nsIZipWriter.COMPRESSION_BEST, stream, false);
|
||||
}
|
||||
|
||||
function readFile(path, fromTmp) {
|
||||
var dir = fromTmp ? "TmpD" : "CurWorkD";
|
||||
var file = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get(dir, Ci.nsILocalFile);
|
||||
var fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
var split = path.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fstream.init(file, -1, 0, 0);
|
||||
var data = NetUtil.readInputStreamToString(fstream, fstream.available());
|
||||
fstream.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function makeResource(templatePath, version, packagePath, packageSize,
|
||||
appName, developerName, developerUrl) {
|
||||
var res = readFile(templatePath, false)
|
||||
.replace(/VERSIONTOKEN/g, version)
|
||||
.replace(/PACKAGEPATHTOKEN/g, packagePath)
|
||||
.replace(/PACKAGESIZETOKEN/g, packageSize)
|
||||
.replace(/NAMETOKEN/g, appName)
|
||||
.replace(/DEVELOPERTOKEN/g, developerName)
|
||||
.replace(/DEVELOPERURLTOKEN/g, developerUrl);
|
||||
return res;
|
||||
}
|
7
dom/apps/tests/file_packaged_app.template.html
Normal file
7
dom/apps/tests/file_packaged_app.template.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
App Body. Version: VERSIONTOKEN
|
||||
</body>
|
||||
</html>
|
13
dom/apps/tests/file_packaged_app.template.webapp
Normal file
13
dom/apps/tests/file_packaged_app.template.webapp
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name" : "NAMETOKEN",
|
||||
"version" : "VERSIONTOKEN",
|
||||
"size" : PACKAGESIZETOKEN,
|
||||
"package_path": "PACKAGEPATHTOKEN",
|
||||
"description": "Updated even faster than Firefox, just to annoy slashdotters",
|
||||
"launch_path": "tests/dom/apps/tests/file_packaged_app.sjs",
|
||||
"developer": {
|
||||
"name": "DEVELOPERTOKEN",
|
||||
"url": "DEVELOPERURLTOKEN"
|
||||
},
|
||||
"default_locale": "en-US"
|
||||
}
|
401
dom/apps/tests/test_packaged_app_install.html
Normal file
401
dom/apps/tests/test_packaged_app_install.html
Normal file
@ -0,0 +1,401 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={821589}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {821589} Packaged apps installation and update</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={821589}">Mozilla Bug {821589}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
var gInstallOrigin = "http://mochi.test:8888";
|
||||
var gSJSPath = "tests/dom/apps/tests/file_packaged_app.sjs";
|
||||
var gSJS = "http://test/" + gSJSPath;
|
||||
var gAppName = "appname";
|
||||
var gApp = null;
|
||||
|
||||
var launchableValue = undefined;
|
||||
|
||||
var index = -1;
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("== Tests debug == " + aMsg + "\n");
|
||||
}
|
||||
|
||||
function next() {
|
||||
index += 1;
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
steps[index]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
function go() {
|
||||
next();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.setAllAppsLaunchable(launchableValue);
|
||||
SpecialPowers.removePermission("webapps-manage", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbError(aError) {
|
||||
ok(false, "Error callback invoked " + aError);
|
||||
finish();
|
||||
}
|
||||
|
||||
function setAppVersion(aVersion, aCb) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", function() {
|
||||
is(xhr.responseText, "OK", "setVersion OK");
|
||||
aCb();
|
||||
});
|
||||
xhr.addEventListener("error", cbError);
|
||||
xhr.addEventListener("abort", cbError);
|
||||
xhr.open("GET", gSJS + "?setVersion=" + aVersion, true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function checkAppInstallError(aMiniManifestURL, aExpectedError) {
|
||||
var req = navigator.mozApps.installPackage(aMiniManifestURL);
|
||||
req.onsuccess = function() {
|
||||
ok(false, "We are supposed to throw " + aExpectedError);
|
||||
finish();
|
||||
};
|
||||
req.onerror = function(evt) {
|
||||
var error = evt.target.error.name;
|
||||
if (error == aExpectedError) {
|
||||
ok(true, "Got expected " + aExpectedError);
|
||||
next();
|
||||
} else {
|
||||
ok(false, "Got unexpected " + aError);
|
||||
finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function checkUninstallApp(aApp) {
|
||||
var req = navigator.mozApps.mgmt.uninstall(aApp);
|
||||
req.onsuccess = function() {
|
||||
ok(true, "App uninstalled");
|
||||
aApp.ondownloadsuccess = null;
|
||||
aApp.ondownloaderror = null;
|
||||
aApp.onprogress = null;
|
||||
next();
|
||||
};
|
||||
req.onerror = function(evt) {
|
||||
ok(false, "Got unexpected " + evt.target.error.name);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
function checkAppDownloadError(aMiniManifestURL,
|
||||
aExpectedError,
|
||||
aVersion,
|
||||
aUninstall,
|
||||
aDownloadAvailable,
|
||||
aName) {
|
||||
var req = navigator.mozApps.installPackage(aMiniManifestURL);
|
||||
req.onsuccess = function() {
|
||||
ok(true, "App installed");
|
||||
};
|
||||
req.onerror = function(evt) {
|
||||
ok(false, "Got unexpected " + evt.target.error.name);
|
||||
finish();
|
||||
};
|
||||
|
||||
navigator.mozApps.mgmt.oninstall = function(evt) {
|
||||
var aApp = evt.application;
|
||||
aApp.ondownloaderror = function(evt) {
|
||||
var error = aApp.downloadError.name;
|
||||
if (error == aExpectedError) {
|
||||
ok(true, "Got expected " + aExpectedError);
|
||||
var expected = {
|
||||
name: aName,
|
||||
manifestURL: aMiniManifestURL,
|
||||
installOrigin: gInstallOrigin,
|
||||
progress: 0,
|
||||
installState: "pending",
|
||||
downloadAvailable: aDownloadAvailable,
|
||||
downloading: false,
|
||||
downloadSize: 0,
|
||||
size: 0,
|
||||
readyToApplyDownload: false,
|
||||
};
|
||||
checkAppState(aApp, aVersion, expected, false, aUninstall, next);
|
||||
} else {
|
||||
ok(false, "Got unexpected " + error);
|
||||
finish();
|
||||
}
|
||||
};
|
||||
aApp.ondownloadsuccess = function(evt) {
|
||||
ok(false, "We are supposed to throw " + aExpectedError);
|
||||
finish();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function checkInstalledApp(aMiniManifestURL,
|
||||
aVersion,
|
||||
aExpectedApp,
|
||||
aLaunchable,
|
||||
aCb) {
|
||||
var req = navigator.mozApps.checkInstalled(aMiniManifestURL);
|
||||
req.onsuccess = function(evt) {
|
||||
ok(true, "The app is installed");
|
||||
checkAppState(evt.application, aVersion, aExpectedApp, aLaunchable,
|
||||
false, aCb);
|
||||
};
|
||||
req.onerror = function() {
|
||||
ok(false, "The app is not installed");
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
function checkAppState(aApp,
|
||||
aVersion,
|
||||
aExpectedApp,
|
||||
aLaunchable,
|
||||
aUninstall,
|
||||
aCb) {
|
||||
debug(JSON.stringify(aApp, null, 2));
|
||||
if (aApp.manifest) {
|
||||
debug(JSON.stringify(aApp.manifest, null, 2));
|
||||
}
|
||||
|
||||
if (aExpectedApp.name) {
|
||||
if (aApp.manifest) {
|
||||
is(aApp.manifest.name, aExpectedApp.name, "Check name");
|
||||
}
|
||||
is(aApp.updateManifest.name, aExpectedApp.name, "Check name mini-manifest");
|
||||
}
|
||||
if (aApp.manifest) {
|
||||
is(aApp.manifest.version, aVersion, "Check version");
|
||||
}
|
||||
if (typeof aExpectedApp.size !== "undefined" && aApp.manifest) {
|
||||
is(aApp.manifest.size, aExpectedApp.size, "Check size");
|
||||
}
|
||||
if (aApp.manifest) {
|
||||
is(aApp.manifest.launch_path, gSJSPath, "Check launch path");
|
||||
}
|
||||
if (aExpectedApp.manifestURL) {
|
||||
is(aApp.manifestURL, aExpectedApp.manifestURL, "Check manifestURL");
|
||||
}
|
||||
if (aExpectedApp.installOrigin) {
|
||||
is(aApp.installOrigin, aExpectedApp.installOrigin, "Check installOrigin");
|
||||
}
|
||||
ok(aApp.removable, "Removable app");
|
||||
if (typeof aExpectedApp.progress !== "undefined") {
|
||||
todo(aApp.progress == aExpectedApp.progress, "Check progress");
|
||||
}
|
||||
if (aExpectedApp.installState) {
|
||||
is(aApp.installState, aExpectedApp.installState, "Check installState");
|
||||
}
|
||||
if (typeof aExpectedApp.downloadAvailable !== "undefined") {
|
||||
is(aApp.downloadAvailable, aExpectedApp.downloadAvailable,
|
||||
"Check download available");
|
||||
}
|
||||
if (typeof aExpectedApp.downloading !== "undefined") {
|
||||
is(aApp.downloading, aExpectedApp.downloading, "Check downloading");
|
||||
}
|
||||
if (typeof aExpectedApp.downloadSize !== "undefined") {
|
||||
is(aApp.downloadSize, aExpectedApp.downloadSize, "Check downloadSize");
|
||||
}
|
||||
if (typeof aExpectedApp.readyToApplyDownload !== "undefined") {
|
||||
is(aApp.readyToApplyDownload, aExpectedApp.readyToApplyDownload,
|
||||
"Check readyToApplyDownload");
|
||||
}
|
||||
if (aLaunchable) {
|
||||
if (aUninstall) {
|
||||
checkUninstallApp(aApp);
|
||||
} else if (aCb && typeof aCb === 'function') {
|
||||
aCb();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if app is not launchable.
|
||||
var req = aApp.launch();
|
||||
req.onsuccess = function () {
|
||||
ok(false, "We shouldn't be here");
|
||||
finish();
|
||||
};
|
||||
req.onerror = function() {
|
||||
ok(true, "App is not launchable");
|
||||
if (aUninstall) {
|
||||
checkUninstallApp(aApp);
|
||||
} else if (aCb && typeof aCb === 'function') {
|
||||
aCb();
|
||||
}
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var steps = [
|
||||
function() {
|
||||
// Set up
|
||||
launchableValue = SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.addPermission("webapps-manage", true, document);
|
||||
ok(true, "Set up");
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
ok(true, "autoConfirmAppInstall");
|
||||
SpecialPowers.autoConfirmAppInstall(next);
|
||||
},
|
||||
function() {
|
||||
setAppVersion(0, next);
|
||||
},
|
||||
function() {
|
||||
// Test network error.
|
||||
ok(true, "== TEST == Network error");
|
||||
checkAppInstallError("http://notvalidurl", "NETWORK_ERROR");
|
||||
},
|
||||
function() {
|
||||
// Test wrong mini-manifest content type.
|
||||
ok(true, "== TEST == Not valid mini-manifest content type");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&noManifestContentType=true";
|
||||
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
|
||||
},
|
||||
function() {
|
||||
// Test mini-manifest 'size' value is not number. Bug 839435.
|
||||
ok(true, "== TEST == Size value is not a number");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&packageSize=\"NotANumber\"";
|
||||
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
|
||||
},
|
||||
function() {
|
||||
// Test mini-manifest negative 'size' value. Bug 839435.
|
||||
ok(true, "== TEST == Negative size value");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&packageSize=-1";
|
||||
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
|
||||
},
|
||||
function() {
|
||||
// Test wrong package path
|
||||
ok(true, "== TEST == Installing app with wrong package path");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&wrongPackagePath=true";
|
||||
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
|
||||
},
|
||||
function() {
|
||||
// Test no manifest in zip file.
|
||||
ok(true, "== TEST == No manifest in the zip file");
|
||||
var miniManifestURL = gSJS + "?getManifest=true";
|
||||
checkAppDownloadError(miniManifestURL, "MISSING_MANIFEST", 0, true, true,
|
||||
gAppName);
|
||||
},
|
||||
function() {
|
||||
setAppVersion(1, next);
|
||||
},
|
||||
function() {
|
||||
// Test mini-manifest app name is different from the webapp manifest name.
|
||||
// Bug 844243.
|
||||
ok(true, "== TEST == Mini-manifest app name is different from webapp " +
|
||||
"manifest name");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&appName=arandomname";
|
||||
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
|
||||
"arandomname");
|
||||
},
|
||||
function() {
|
||||
// Test mini-manifest dev name is different from the webapp manifest dev
|
||||
// name.
|
||||
ok (true, "== TEST == Mini-manifest dev name is different from manifest " +
|
||||
"dev name");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&devName=arandomdevname";
|
||||
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
|
||||
gAppName);
|
||||
},
|
||||
function() {
|
||||
// Test mini-manifest dev url is different from the webapp manifest dev
|
||||
// url.
|
||||
ok (true, "== TEST == Mini-manifest dev url is different from manifest " +
|
||||
"dev url");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true" +
|
||||
"&devUrl=arandomdevurl";
|
||||
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
|
||||
gAppName);
|
||||
},
|
||||
function() {
|
||||
setAppVersion(2, next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Install packaged app");
|
||||
var miniManifestURL = gSJS +
|
||||
"?getManifest=true";
|
||||
navigator.mozApps.mgmt.oninstall = function(evt) {
|
||||
ok(true, "Got oninstall event");
|
||||
gApp = evt.application;
|
||||
gApp.ondownloaderror = function() {
|
||||
ok(false, "Download error " + gApp.downloadError.name);
|
||||
finish();
|
||||
};
|
||||
gApp.ondownloadsuccess = function() {
|
||||
ok(true, "App downloaded");
|
||||
var expected = {
|
||||
name: gAppName,
|
||||
manifestURL: miniManifestURL,
|
||||
installOrigin: gInstallOrigin,
|
||||
progress: 0,
|
||||
installState: "installed",
|
||||
downloadAvailable: false,
|
||||
downloading: false,
|
||||
downloadSize: 0,
|
||||
size: 0,
|
||||
readyToApplyDownload: false,
|
||||
};
|
||||
checkAppState(gApp, 2, expected, true, false, next);
|
||||
};
|
||||
};
|
||||
|
||||
var request = navigator.mozApps.installPackage(miniManifestURL);
|
||||
request.onerror = function(evt) {
|
||||
cbError(evt.target.error.name);
|
||||
};
|
||||
request.onsuccess = function() {
|
||||
ok(true, "Application installed");
|
||||
};
|
||||
},
|
||||
function() {
|
||||
ok(true, "all done!\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
addLoadEvent(go);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -893,6 +893,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(LockedFile, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSFontFeatureValuesRule, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
#ifdef MOZ_TIME_MANAGER
|
||||
NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH,
|
||||
@ -2257,6 +2259,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLockedFile)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CSSFontFeatureValuesRule, nsIDOMCSSFontFeatureValuesRule)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
#ifdef MOZ_TIME_MANAGER
|
||||
DOM_CLASSINFO_MAP_BEGIN(MozTimeManager, nsIDOMMozTimeManager)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTimeManager)
|
||||
@ -2643,8 +2649,8 @@ nsDOMClassInfo::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
nsresult rv;
|
||||
JS::Rooted<JSObject*> real_obj(cx);
|
||||
if (wrapper) {
|
||||
rv = wrapper->GetJSObject(real_obj.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
real_obj = wrapper->GetJSObject();
|
||||
NS_ENSURE_STATE(real_obj);
|
||||
}
|
||||
else {
|
||||
real_obj = obj;
|
||||
@ -3354,8 +3360,7 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
|
||||
} else {
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native);
|
||||
|
||||
JS::Rooted<JSObject*> thisObject(cx);
|
||||
wrappedJS->GetJSObject(thisObject.address());
|
||||
JS::Rooted<JSObject*> thisObject(cx, wrappedJS->GetJSObject());
|
||||
if (!thisObject) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -4100,8 +4105,7 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
|
||||
aProto);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> proto_obj(cx);
|
||||
(*aProto)->GetJSObject(proto_obj.address());
|
||||
JS::Rooted<JSObject*> proto_obj(cx, (*aProto)->GetJSObject());
|
||||
if (!JS_WrapObject(cx, proto_obj.address())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -4143,8 +4147,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> class_obj(cx);
|
||||
holder->GetJSObject(class_obj.address());
|
||||
JS::Rooted<JSObject*> class_obj(cx, holder->GetJSObject());
|
||||
NS_ASSERTION(class_obj, "The return value lied");
|
||||
|
||||
const nsIID *primary_iid = &NS_GET_IID(nsISupports);
|
||||
@ -4421,8 +4424,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
rv = constructor->Install(cx, obj, v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> class_obj(cx);
|
||||
holder->GetJSObject(class_obj.address());
|
||||
JS::Rooted<JSObject*> class_obj(cx, holder->GetJSObject());
|
||||
NS_ASSERTION(class_obj, "The return value lied");
|
||||
|
||||
// ... and define the constants from the DOM interface on that
|
||||
@ -4450,9 +4452,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
getter_AddRefs(proto_holder));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && obj != aWin->GetGlobalJSObject()) {
|
||||
JS::Rooted<JSObject*> dot_prototype(cx);
|
||||
rv = proto_holder->GetJSObject(dot_prototype.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JS::Rooted<JSObject*> dot_prototype(cx, proto_holder->GetJSObject());
|
||||
NS_ENSURE_STATE(dot_prototype);
|
||||
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
@ -4492,9 +4493,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
getter_AddRefs(proto_holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject* dot_prototype;
|
||||
rv = proto_holder->GetJSObject(&dot_prototype);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JSObject* dot_prototype = proto_holder->GetJSObject();
|
||||
NS_ENSURE_STATE(dot_prototype);
|
||||
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
@ -4526,9 +4526,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
rv = constructor->Install(cx, obj, val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject* class_obj;
|
||||
holder->GetJSObject(&class_obj);
|
||||
NS_ASSERTION(class_obj, "Why didn't we get a JSObject?");
|
||||
NS_ASSERTION(holder->GetJSObject(), "Why didn't we get a JSObject?");
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
@ -4873,8 +4871,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Make sure we wrap the location object in the window's scope.
|
||||
JS::Rooted<JSObject*> scope(cx);
|
||||
wrapper->GetJSObject(scope.address());
|
||||
JS::Rooted<JSObject*> scope(cx, wrapper->GetJSObject());
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
@ -5057,8 +5054,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
// defined on our prototype chain. This way we can access this
|
||||
// expando w/o ever getting back into XPConnect.
|
||||
if (flags & JSRESOLVE_ASSIGNING) {
|
||||
JS::Rooted<JSObject*> realObj(cx);
|
||||
wrapper->GetJSObject(realObj.address());
|
||||
JS::Rooted<JSObject*> realObj(cx, wrapper->GetJSObject());
|
||||
|
||||
if (obj == realObj) {
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
@ -5903,13 +5899,7 @@ nsNamedArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
!ObjectIsNativeWrapper(cx, obj)) {
|
||||
|
||||
{
|
||||
JS::Rooted<JSObject*> realObj(cx);
|
||||
|
||||
if (wrapper) {
|
||||
wrapper->GetJSObject(realObj.address());
|
||||
} else {
|
||||
realObj = obj;
|
||||
}
|
||||
JS::Rooted<JSObject*> realObj(cx, wrapper ? wrapper->GetJSObject() : obj);
|
||||
|
||||
JSAutoCompartment ac(cx, realObj);
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
@ -6899,8 +6889,7 @@ nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> realObj(cx);
|
||||
wrapper->GetJSObject(realObj.address());
|
||||
JS::Rooted<JSObject*> realObj(cx, wrapper->GetJSObject());
|
||||
|
||||
JSAutoCompartment ac(cx, realObj);
|
||||
|
||||
|
@ -232,6 +232,8 @@ DOMCI_CLASS(AsyncScrollEventDetail)
|
||||
|
||||
DOMCI_CLASS(LockedFile)
|
||||
|
||||
DOMCI_CLASS(CSSFontFeatureValuesRule)
|
||||
|
||||
#ifdef MOZ_TIME_MANAGER
|
||||
DOMCI_CLASS(MozTimeManager)
|
||||
#endif
|
||||
|
@ -2130,7 +2130,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(jsholder);
|
||||
jsholder->GetJSObject(aNativeGlobal);
|
||||
*aNativeGlobal = jsholder->GetJSObject();
|
||||
jsholder.forget(aHolder);
|
||||
|
||||
// Set the location information for the new global, so that tools like
|
||||
|
@ -343,8 +343,8 @@ public:
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx);
|
||||
if (NS_FAILED(wrappedJS->GetJSObject(obj.address())) || !obj) {
|
||||
JS::Rooted<JSObject*> obj(cx, wrappedJS->GetJSObject());
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -8997,7 +8997,8 @@ def genConstructorBody(descriptor, initCall=""):
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
if (NS_FAILED(implWrapped->GetJSObject(jsImplObj.address()))) {
|
||||
jsImplObj = implWrapped->GetJSObject();
|
||||
if (!jsImplObj) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -218,9 +218,8 @@ IDBFactory::Create(ContentParent* aContentParent,
|
||||
nsresult rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> global(cx);
|
||||
rv = globalHolder->GetJSObject(global.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JS::Rooted<JSObject*> global(cx, globalHolder->GetJSObject());
|
||||
NS_ENSURE_STATE(global);
|
||||
|
||||
// The CreateSandbox call returns a proxy to the actual sandbox object. We
|
||||
// don't need a proxy here.
|
||||
|
@ -52,8 +52,8 @@ ReturnKeyRange(JSContext* aCx,
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> result(aCx);
|
||||
if (NS_FAILED(holder->GetJSObject(result.address()))) {
|
||||
JS::Rooted<JSObject*> result(aCx, holder->GetJSObject());
|
||||
if (!result) {
|
||||
JS_ReportError(aCx, "Couldn't get JSObject from wrapper.");
|
||||
return false;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ interface nsIDOMCSSPrimitiveValue;
|
||||
interface nsIDOMCSSRule;
|
||||
interface nsIDOMCSSRuleList;
|
||||
interface nsIDOMMozCSSKeyframeRule;
|
||||
interface nsIDOMCSSFontFeatureValuesRule;
|
||||
interface nsIDOMCSSStyleSheet;
|
||||
interface nsIDOMCSSStyleDeclaration;
|
||||
interface nsIDOMCounter;
|
||||
|
@ -8,6 +8,7 @@ XPIDL_SOURCES += [
|
||||
'nsIDOMCSSCharsetRule.idl',
|
||||
'nsIDOMCSSConditionRule.idl',
|
||||
'nsIDOMCSSFontFaceRule.idl',
|
||||
'nsIDOMCSSFontFeatureValuesRule.idl',
|
||||
'nsIDOMCSSGroupingRule.idl',
|
||||
'nsIDOMCSSImportRule.idl',
|
||||
'nsIDOMCSSMediaRule.idl',
|
||||
|
48
dom/interfaces/css/nsIDOMCSSFontFeatureValuesRule.idl
Normal file
48
dom/interfaces/css/nsIDOMCSSFontFeatureValuesRule.idl
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* John Daggett <jdaggett@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMCSSRule.idl"
|
||||
|
||||
[scriptable, uuid(f4cb1776-389d-4f52-a4d8-68bea5bd00c1)]
|
||||
interface nsIDOMCSSFontFeatureValuesRule : nsIDOMCSSRule
|
||||
{
|
||||
attribute DOMString fontFamily;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString valueText;
|
||||
// raises(DOMException) on setting
|
||||
};
|
@ -32,6 +32,7 @@ interface nsIDOMCSSRule : nsISupports
|
||||
const unsigned short MOZ_KEYFRAME_RULE = 8;
|
||||
const unsigned short NAMESPACE_RULE = 10;
|
||||
const unsigned short SUPPORTS_RULE = 12;
|
||||
const unsigned short FONT_FEATURE_VALUES_RULE = 14;
|
||||
|
||||
readonly attribute unsigned short type;
|
||||
attribute DOMString cssText;
|
||||
|
@ -1026,7 +1026,7 @@ ContentChild::RecvAsyncMessage(const nsString& aMsg,
|
||||
if (cpm) {
|
||||
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
|
||||
cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
|
||||
aMsg, false, &cloneData, nullptr, nullptr);
|
||||
aMsg, false, &cloneData, JS::NullPtr(), nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -866,7 +866,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
if (ppm) {
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
|
||||
nullptr, nullptr, nullptr);
|
||||
nullptr, JS::NullPtr(), nullptr);
|
||||
}
|
||||
nsCOMPtr<nsIThreadObserver>
|
||||
kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
|
||||
@ -2331,7 +2331,7 @@ ContentParent::RecvSyncMessage(const nsString& aMsg,
|
||||
if (ppm) {
|
||||
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
aMsg, true, &cloneData, nullptr, aRetvals);
|
||||
aMsg, true, &cloneData, JS::NullPtr(), aRetvals);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2344,7 +2344,7 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg,
|
||||
if (ppm) {
|
||||
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
aMsg, false, &cloneData, nullptr, nullptr);
|
||||
aMsg, false, &cloneData, JS::NullPtr(), nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1436,7 +1436,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
|
||||
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
|
||||
aMessageName, false, &cloneData, nullptr, nullptr);
|
||||
aMessageName, false, &cloneData, JS::NullPtr(), nullptr);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1974,7 +1974,7 @@ TabChild::RecvAsyncMessage(const nsString& aMessage,
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
|
||||
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
|
||||
aMessage, false, &cloneData, nullptr, nullptr);
|
||||
aMessage, false, &cloneData, JS::NullPtr(), nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1102,7 +1102,7 @@ TabParent::ReceiveMessage(const nsString& aMessage,
|
||||
uint32_t len = 0; //TODO: obtain a real value in bug 572685
|
||||
// Because we want JS messages to have always the same properties,
|
||||
// create array even if len == 0.
|
||||
JSObject* objectsArray = JS_NewArrayObject(ctx, len, NULL);
|
||||
JS::Rooted<JSObject*> objectsArray(ctx, JS_NewArrayObject(ctx, len, NULL));
|
||||
if (!objectsArray) {
|
||||
return false;
|
||||
}
|
||||
|
@ -115,6 +115,17 @@ PEMQExpectedFeatureValue=Found invalid value for media feature.
|
||||
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
|
||||
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
|
||||
PEAnonBoxNotAlone=Did not expect anonymous box.
|
||||
PEFFVUnexpectedEOF=Unexpected end of @font-feature-values rule.
|
||||
PEFFVBlockStart=Expected opening { of @font-feature-values rule but found '%1$S'.
|
||||
PEFFVValueSetStart=Expected opening { of feature value set but found '%1$S'.
|
||||
PEFFVNoFamily=Expected font family list for @font-feature-values rule but found '%1$S'.
|
||||
PEFFVUnexpectedBlockEnd=Expected '}' to end @font-feature-values rule but found '%1$S'.
|
||||
PEFFVUnknownFontVariantPropValue=Unknown font-variant property value '%1$S'.
|
||||
PEFFVExpectedIdent=Expected identifier but found '%1$S'.
|
||||
PEFFVExpectedValue=Expected non-negative integer value but found '%1$S'.
|
||||
PEFFVTooManyValues=Too many values for feature type '%1$S'.
|
||||
PEFFVGenericInFamilyList=Family list cannot contain generic font family name.
|
||||
PEFFVValueDefinitionTrailing=Expected end of value definition but found '%1$S'.
|
||||
PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
|
||||
PESupportsConditionStartEOF2='not', '(', or function
|
||||
PESupportsConditionInParensEOF=')'
|
||||
|
@ -1245,8 +1245,7 @@ _getpluginelement(NPP npp)
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_TRUE(holder, nullptr);
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx);
|
||||
holder->GetJSObject(obj.address());
|
||||
JS::Rooted<JSObject*> obj(cx, holder->GetJSObject());
|
||||
NS_ENSURE_TRUE(obj, nullptr);
|
||||
|
||||
return nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
|
||||
|
@ -290,9 +290,8 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
|
||||
// our current compartment. Because our current context doesn't necessarily
|
||||
// subsume that of the sandbox, we want to unwrap and enter the sandbox's
|
||||
// compartment. It's a shame that the APIs here are so clunkly. :-(
|
||||
JS::Rooted<JSObject*> sandboxObj(cx);
|
||||
rv = sandbox->GetJSObject(sandboxObj.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JS::Rooted<JSObject*> sandboxObj(cx, sandbox->GetJSObject());
|
||||
NS_ENSURE_STATE(sandboxObj);
|
||||
sandboxObj = js::UncheckedUnwrap(sandboxObj);
|
||||
JSAutoCompartment ac(cx, sandboxObj);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,8 +11,6 @@
|
||||
*/
|
||||
|
||||
interface SVGAnimatedRect {
|
||||
[GetterThrows]
|
||||
readonly attribute SVGRect? baseVal;
|
||||
[GetterThrows]
|
||||
readonly attribute SVGRect? animVal;
|
||||
};
|
||||
|
@ -57,8 +57,8 @@ nsresult CentralizedAdminPrefManagerInit()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Unwrap, store and root the sandbox.
|
||||
rv = sandbox->GetJSObject(&autoconfigSb);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
autoconfigSb = sandbox->GetJSObject();
|
||||
NS_ENSURE_STATE(autoconfigSb);
|
||||
autoconfigSb = js::UncheckedUnwrap(autoconfigSb);
|
||||
JSAutoCompartment ac(cx, autoconfigSb);
|
||||
if (!JS_AddNamedObjectRoot(cx, &autoconfigSb, "AutoConfig Sandbox"))
|
||||
|
@ -352,6 +352,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
const char *rendererMatchStrings[RendererOther] = {
|
||||
"Adreno 200",
|
||||
"Adreno 205",
|
||||
"Adreno (TM) 205",
|
||||
"Adreno (TM) 320",
|
||||
"PowerVR SGX 530",
|
||||
"PowerVR SGX 540"
|
||||
|
@ -297,7 +297,8 @@ public:
|
||||
enum {
|
||||
RendererAdreno200,
|
||||
RendererAdreno205,
|
||||
RendererAdreno320,
|
||||
RendererAdrenoTM205,
|
||||
RendererAdrenoTM320,
|
||||
RendererSGX530,
|
||||
RendererSGX540,
|
||||
RendererOther
|
||||
|
@ -37,10 +37,11 @@ D3D9SurfaceImage::SetData(const Data& aData)
|
||||
// DXVA surfaces aren't created sharable, so we need to copy the surface
|
||||
// to a sharable texture to that it's accessible to the layer manager's
|
||||
// device.
|
||||
const nsIntRect& region = aData.mRegion;
|
||||
RefPtr<IDirect3DTexture9> texture;
|
||||
HANDLE shareHandle = NULL;
|
||||
hr = device->CreateTexture(desc.Width,
|
||||
desc.Height,
|
||||
hr = device->CreateTexture(region.width,
|
||||
region.height,
|
||||
1,
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_X8R8G8B8,
|
||||
@ -57,7 +58,8 @@ D3D9SurfaceImage::SetData(const Data& aData)
|
||||
// Stash the surface description for later use.
|
||||
textureSurface->GetDesc(&mDesc);
|
||||
|
||||
hr = device->StretchRect(surface, NULL, textureSurface, NULL, D3DTEXF_NONE);
|
||||
RECT src = { region.x, region.y, region.x+region.width, region.y+region.height };
|
||||
hr = device->StretchRect(surface, &src, textureSurface, NULL, D3DTEXF_NONE);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
// Flush the draw command now, so that by the time we come to draw this
|
||||
@ -71,7 +73,7 @@ D3D9SurfaceImage::SetData(const Data& aData)
|
||||
|
||||
mTexture = texture;
|
||||
mShareHandle = shareHandle;
|
||||
mSize = gfxIntSize(aData.mSize.width, aData.mSize.height);
|
||||
mSize = gfxIntSize(region.width, region.height);
|
||||
mQuery = query;
|
||||
|
||||
return S_OK;
|
||||
|
@ -22,10 +22,10 @@ class D3D9SurfaceImage : public Image {
|
||||
public:
|
||||
|
||||
struct Data {
|
||||
Data(IDirect3DSurface9* aSurface, const nsIntSize& aSize)
|
||||
: mSurface(aSurface), mSize(aSize) {}
|
||||
Data(IDirect3DSurface9* aSurface, const nsIntRect& aRegion)
|
||||
: mSurface(aSurface), mRegion(aRegion) {}
|
||||
RefPtr<IDirect3DSurface9> mSurface;
|
||||
nsIntSize mSize;
|
||||
nsIntRect mRegion;
|
||||
};
|
||||
|
||||
D3D9SurfaceImage() : Image(NULL, D3D9_RGB32_TEXTURE), mSize(0, 0) {}
|
||||
|
@ -313,7 +313,6 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
|
||||
c->GetInheritedYScale(),
|
||||
1);
|
||||
}
|
||||
NS_ASSERTION(!aLayer->GetIsFixedPosition(), "Can't animate transforms on fixed-position layers");
|
||||
layerComposite->SetShadowTransform(matrix);
|
||||
layerComposite->SetShadowTransformSetByAnimation(true);
|
||||
break;
|
||||
|
@ -839,6 +839,19 @@ GrallocTextureHostOGL::Unlock()
|
||||
* i.e. before the next time that we will try to acquire a write lock on the same buffer,
|
||||
* because read and write locks on gralloc buffers are mutually exclusive.
|
||||
*/
|
||||
if (mGL->Renderer() == GLContext::RendererAdrenoTM205) {
|
||||
/* XXX This is working around a driver bug exhibited on at least the
|
||||
* Geeksphone Peak, where retargeting to a different EGL image is very
|
||||
* slow. See Bug 869696.
|
||||
*/
|
||||
if (mGLTexture) {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteTextures(1, &mGLTexture);
|
||||
mGLTexture = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mGL->MakeCurrent();
|
||||
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
mGL->fBindTexture(mTextureTarget, mGLTexture);
|
||||
|
@ -11,8 +11,7 @@
|
||||
|
||||
nsFont::nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
|
||||
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
|
||||
nscoord aSize, float aSizeAdjust,
|
||||
const nsString* aLanguageOverride)
|
||||
nscoord aSize)
|
||||
{
|
||||
NS_ASSERTION(aName && IsASCII(nsDependentCString(aName)),
|
||||
"Must only pass ASCII names here");
|
||||
@ -24,16 +23,21 @@ nsFont::nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
|
||||
stretch = aStretch;
|
||||
decorations = aDecoration;
|
||||
size = aSize;
|
||||
sizeAdjust = aSizeAdjust;
|
||||
if (aLanguageOverride) {
|
||||
languageOverride = *aLanguageOverride;
|
||||
}
|
||||
sizeAdjust = 0.0;
|
||||
kerning = NS_FONT_KERNING_AUTO;
|
||||
synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
|
||||
|
||||
variantAlternates = 0;
|
||||
variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
|
||||
variantEastAsian = 0;
|
||||
variantLigatures = 0;
|
||||
variantNumeric = 0;
|
||||
variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
|
||||
}
|
||||
|
||||
nsFont::nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
|
||||
nsFont::nsFont(const nsSubstring& aName, uint8_t aStyle, uint8_t aVariant,
|
||||
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
|
||||
nscoord aSize, float aSizeAdjust,
|
||||
const nsString* aLanguageOverride)
|
||||
nscoord aSize)
|
||||
: name(aName)
|
||||
{
|
||||
style = aStyle;
|
||||
@ -43,10 +47,16 @@ nsFont::nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
|
||||
stretch = aStretch;
|
||||
decorations = aDecoration;
|
||||
size = aSize;
|
||||
sizeAdjust = aSizeAdjust;
|
||||
if (aLanguageOverride) {
|
||||
languageOverride = *aLanguageOverride;
|
||||
}
|
||||
sizeAdjust = 0.0;
|
||||
kerning = NS_FONT_KERNING_AUTO;
|
||||
synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
|
||||
|
||||
variantAlternates = 0;
|
||||
variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
|
||||
variantEastAsian = 0;
|
||||
variantLigatures = 0;
|
||||
variantNumeric = 0;
|
||||
variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
|
||||
}
|
||||
|
||||
nsFont::nsFont(const nsFont& aOther)
|
||||
@ -60,8 +70,18 @@ nsFont::nsFont(const nsFont& aOther)
|
||||
decorations = aOther.decorations;
|
||||
size = aOther.size;
|
||||
sizeAdjust = aOther.sizeAdjust;
|
||||
languageOverride = aOther.languageOverride;
|
||||
kerning = aOther.kerning;
|
||||
synthesis = aOther.synthesis;
|
||||
fontFeatureSettings = aOther.fontFeatureSettings;
|
||||
languageOverride = aOther.languageOverride;
|
||||
variantAlternates = aOther.variantAlternates;
|
||||
variantCaps = aOther.variantCaps;
|
||||
variantEastAsian = aOther.variantEastAsian;
|
||||
variantLigatures = aOther.variantLigatures;
|
||||
variantNumeric = aOther.variantNumeric;
|
||||
variantPosition = aOther.variantPosition;
|
||||
alternateValues = aOther.alternateValues;
|
||||
featureValueLookup = aOther.featureValueLookup;
|
||||
}
|
||||
|
||||
nsFont::nsFont()
|
||||
@ -81,8 +101,18 @@ bool nsFont::BaseEquals(const nsFont& aOther) const
|
||||
(size == aOther.size) &&
|
||||
(sizeAdjust == aOther.sizeAdjust) &&
|
||||
name.Equals(aOther.name, nsCaseInsensitiveStringComparator()) &&
|
||||
(kerning == aOther.kerning) &&
|
||||
(synthesis == aOther.synthesis) &&
|
||||
(fontFeatureSettings == aOther.fontFeatureSettings) &&
|
||||
(languageOverride == aOther.languageOverride) &&
|
||||
(fontFeatureSettings == aOther.fontFeatureSettings)) {
|
||||
(variantAlternates == aOther.variantAlternates) &&
|
||||
(variantCaps == aOther.variantCaps) &&
|
||||
(variantEastAsian == aOther.variantEastAsian) &&
|
||||
(variantLigatures == aOther.variantLigatures) &&
|
||||
(variantNumeric == aOther.variantNumeric) &&
|
||||
(variantPosition == aOther.variantPosition) &&
|
||||
(alternateValues == aOther.alternateValues) &&
|
||||
(featureValueLookup == aOther.featureValueLookup)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -109,16 +139,27 @@ nsFont& nsFont::operator=(const nsFont& aOther)
|
||||
decorations = aOther.decorations;
|
||||
size = aOther.size;
|
||||
sizeAdjust = aOther.sizeAdjust;
|
||||
languageOverride = aOther.languageOverride;
|
||||
kerning = aOther.kerning;
|
||||
synthesis = aOther.synthesis;
|
||||
fontFeatureSettings = aOther.fontFeatureSettings;
|
||||
languageOverride = aOther.languageOverride;
|
||||
variantAlternates = aOther.variantAlternates;
|
||||
variantCaps = aOther.variantCaps;
|
||||
variantEastAsian = aOther.variantEastAsian;
|
||||
variantLigatures = aOther.variantLigatures;
|
||||
variantNumeric = aOther.variantNumeric;
|
||||
variantPosition = aOther.variantPosition;
|
||||
alternateValues = aOther.alternateValues;
|
||||
featureValueLookup = aOther.featureValueLookup;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
|
||||
nsFont::CopyAlternates(const nsFont& aOther)
|
||||
{
|
||||
// simple copy for now, font-variant implementation will expand
|
||||
aStyle->featureSettings.AppendElements(fontFeatureSettings);
|
||||
variantAlternates = aOther.variantAlternates;
|
||||
alternateValues = aOther.alternateValues;
|
||||
featureValueLookup = aOther.featureValueLookup;
|
||||
}
|
||||
|
||||
static bool IsGenericFontFamily(const nsString& aFamily)
|
||||
@ -184,6 +225,199 @@ bool nsFont::EnumerateFamilies(nsFontFamilyEnumFunc aFunc, void* aData) const
|
||||
return true;
|
||||
}
|
||||
|
||||
// mapping from bitflag to font feature tag/value pair
|
||||
//
|
||||
// these need to be kept in sync with the constants listed
|
||||
// in gfxFontConstants.h (e.g. NS_FONT_VARIANT_EAST_ASIAN_JIS78)
|
||||
|
||||
// NS_FONT_VARIANT_EAST_ASIAN_xxx values
|
||||
const gfxFontFeature eastAsianDefaults[] = {
|
||||
{ TRUETYPE_TAG('j','p','7','8'), 1 },
|
||||
{ TRUETYPE_TAG('j','p','8','3'), 1 },
|
||||
{ TRUETYPE_TAG('j','p','9','0'), 1 },
|
||||
{ TRUETYPE_TAG('j','p','0','4'), 1 },
|
||||
{ TRUETYPE_TAG('s','m','p','l'), 1 },
|
||||
{ TRUETYPE_TAG('t','r','a','d'), 1 },
|
||||
{ TRUETYPE_TAG('f','w','i','d'), 1 },
|
||||
{ TRUETYPE_TAG('p','w','i','d'), 1 },
|
||||
{ TRUETYPE_TAG('r','u','b','y'), 1 }
|
||||
};
|
||||
|
||||
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(eastAsianDefaults) ==
|
||||
eFeatureEastAsian_numFeatures);
|
||||
|
||||
// NS_FONT_VARIANT_LIGATURES_xxx values
|
||||
const gfxFontFeature ligDefaults[] = {
|
||||
{ TRUETYPE_TAG('l','i','g','a'), 1 },
|
||||
{ TRUETYPE_TAG('l','i','g','a'), 0 },
|
||||
{ TRUETYPE_TAG('d','l','i','g'), 1 },
|
||||
{ TRUETYPE_TAG('d','l','i','g'), 0 },
|
||||
{ TRUETYPE_TAG('h','l','i','g'), 1 },
|
||||
{ TRUETYPE_TAG('h','l','i','g'), 0 },
|
||||
{ TRUETYPE_TAG('c','a','l','t'), 1 },
|
||||
{ TRUETYPE_TAG('c','a','l','t'), 0 }
|
||||
};
|
||||
|
||||
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(ligDefaults) ==
|
||||
eFeatureLigatures_numFeatures);
|
||||
|
||||
// NS_FONT_VARIANT_NUMERIC_xxx values
|
||||
const gfxFontFeature numericDefaults[] = {
|
||||
{ TRUETYPE_TAG('l','n','u','m'), 1 },
|
||||
{ TRUETYPE_TAG('o','n','u','m'), 1 },
|
||||
{ TRUETYPE_TAG('p','n','u','m'), 1 },
|
||||
{ TRUETYPE_TAG('t','n','u','m'), 1 },
|
||||
{ TRUETYPE_TAG('f','r','a','c'), 1 },
|
||||
{ TRUETYPE_TAG('a','f','r','c'), 1 },
|
||||
{ TRUETYPE_TAG('z','e','r','o'), 1 },
|
||||
{ TRUETYPE_TAG('o','r','d','n'), 1 }
|
||||
};
|
||||
|
||||
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(numericDefaults) ==
|
||||
eFeatureNumeric_numFeatures);
|
||||
|
||||
static void
|
||||
AddFontFeaturesBitmask(uint32_t aValue, uint32_t aMin, uint32_t aMax,
|
||||
const gfxFontFeature aFeatureDefaults[],
|
||||
nsTArray<gfxFontFeature>& aFeaturesOut)
|
||||
|
||||
{
|
||||
uint32_t i, m;
|
||||
|
||||
for (i = 0, m = aMin; m <= aMax; i++, m <<= 1) {
|
||||
if (m & aValue) {
|
||||
const gfxFontFeature& feature = aFeatureDefaults[i];
|
||||
aFeaturesOut.AppendElement(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
|
||||
{
|
||||
// add in font-variant features
|
||||
gfxFontFeature setting;
|
||||
|
||||
// -- kerning
|
||||
setting.mTag = TRUETYPE_TAG('k','e','r','n');
|
||||
switch (kerning) {
|
||||
case NS_FONT_KERNING_NONE:
|
||||
setting.mValue = 0;
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
case NS_FONT_KERNING_NORMAL:
|
||||
setting.mValue = 1;
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
default:
|
||||
// auto case implies use user agent default
|
||||
break;
|
||||
}
|
||||
|
||||
// -- alternates
|
||||
if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_HISTORICAL) {
|
||||
setting.mValue = 1;
|
||||
setting.mTag = TRUETYPE_TAG('h','i','s','t');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
}
|
||||
|
||||
|
||||
// -- copy font-specific alternate info into style
|
||||
// (this will be resolved after font-matching occurs)
|
||||
aStyle->alternateValues.AppendElements(alternateValues);
|
||||
aStyle->featureValueLookup = featureValueLookup;
|
||||
|
||||
// -- caps
|
||||
setting.mValue = 1;
|
||||
switch (variantCaps) {
|
||||
case NS_FONT_VARIANT_CAPS_ALLSMALL:
|
||||
setting.mTag = TRUETYPE_TAG('c','2','s','c');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
// fall through to the small-caps case
|
||||
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
|
||||
setting.mTag = TRUETYPE_TAG('s','m','c','p');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_ALLPETITE:
|
||||
setting.mTag = TRUETYPE_TAG('c','2','p','c');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
// fall through to the petite-caps case
|
||||
case NS_FONT_VARIANT_CAPS_PETITECAPS:
|
||||
setting.mTag = TRUETYPE_TAG('p','c','a','p');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_TITLING:
|
||||
setting.mTag = TRUETYPE_TAG('t','i','t','l');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_UNICASE:
|
||||
setting.mTag = TRUETYPE_TAG('u','n','i','c');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// -- east-asian
|
||||
if (variantEastAsian) {
|
||||
AddFontFeaturesBitmask(variantEastAsian,
|
||||
NS_FONT_VARIANT_EAST_ASIAN_JIS78,
|
||||
NS_FONT_VARIANT_EAST_ASIAN_RUBY,
|
||||
eastAsianDefaults, aStyle->featureSettings);
|
||||
}
|
||||
|
||||
// -- ligatures
|
||||
if (variantLigatures) {
|
||||
AddFontFeaturesBitmask(variantLigatures,
|
||||
NS_FONT_VARIANT_LIGATURES_COMMON,
|
||||
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
|
||||
ligDefaults, aStyle->featureSettings);
|
||||
|
||||
// special case common ligs, which also enable/disable clig
|
||||
if (variantLigatures & NS_FONT_VARIANT_LIGATURES_COMMON) {
|
||||
setting.mTag = TRUETYPE_TAG('c','l','i','g');
|
||||
setting.mValue = 1;
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
} else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NO_COMMON) {
|
||||
setting.mTag = TRUETYPE_TAG('c','l','i','g');
|
||||
setting.mValue = 0;
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
}
|
||||
}
|
||||
|
||||
// -- numeric
|
||||
if (variantNumeric) {
|
||||
AddFontFeaturesBitmask(variantNumeric,
|
||||
NS_FONT_VARIANT_NUMERIC_LINING,
|
||||
NS_FONT_VARIANT_NUMERIC_ORDINAL,
|
||||
numericDefaults, aStyle->featureSettings);
|
||||
}
|
||||
|
||||
// -- position
|
||||
setting.mTag = 0;
|
||||
setting.mValue = 1;
|
||||
switch (variantPosition) {
|
||||
case NS_FONT_VARIANT_POSITION_SUPER:
|
||||
setting.mTag = TRUETYPE_TAG('s','u','p','s');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_POSITION_SUB:
|
||||
setting.mTag = TRUETYPE_TAG('s','u','b','s');
|
||||
aStyle->featureSettings.AppendElement(setting);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// add in features from font-feature-settings
|
||||
aStyle->featureSettings.AppendElements(fontFeatureSettings);
|
||||
}
|
||||
|
||||
static bool FontEnumCallback(const nsString& aFamily, bool aGeneric, void *aData)
|
||||
{
|
||||
*((nsString*)aData) = aFamily;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "gfxFontFeatures.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
// XXX we need a method to enumerate all of the possible fonts on the
|
||||
// system across family, weight, style, size, etc. But not here!
|
||||
@ -50,6 +51,22 @@ struct NS_GFX nsFont {
|
||||
// The variant of the font (normal, small-caps)
|
||||
uint8_t variant;
|
||||
|
||||
// Variant subproperties
|
||||
// (currently -moz- versions, will replace variant above eventually)
|
||||
uint8_t variantCaps;
|
||||
uint8_t variantLigatures;
|
||||
uint8_t variantNumeric;
|
||||
uint8_t variantPosition;
|
||||
|
||||
uint16_t variantEastAsian;
|
||||
|
||||
// Some font-variant-alternates property values require
|
||||
// font-specific settings defined via @font-feature-values rules.
|
||||
// These are resolved *after* font matching occurs.
|
||||
|
||||
// -- bitmask for both enumerated and functional propvals
|
||||
uint16_t variantAlternates;
|
||||
|
||||
// The decorations on the font (underline, overline,
|
||||
// line-through). The decorations can be binary or'd together.
|
||||
uint8_t decorations;
|
||||
@ -70,6 +87,12 @@ struct NS_GFX nsFont {
|
||||
// needs to be done.
|
||||
float sizeAdjust;
|
||||
|
||||
// -- list of value tags for font-specific alternate features
|
||||
nsTArray<gfxAlternateValue> alternateValues;
|
||||
|
||||
// -- object used to look these up once the font is matched
|
||||
nsRefPtr<gfxFontFeatureValueSet> featureValueLookup;
|
||||
|
||||
// Font features from CSS font-feature-settings
|
||||
nsTArray<gfxFontFeature> fontFeatureSettings;
|
||||
|
||||
@ -78,17 +101,21 @@ struct NS_GFX nsFont {
|
||||
// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
|
||||
nsString languageOverride;
|
||||
|
||||
// Kerning
|
||||
uint8_t kerning;
|
||||
|
||||
// Synthesis setting, controls use of fake bolding/italics
|
||||
uint8_t synthesis;
|
||||
|
||||
// Initialize the font struct with an ASCII name
|
||||
nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
|
||||
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
|
||||
nscoord aSize, float aSizeAdjust=0.0f,
|
||||
const nsString* aLanguageOverride = nullptr);
|
||||
nscoord aSize);
|
||||
|
||||
// Initialize the font struct with a (potentially) unicode name
|
||||
nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
|
||||
nsFont(const nsSubstring& aName, uint8_t aStyle, uint8_t aVariant,
|
||||
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
|
||||
nscoord aSize, float aSizeAdjust=0.0f,
|
||||
const nsString* aLanguageOverride = nullptr);
|
||||
nscoord aSize);
|
||||
|
||||
// Make a copy of the given font
|
||||
nsFont(const nsFont& aFont);
|
||||
@ -106,6 +133,8 @@ struct NS_GFX nsFont {
|
||||
|
||||
nsFont& operator=(const nsFont& aOther);
|
||||
|
||||
void CopyAlternates(const nsFont& aOther);
|
||||
|
||||
// Add featureSettings into style
|
||||
void AddFontFeaturesToStyle(gfxFontStyle *aStyle) const;
|
||||
|
||||
|
@ -80,7 +80,6 @@ SetupTests()
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
NS_LITERAL_STRING(""),
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
gfxFontStyle style_western_bold_16 (FONT_STYLE_NORMAL,
|
||||
@ -90,7 +89,6 @@ SetupTests()
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
NS_LITERAL_STRING(""),
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
/* Test 0 */
|
||||
|
@ -66,7 +66,6 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
NS_LITERAL_STRING(""),
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nullptr);
|
||||
|
@ -124,7 +124,6 @@ main (int argc, char **argv) {
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
NS_LITERAL_STRING(""),
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup =
|
||||
|
@ -34,6 +34,7 @@ CPPSRCS = \
|
||||
gfxDrawable.cpp \
|
||||
gfxImageSurface.cpp \
|
||||
gfxFont.cpp \
|
||||
gfxFontFeatures.cpp \
|
||||
gfxFontMissingGlyphs.cpp \
|
||||
gfxFontTest.cpp \
|
||||
gfxFontUtils.cpp \
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include "nsIWindowsRegKey.h"
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
|
||||
@ -264,8 +266,8 @@ UsingArabicOrHebrewScriptSystemLocale()
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t> &aBuffer)
|
||||
gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t> &aBuffer)
|
||||
{
|
||||
gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList();
|
||||
|
||||
@ -301,12 +303,8 @@ gfxDWriteFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
nsresult rv;
|
||||
nsRefPtr<IDWriteFontFace> fontFace;
|
||||
|
||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
nsresult rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -315,29 +313,83 @@ gfxDWriteFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
hr = fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
|
||||
HRESULT hr =
|
||||
fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag),
|
||||
(const void**)&tableData, &len,
|
||||
&tableContext, &exists);
|
||||
if (FAILED(hr) || !exists) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!aBuffer.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (aBuffer.SetLength(len)) {
|
||||
memcpy(aBuffer.Elements(), tableData, len);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(aBuffer.Elements(), tableData, len);
|
||||
|
||||
if (tableContext) {
|
||||
fontFace->ReleaseFontTable(&tableContext);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Access to font tables packaged in hb_blob_t form
|
||||
|
||||
// object attached to the Harfbuzz blob, used to release
|
||||
// the table when the blob is destroyed
|
||||
class FontTableRec {
|
||||
public:
|
||||
FontTableRec(IDWriteFontFace *aFontFace, void *aContext)
|
||||
: mFontFace(aFontFace), mContext(aContext)
|
||||
{ }
|
||||
|
||||
~FontTableRec() {
|
||||
mFontFace->ReleaseFontTable(mContext);
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFontFace *mFontFace;
|
||||
void *mContext;
|
||||
};
|
||||
|
||||
static void
|
||||
DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
FontTableRec *ftr = static_cast<FontTableRec*>(aUserData);
|
||||
delete ftr;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxDWriteFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
// try to avoid potentially expensive DWrite call if we haven't actually
|
||||
// created the font face yet, by using the gfxFontEntry method that will
|
||||
// use CopyFontTable and then cache the data
|
||||
if (!mFontFace) {
|
||||
return gfxFontEntry::GetFontTable(aTag);
|
||||
}
|
||||
|
||||
const void *data;
|
||||
UINT32 size;
|
||||
void *context;
|
||||
BOOL exists;
|
||||
HRESULT hr = mFontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTag),
|
||||
&data, &size, &context, &exists);
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
FontTableRec *ftr = new FontTableRec(mFontFace, context);
|
||||
return hb_blob_create(static_cast<const char*>(data), size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
ftr, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::ReadCMAP()
|
||||
{
|
||||
HRESULT hr;
|
||||
nsresult rv;
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
@ -347,47 +399,17 @@ gfxDWriteFontEntry::ReadCMAP()
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
// if loading via GDI, just use GetFontTable
|
||||
if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) {
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
} else {
|
||||
// loading using dwrite, don't use GetFontTable to avoid copy
|
||||
nsRefPtr<IDWriteFontFace> fontFace;
|
||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
const uint32_t kCmapTag = DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p');
|
||||
uint8_t *tableData;
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
hr = fontFace->TryGetFontTable(kCmapTag, (const void**)&tableData,
|
||||
&len, &tableContext, &exists);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
bool isSymbol = fontFace->IsSymbolFont();
|
||||
bool isUnicode = true;
|
||||
if (exists) {
|
||||
rv = gfxFontUtils::ReadCMAP(tableData, len, *charmap,
|
||||
mUVSOffset, isUnicode,
|
||||
isSymbol);
|
||||
}
|
||||
fontFace->ReleaseFontTable(tableContext);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
uint32_t cmapLen;
|
||||
const uint8_t* cmapData =
|
||||
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
|
||||
&cmapLen));
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
@ -426,52 +448,60 @@ nsresult
|
||||
gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace,
|
||||
DWRITE_FONT_SIMULATIONS aSimulations)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (mFont) {
|
||||
hr = mFont->CreateFontFace(aFontFace);
|
||||
if (SUCCEEDED(hr) && (aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!((*aFontFace)->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) {
|
||||
// need to replace aFontFace with a version that has the Bold
|
||||
// simulation - unfortunately, DWrite doesn't provide a simple API
|
||||
// for this
|
||||
nsRefPtr<IDWriteFontFace> origFace = (*aFontFace);
|
||||
(*aFontFace)->Release();
|
||||
*aFontFace = NULL;
|
||||
UINT32 numberOfFiles = 0;
|
||||
hr = origFace->GetFiles(&numberOfFiles, NULL);
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoTArray<IDWriteFontFile*,1> files;
|
||||
files.AppendElements(numberOfFiles);
|
||||
hr = origFace->GetFiles(&numberOfFiles, files.Elements());
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// initialize mFontFace if this hasn't been done before
|
||||
if (!mFontFace) {
|
||||
HRESULT hr;
|
||||
if (mFont) {
|
||||
hr = mFont->CreateFontFace(getter_AddRefs(mFontFace));
|
||||
} else if (mFontFile) {
|
||||
IDWriteFontFile *fontFile = mFontFile.get();
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(origFace->GetType(),
|
||||
numberOfFiles,
|
||||
files.Elements(),
|
||||
origFace->GetIndex(),
|
||||
aSimulations,
|
||||
aFontFace);
|
||||
for (UINT32 i = 0; i < numberOfFiles; ++i) {
|
||||
files[i]->Release();
|
||||
}
|
||||
CreateFontFace(mFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
getter_AddRefs(mFontFace));
|
||||
} else {
|
||||
NS_NOTREACHED("invalid font entry");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else if (mFontFile) {
|
||||
IDWriteFontFile *fontFile = mFontFile.get();
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(mFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we need to add a DWrite simulated style
|
||||
if ((aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) {
|
||||
// if so, we need to return not mFontFace itself but a version that
|
||||
// has the Bold simulation - unfortunately, DWrite doesn't provide
|
||||
// a simple API for this
|
||||
UINT32 numberOfFiles = 0;
|
||||
if (FAILED(mFontFace->GetFiles(&numberOfFiles, NULL))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoTArray<IDWriteFontFile*,1> files;
|
||||
files.AppendElements(numberOfFiles);
|
||||
if (FAILED(mFontFace->GetFiles(&numberOfFiles, files.Elements()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(mFontFace->GetType(),
|
||||
numberOfFiles,
|
||||
files.Elements(),
|
||||
mFontFace->GetIndex(),
|
||||
aSimulations,
|
||||
aFontFace);
|
||||
for (UINT32 i = 0; i < numberOfFiles; ++i) {
|
||||
files[i]->Release();
|
||||
}
|
||||
return FAILED(hr) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// no simulation: we can just add a reference to mFontFace and return that
|
||||
*aFontFace = mFontFace;
|
||||
(*aFontFace)->AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -498,7 +528,7 @@ gfxDWriteFontEntry::IsCJKFont()
|
||||
|
||||
const uint32_t kOS2Tag = TRUETYPE_TAG('O','S','/','2');
|
||||
AutoFallibleTArray<uint8_t,128> buffer;
|
||||
if (GetFontTable(kOS2Tag, buffer) != NS_OK) {
|
||||
if (CopyFontTable(kOS2Tag, buffer) != NS_OK) {
|
||||
return mIsCJK;
|
||||
}
|
||||
|
||||
|
@ -143,8 +143,7 @@ public:
|
||||
|
||||
virtual bool IsSymbolFont();
|
||||
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer);
|
||||
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
|
||||
|
||||
nsresult ReadCMAP();
|
||||
|
||||
@ -162,6 +161,9 @@ protected:
|
||||
friend class gfxDWriteFont;
|
||||
friend class gfxDWriteFontList;
|
||||
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
|
||||
bool aNeedsBold);
|
||||
|
||||
@ -177,6 +179,11 @@ protected:
|
||||
*/
|
||||
nsRefPtr<IDWriteFont> mFont;
|
||||
nsRefPtr<IDWriteFontFile> mFontFile;
|
||||
|
||||
// font face corresponding to the mFont/mFontFile *without* any DWrite
|
||||
// style simulations applied
|
||||
nsRefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
DWRITE_FONT_FACE_TYPE mFaceType;
|
||||
|
||||
int8_t mIsCJK;
|
||||
|
@ -19,6 +19,7 @@
|
||||
// Chosen this as to resemble DWrite's own oblique face style.
|
||||
#define OBLIQUE_SKEW_FACTOR 0.3
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
// This is also in gfxGDIFont.cpp. Would be nice to put it somewhere common,
|
||||
@ -229,24 +230,16 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
mMetrics->maxAdvance = mAdjustedSize;
|
||||
|
||||
// try to get the true maxAdvance value from 'hhea'
|
||||
uint8_t *tableData;
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
HRESULT hr =
|
||||
mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('h', 'h', 'e', 'a'),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (exists && len >= sizeof(mozilla::HheaTable)) {
|
||||
const mozilla::HheaTable* hhea =
|
||||
reinterpret_cast<const mozilla::HheaTable*>(tableData);
|
||||
gfxFontEntry::AutoTable hheaTable(GetFontEntry(),
|
||||
TRUETYPE_TAG('h','h','e','a'));
|
||||
if (hheaTable) {
|
||||
uint32_t len;
|
||||
const HheaTable* hhea =
|
||||
reinterpret_cast<const HheaTable*>(hb_blob_get_data(hheaTable, &len));
|
||||
if (len >= sizeof(HheaTable)) {
|
||||
mMetrics->maxAdvance =
|
||||
uint16_t(hhea->advanceWidthMax) * mFUnitsConvFactor;
|
||||
}
|
||||
mFontFace->ReleaseFontTable(tableContext);
|
||||
}
|
||||
|
||||
mMetrics->internalLeading = std::max(mMetrics->maxHeight - mMetrics->emHeight, 0.0);
|
||||
@ -259,22 +252,19 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
// if the table is not available or if using hinted/pixel-snapped widths
|
||||
if (mUseSubpixelPositions) {
|
||||
mMetrics->aveCharWidth = 0;
|
||||
hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('O', 'S', '/', '2'),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (exists && len >= 4) {
|
||||
gfxFontEntry::AutoTable os2Table(GetFontEntry(),
|
||||
TRUETYPE_TAG('O','S','/','2'));
|
||||
if (os2Table) {
|
||||
uint32_t len;
|
||||
const OS2Table* os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (len >= 4) {
|
||||
// Not checking against sizeof(mozilla::OS2Table) here because older
|
||||
// versions of the table have different sizes; we only need the first
|
||||
// two 16-bit fields here.
|
||||
const mozilla::OS2Table* os2 =
|
||||
reinterpret_cast<const mozilla::OS2Table*>(tableData);
|
||||
mMetrics->aveCharWidth =
|
||||
int16_t(os2->xAvgCharWidth) * mFUnitsConvFactor;
|
||||
}
|
||||
mFontFace->ReleaseFontTable(tableContext);
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,60 +591,6 @@ gfxDWriteFont::Measure(gfxTextRun *aTextRun,
|
||||
return metrics;
|
||||
}
|
||||
|
||||
// Access to font tables packaged in hb_blob_t form
|
||||
|
||||
// object attached to the Harfbuzz blob, used to release
|
||||
// the table when the blob is destroyed
|
||||
class FontTableRec {
|
||||
public:
|
||||
FontTableRec(IDWriteFontFace *aFontFace, void *aContext)
|
||||
: mFontFace(aFontFace), mContext(aContext)
|
||||
{ }
|
||||
|
||||
~FontTableRec() {
|
||||
mFontFace->ReleaseFontTable(mContext);
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFontFace *mFontFace;
|
||||
void *mContext;
|
||||
};
|
||||
|
||||
/*static*/ void
|
||||
gfxDWriteFont::DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
FontTableRec *ftr = static_cast<FontTableRec*>(aUserData);
|
||||
delete ftr;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxDWriteFont::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
const void *data;
|
||||
UINT32 size;
|
||||
void *context;
|
||||
BOOL exists;
|
||||
HRESULT hr = mFontFace->TryGetFontTable(mozilla::NativeEndian::swapToBigEndian(aTag),
|
||||
&data, &size, &context, &exists);
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
FontTableRec *ftr = new FontTableRec(mFontFace, context);
|
||||
return hb_blob_create(static_cast<const char*>(data), size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
ftr, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
// for downloaded fonts, there may be layout tables cached in the entry
|
||||
// even though they're absent from the sanitized platform font
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxDWriteFont::ProvidesGlyphWidths()
|
||||
{
|
||||
|
@ -52,10 +52,6 @@ public:
|
||||
gfxContext *aContextForTightBoundingBox,
|
||||
Spacing *aSpacing);
|
||||
|
||||
// override gfxFont table access function to bypass gfxFontEntry cache,
|
||||
// use DWrite API to get direct access to system font data
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
virtual bool ProvidesGlyphWidths();
|
||||
|
||||
virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID);
|
||||
@ -88,8 +84,6 @@ protected:
|
||||
|
||||
gfxFloat MeasureGlyphWidth(uint16_t aGlyph);
|
||||
|
||||
static void DestroyBlobFunc(void* userArg);
|
||||
|
||||
DWRITE_MEASURING_MODE GetMeasuringMode();
|
||||
bool GetForceGDIClassic();
|
||||
|
||||
|
@ -146,22 +146,6 @@ gfxFT2FontBase::GetSpaceGlyph()
|
||||
return mSpaceGlyph;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFT2FontBase::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob))
|
||||
return blob;
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = gfxFT2LockedFace(this).GetFontTable(aTag, buffer);
|
||||
|
||||
// Cache even when there is no table to save having to open the FT_Face
|
||||
// again.
|
||||
return mFontEntry->ShareFontTableAndGetBlob(aTag,
|
||||
haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector)
|
||||
{
|
||||
|
@ -23,7 +23,6 @@ public:
|
||||
cairo_text_extents_t* aExtents);
|
||||
virtual const gfxFont::Metrics& GetMetrics();
|
||||
virtual uint32_t GetSpaceGlyph();
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
virtual bool ProvidesGetGlyph() const { return true; }
|
||||
virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector);
|
||||
virtual bool ProvidesGlyphWidths() { return true; }
|
||||
|
@ -416,7 +416,7 @@ FT2FontEntry::ReadCMAP()
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
||||
nsresult rv = CopyFontTable(TTAG_cmap, buffer);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool unicodeFont;
|
||||
@ -438,8 +438,8 @@ FT2FontEntry::ReadCMAP()
|
||||
}
|
||||
|
||||
nsresult
|
||||
FT2FontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
FT2FontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
AutoFTFace face(this);
|
||||
if (!face) {
|
||||
|
@ -66,7 +66,9 @@ public:
|
||||
cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
|
||||
|
||||
nsresult ReadCMAP();
|
||||
nsresult GetFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
// Check for various kinds of brokenness, and set flags on the entry
|
||||
// accordingly so that we avoid using bad font tables
|
||||
|
@ -318,31 +318,6 @@ gfxFT2LockedFace::GetUVSGlyph(uint32_t aCharCode, uint32_t aVariantSelector)
|
||||
return (*sGetCharVariantPtr)(mFace, aCharCode, aVariantSelector);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFT2LockedFace::GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
if (!mFace || !FT_IS_SFNT(mFace))
|
||||
return false;
|
||||
|
||||
FT_ULong length = 0;
|
||||
// TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
|
||||
FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
|
||||
if (error != 0)
|
||||
return false;
|
||||
|
||||
if (MOZ_UNLIKELY(length > static_cast<FallibleTArray<uint8_t>::size_type>(-1))
|
||||
|| MOZ_UNLIKELY(!aBuffer.SetLength(length)))
|
||||
return false;
|
||||
|
||||
error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
|
||||
if (MOZ_UNLIKELY(error != 0)) {
|
||||
aBuffer.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxFT2LockedFace::GetCharExtents(char aChar, cairo_text_extents_t* aExtents)
|
||||
{
|
||||
|
@ -48,8 +48,6 @@ public:
|
||||
|
||||
void GetMetrics(gfxFont::Metrics* aMetrics, uint32_t* aSpaceGlyph);
|
||||
|
||||
bool GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
// A scale factor for use in converting horizontal metrics from font units
|
||||
// to pixels.
|
||||
gfxFloat XScale()
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
#include "harfbuzz/hb-ot.h"
|
||||
#include "graphite2/Font.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -95,6 +96,12 @@ gfxFontEntry::~gfxFontEntry()
|
||||
gfxUserFontSet::UserFontCache::ForgetFont(this);
|
||||
}
|
||||
|
||||
// By the time the entry is destroyed, all font instances that were
|
||||
// using it should already have been deleted, and so the HB and/or Gr
|
||||
// face objects should have been released.
|
||||
MOZ_ASSERT(!mHBFace);
|
||||
MOZ_ASSERT(!mGrFaceInitialized);
|
||||
|
||||
if (mSVGGlyphs) {
|
||||
delete mSVGGlyphs;
|
||||
}
|
||||
@ -130,17 +137,19 @@ nsresult gfxFontEntry::InitializeUVSMap()
|
||||
|
||||
if (!mUVSData) {
|
||||
const uint32_t kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK) {
|
||||
AutoTable cmapTable(this, kCmapTag);
|
||||
if (!cmapTable) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint8_t* uvsData;
|
||||
unsigned int cmapLen;
|
||||
const char* cmapData = hb_blob_get_data(cmapTable, &cmapLen);
|
||||
nsresult rv = gfxFontUtils::ReadCMAPTableFormat14(
|
||||
buffer.Elements() + mUVSOffset,
|
||||
buffer.Length() - mUVSOffset,
|
||||
uvsData);
|
||||
(const uint8_t*)cmapData + mUVSOffset,
|
||||
cmapLen - mUVSOffset, uvsData);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return rv;
|
||||
@ -173,11 +182,10 @@ nsresult gfxFontEntry::ReadCMAP()
|
||||
nsString
|
||||
gfxFontEntry::RealFaceName()
|
||||
{
|
||||
FallibleTArray<uint8_t> nameTable;
|
||||
nsresult rv = GetFontTable(TRUETYPE_TAG('n','a','m','e'), nameTable);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
AutoTable nameTable(this, TRUETYPE_TAG('n','a','m','e'));
|
||||
if (nameTable) {
|
||||
nsAutoString name;
|
||||
rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
|
||||
nsresult rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return name;
|
||||
}
|
||||
@ -248,16 +256,22 @@ gfxFontEntry::TryGetSVGData()
|
||||
if (!mSVGInitialized) {
|
||||
mSVGInitialized = true;
|
||||
|
||||
FallibleTArray<uint8_t> svgTable;
|
||||
nsresult rv = GetFontTable(TRUETYPE_TAG('S', 'V', 'G', ' '), svgTable);
|
||||
if (NS_FAILED(rv)) {
|
||||
// We don't use AutoTable here because we'll pass ownership of these
|
||||
// blobs to the gfxSVGGlyphs, once we've confirmed the tables exist
|
||||
hb_blob_t *svgTable = GetFontTable(TRUETYPE_TAG('S','V','G',' '));
|
||||
if (!svgTable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FallibleTArray<uint8_t> cmapTable;
|
||||
rv = GetFontTable(TRUETYPE_TAG('c', 'm', 'a', 'p'), cmapTable);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
hb_blob_t *cmapTable = GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
if (!cmapTable) {
|
||||
NS_NOTREACHED("using a font with no cmap!");
|
||||
hb_blob_destroy(svgTable);
|
||||
return false;
|
||||
}
|
||||
|
||||
// gfxSVGGlyphs will hb_blob_destroy() the tables when it is finished
|
||||
// with them.
|
||||
mSVGGlyphs = new gfxSVGGlyphs(svgTable, cmapTable);
|
||||
}
|
||||
|
||||
@ -427,12 +441,136 @@ gfxFontEntry::ShareFontTableAndGetBlob(uint32_t aTag,
|
||||
return entry->ShareTableAndGetBlob(*aBuffer, &mFontTableCache);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
if (GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = NS_SUCCEEDED(CopyFontTable(aTag, buffer));
|
||||
|
||||
return ShareFontTableAndGetBlob(aTag, haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
// callback for HarfBuzz to get a font table (in hb_blob_t form)
|
||||
// from the font entry (passed as aUserData)
|
||||
/*static*/ hb_blob_t *
|
||||
gfxFontEntry::HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData)
|
||||
{
|
||||
gfxFontEntry *fontEntry = static_cast<gfxFontEntry*>(aUserData);
|
||||
|
||||
// bug 589682 - ignore the GDEF table in buggy fonts (applies to
|
||||
// Italic and BoldItalic faces of Times New Roman)
|
||||
if (aTag == TRUETYPE_TAG('G','D','E','F') &&
|
||||
fontEntry->IgnoreGDEF()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// bug 721719 - ignore the GSUB table in buggy fonts (applies to Roboto,
|
||||
// at least on some Android ICS devices; set in gfxFT2FontList.cpp)
|
||||
if (aTag == TRUETYPE_TAG('G','S','U','B') &&
|
||||
fontEntry->IgnoreGSUB()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fontEntry->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxFontEntry::HBFaceDeletedCallback(void *aUserData)
|
||||
{
|
||||
gfxFontEntry *fe = static_cast<gfxFontEntry*>(aUserData);
|
||||
fe->ForgetHBFace();
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::ForgetHBFace()
|
||||
{
|
||||
mHBFace = nullptr;
|
||||
}
|
||||
|
||||
hb_face_t*
|
||||
gfxFontEntry::GetHBFace()
|
||||
{
|
||||
if (!mHBFace) {
|
||||
mHBFace = hb_face_create_for_tables(HBGetTable, this,
|
||||
HBFaceDeletedCallback);
|
||||
return mHBFace;
|
||||
}
|
||||
return hb_face_reference(mHBFace);
|
||||
}
|
||||
|
||||
/*static*/ const void*
|
||||
gfxFontEntry::GrGetTable(const void *aAppFaceHandle, unsigned int aName,
|
||||
size_t *aLen)
|
||||
{
|
||||
gfxFontEntry *fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
hb_blob_t *blob = fontEntry->GetFontTable(aName);
|
||||
if (blob) {
|
||||
unsigned int blobLength;
|
||||
const void *tableData = hb_blob_get_data(blob, &blobLength);
|
||||
fontEntry->mGrTableMap->Put(tableData, blob);
|
||||
*aLen = blobLength;
|
||||
return tableData;
|
||||
}
|
||||
*aLen = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxFontEntry::GrReleaseTable(const void *aAppFaceHandle,
|
||||
const void *aTableBuffer)
|
||||
{
|
||||
gfxFontEntry *fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
void *data;
|
||||
if (fontEntry->mGrTableMap->Get(aTableBuffer, &data)) {
|
||||
fontEntry->mGrTableMap->Remove(aTableBuffer);
|
||||
hb_blob_destroy(static_cast<hb_blob_t*>(data));
|
||||
}
|
||||
}
|
||||
|
||||
gr_face*
|
||||
gfxFontEntry::GetGrFace()
|
||||
{
|
||||
if (!mGrFaceInitialized) {
|
||||
gr_face_ops faceOps = {
|
||||
sizeof(gr_face_ops),
|
||||
GrGetTable,
|
||||
GrReleaseTable
|
||||
};
|
||||
mGrTableMap = new nsDataHashtable<nsPtrHashKey<const void>,void*>;
|
||||
mGrTableMap->Init();
|
||||
mGrFace = gr_make_face_with_ops(this, &faceOps, gr_face_default);
|
||||
mGrFaceInitialized = true;
|
||||
}
|
||||
++mGrFaceRefCnt;
|
||||
return mGrFace;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::ReleaseGrFace(gr_face *aFace)
|
||||
{
|
||||
MOZ_ASSERT(aFace == mGrFace); // sanity-check
|
||||
MOZ_ASSERT(mGrFaceRefCnt > 0);
|
||||
if (--mGrFaceRefCnt == 0) {
|
||||
gr_face_destroy(mGrFace);
|
||||
mGrFace = nullptr;
|
||||
mGrFaceInitialized = false;
|
||||
delete mGrTableMap;
|
||||
mGrTableMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::CheckForGraphiteTables()
|
||||
{
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
mHasGraphiteTables =
|
||||
NS_SUCCEEDED(GetFontTable(TRUETYPE_TAG('S','i','l','f'), buffer));
|
||||
AutoTable silfTable(this, TRUETYPE_TAG('S','i','l','f'));
|
||||
mHasGraphiteTables = silfTable && hb_blob_get_length(silfTable) > 0;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
@ -884,11 +1022,11 @@ gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch *aMatchData)
|
||||
// returns true if other names were found, false otherwise
|
||||
bool
|
||||
gfxFontFamily::ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
|
||||
FallibleTArray<uint8_t>& aNameTable,
|
||||
bool useFullName)
|
||||
hb_blob_t *aNameTable,
|
||||
bool useFullName)
|
||||
{
|
||||
const uint8_t *nameData = aNameTable.Elements();
|
||||
uint32_t dataLength = aNameTable.Length();
|
||||
uint32_t dataLength;
|
||||
const char *nameData = hb_blob_get_data(aNameTable, &dataLength);
|
||||
const gfxFontUtils::NameHeader *nameHeader =
|
||||
reinterpret_cast<const gfxFontUtils::NameHeader*>(nameData);
|
||||
|
||||
@ -947,18 +1085,18 @@ gfxFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
||||
// read in other family names for the first face in the list
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
AutoFallibleTArray<uint8_t,8192> buffer;
|
||||
|
||||
for (i = 0; i < numFonts; ++i) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe)
|
||||
if (!fe) {
|
||||
continue;
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
continue;
|
||||
|
||||
}
|
||||
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
buffer);
|
||||
nameTable);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -972,13 +1110,14 @@ gfxFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
||||
// family names for individual weights (e.g. Hiragino Kaku Gothic Pro W6)
|
||||
for ( ; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe)
|
||||
if (!fe) {
|
||||
continue;
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
continue;
|
||||
|
||||
ReadOtherFamilyNamesForFace(aPlatformFontList, buffer);
|
||||
}
|
||||
ReadOtherFamilyNamesForFace(aPlatformFontList, nameTable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,48 +1134,49 @@ gfxFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
|
||||
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
AutoFallibleTArray<uint8_t,8192> buffer;
|
||||
nsAutoString fullname, psname;
|
||||
|
||||
bool firstTime = true, readAllFaces = false;
|
||||
for (i = 0; i < numFonts; ++i) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe)
|
||||
if (!fe) {
|
||||
continue;
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
continue;
|
||||
|
||||
}
|
||||
if (aNeedFullnamePostscriptNames) {
|
||||
if (gfxFontUtils::ReadCanonicalName(
|
||||
buffer, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK)
|
||||
nameTable, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK)
|
||||
{
|
||||
aPlatformFontList->AddFullname(fe, fullname);
|
||||
}
|
||||
|
||||
if (gfxFontUtils::ReadCanonicalName(
|
||||
buffer, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK)
|
||||
nameTable, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK)
|
||||
{
|
||||
aPlatformFontList->AddPostscriptName(fe, psname);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mOtherFamilyNamesInitialized && (firstTime || readAllFaces)) {
|
||||
bool foundOtherName = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
buffer);
|
||||
if (!mOtherFamilyNamesInitialized && (firstTime || readAllFaces)) {
|
||||
bool foundOtherName = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
nameTable);
|
||||
|
||||
// if the first face has a different name, scan all faces, otherwise
|
||||
// assume the family doesn't have other names
|
||||
if (firstTime && foundOtherName) {
|
||||
mHasOtherFamilyNames = true;
|
||||
readAllFaces = true;
|
||||
}
|
||||
firstTime = false;
|
||||
}
|
||||
// if the first face has a different name, scan all faces, otherwise
|
||||
// assume the family doesn't have other names
|
||||
if (firstTime && foundOtherName) {
|
||||
mHasOtherFamilyNames = true;
|
||||
readAllFaces = true;
|
||||
}
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
// if not reading in any more names, skip other faces
|
||||
if (!readAllFaces && !aNeedFullnamePostscriptNames)
|
||||
break;
|
||||
// if not reading in any more names, skip other faces
|
||||
if (!readAllFaces && !aNeedFullnamePostscriptNames) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mFaceNamesInitialized = true;
|
||||
@ -1367,17 +1507,111 @@ gfxFontCache::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
#define MAX_SSXX_VALUE 99
|
||||
#define MAX_CVXX_VALUE 99
|
||||
|
||||
static void
|
||||
LookupAlternateValues(gfxFontFeatureValueSet *featureLookup,
|
||||
const nsAString& aFamily,
|
||||
const nsTArray<gfxAlternateValue>& altValue,
|
||||
nsTArray<gfxFontFeature>& aFontFeatures)
|
||||
{
|
||||
uint32_t numAlternates = altValue.Length();
|
||||
for (uint32_t i = 0; i < numAlternates; i++) {
|
||||
const gfxAlternateValue& av = altValue.ElementAt(i);
|
||||
nsAutoTArray<uint32_t,4> values;
|
||||
|
||||
// map <family, name, feature> ==> <values>
|
||||
bool found =
|
||||
featureLookup->GetFontFeatureValuesFor(aFamily, av.alternate,
|
||||
av.value, values);
|
||||
uint32_t numValues = values.Length();
|
||||
|
||||
// nothing defined, skip
|
||||
if (!found || numValues == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gfxFontFeature feature;
|
||||
if (av.alternate == NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT) {
|
||||
NS_ASSERTION(numValues <= 2,
|
||||
"too many values allowed for character-variant");
|
||||
// character-variant(12 3) ==> 'cv12' = 3
|
||||
uint32_t nn = values.ElementAt(0);
|
||||
// ignore values greater than 99
|
||||
if (nn == 0 || nn > MAX_CVXX_VALUE) {
|
||||
continue;
|
||||
}
|
||||
feature.mValue = 1;
|
||||
if (numValues > 1) {
|
||||
feature.mValue = values.ElementAt(1);
|
||||
}
|
||||
feature.mTag = HB_TAG('c','v',('0' + nn / 10), ('0' + nn % 10));
|
||||
aFontFeatures.AppendElement(feature);
|
||||
|
||||
} else if (av.alternate == NS_FONT_VARIANT_ALTERNATES_STYLESET) {
|
||||
// styleset(1 2 7) ==> 'ss01' = 1, 'ss02' = 1, 'ss07' = 1
|
||||
feature.mValue = 1;
|
||||
for (uint32_t v = 0; v < numValues; v++) {
|
||||
uint32_t nn = values.ElementAt(v);
|
||||
if (nn == 0 || nn > MAX_SSXX_VALUE) {
|
||||
continue;
|
||||
}
|
||||
feature.mTag = HB_TAG('s','s',('0' + nn / 10), ('0' + nn % 10));
|
||||
aFontFeatures.AppendElement(feature);
|
||||
}
|
||||
|
||||
} else {
|
||||
NS_ASSERTION(numValues == 1,
|
||||
"too many values for font-specific font-variant-alternates");
|
||||
feature.mValue = values.ElementAt(0);
|
||||
|
||||
switch (av.alternate) {
|
||||
case NS_FONT_VARIANT_ALTERNATES_STYLISTIC: // salt
|
||||
feature.mTag = HB_TAG('s','a','l','t');
|
||||
break;
|
||||
case NS_FONT_VARIANT_ALTERNATES_SWASH: // swsh, cswh
|
||||
feature.mTag = HB_TAG('s','w','s','h');
|
||||
aFontFeatures.AppendElement(feature);
|
||||
feature.mTag = HB_TAG('c','s','w','h');
|
||||
break;
|
||||
case NS_FONT_VARIANT_ALTERNATES_ORNAMENTS: // ornm
|
||||
feature.mTag = HB_TAG('o','r','n','m');
|
||||
break;
|
||||
case NS_FONT_VARIANT_ALTERNATES_ANNOTATION: // nalt
|
||||
feature.mTag = HB_TAG('n','a','l','t');
|
||||
break;
|
||||
default:
|
||||
feature.mTag = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ASSERTION(feature.mTag, "unsupported alternate type");
|
||||
if (!feature.mTag) {
|
||||
continue;
|
||||
}
|
||||
aFontFeatures.AppendElement(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
gfxFontShaper::MergeFontFeatures(
|
||||
const nsTArray<gfxFontFeature>& aStyleRuleFeatures,
|
||||
const gfxFontStyle *aStyle,
|
||||
const nsTArray<gfxFontFeature>& aFontFeatures,
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures)
|
||||
{
|
||||
uint32_t numAlts = aStyle->alternateValues.Length();
|
||||
const nsTArray<gfxFontFeature>& styleRuleFeatures =
|
||||
aStyle->featureSettings;
|
||||
|
||||
// bail immediately if nothing to do
|
||||
if (aStyleRuleFeatures.IsEmpty() &&
|
||||
if (styleRuleFeatures.IsEmpty() &&
|
||||
aFontFeatures.IsEmpty() &&
|
||||
!aDisableLigatures) {
|
||||
!aDisableLigatures &&
|
||||
numAlts == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1399,10 +1633,25 @@ gfxFontShaper::MergeFontFeatures(
|
||||
aMergedFeatures.Put(feature.mTag, feature.mValue);
|
||||
}
|
||||
|
||||
// add font-specific feature values from style rules
|
||||
if (aStyle->featureValueLookup && numAlts > 0) {
|
||||
nsAutoTArray<gfxFontFeature,4> featureList;
|
||||
|
||||
// insert list of alternate feature settings
|
||||
LookupAlternateValues(aStyle->featureValueLookup, aFamilyName,
|
||||
aStyle->alternateValues, featureList);
|
||||
|
||||
count = featureList.Length();
|
||||
for (i = 0; i < count; i++) {
|
||||
const gfxFontFeature& feature = featureList.ElementAt(i);
|
||||
aMergedFeatures.Put(feature.mTag, feature.mValue);
|
||||
}
|
||||
}
|
||||
|
||||
// add feature values from style rules
|
||||
count = aStyleRuleFeatures.Length();
|
||||
count = styleRuleFeatures.Length();
|
||||
for (i = 0; i < count; i++) {
|
||||
const gfxFontFeature& feature = aStyleRuleFeatures.ElementAt(i);
|
||||
const gfxFontFeature& feature = styleRuleFeatures.ElementAt(i);
|
||||
aMergedFeatures.Put(feature.mTag, feature.mValue);
|
||||
}
|
||||
|
||||
@ -1465,26 +1714,6 @@ gfxFont::AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData)
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFont::GetFontTable(uint32_t aTag) {
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob))
|
||||
return blob;
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = NS_SUCCEEDED(mFontEntry->GetFontTable(aTag, buffer));
|
||||
|
||||
return mFontEntry->ShareFontTableAndGetBlob(aTag,
|
||||
haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
HBGetTable(hb_face_t *face, hb_tag_t aTag, void *aUserData)
|
||||
{
|
||||
gfxFont* font = static_cast<gfxFont*>(aUserData);
|
||||
return font->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
static bool
|
||||
HasLookupRuleWithGlyphByScript(hb_face_t *aFace, hb_tag_t aTableTag,
|
||||
hb_tag_t aScript, uint16_t aGlyph)
|
||||
@ -1648,7 +1877,7 @@ gfxFont::CheckForFeaturesInvolvingSpace()
|
||||
|
||||
bool result = false;
|
||||
|
||||
hb_face_t *face = hb_face_create_for_tables(HBGetTable, this, nullptr);
|
||||
hb_face_t *face = GetFontEntry()->GetHBFace();
|
||||
|
||||
uint32_t i, len, offset;
|
||||
uint32_t spaceGlyph = GetSpaceGlyph();
|
||||
@ -3183,6 +3412,8 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, bool aNeedTi
|
||||
// Return FALSE if the gfxFontEntry subclass does not
|
||||
// implement GetFontTable(), or for non-sfnt fonts where tables are
|
||||
// not available.
|
||||
// If this returns TRUE without setting the mIsValid flag, then we -did-
|
||||
// apparently find an sfnt, but it was too broken to be used.
|
||||
bool
|
||||
gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
{
|
||||
@ -3193,16 +3424,21 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
const uint32_t kPostTableTag = TRUETYPE_TAG('p','o','s','t');
|
||||
const uint32_t kOS_2TableTag = TRUETYPE_TAG('O','S','/','2');
|
||||
|
||||
uint32_t len;
|
||||
|
||||
if (mFUnitsConvFactor == 0.0) {
|
||||
// If the conversion factor from FUnits is not yet set,
|
||||
// 'head' table is required; otherwise we cannot read any metrics
|
||||
// because we don't know unitsPerEm
|
||||
AutoFallibleTArray<uint8_t,sizeof(HeadTable)> headData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHeadTableTag, headData)) ||
|
||||
headData.Length() < sizeof(HeadTable)) {
|
||||
return false; // no 'head' table -> not an sfnt
|
||||
gfxFontEntry::AutoTable headTable(mFontEntry, kHeadTableTag);
|
||||
if (!headTable) {
|
||||
return false;
|
||||
}
|
||||
const HeadTable* head =
|
||||
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
|
||||
if (len < sizeof(HeadTable)) {
|
||||
return false;
|
||||
}
|
||||
HeadTable *head = reinterpret_cast<HeadTable*>(headData.Elements());
|
||||
uint32_t unitsPerEm = head->unitsPerEm;
|
||||
if (!unitsPerEm) {
|
||||
return true; // is an sfnt, but not valid
|
||||
@ -3211,12 +3447,15 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
}
|
||||
|
||||
// 'hhea' table is required to get vertical extents
|
||||
AutoFallibleTArray<uint8_t,sizeof(HheaTable)> hheaData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHheaTableTag, hheaData)) ||
|
||||
hheaData.Length() < sizeof(HheaTable)) {
|
||||
gfxFontEntry::AutoTable hheaTable(mFontEntry, kHheaTableTag);
|
||||
if (!hheaTable) {
|
||||
return false; // no 'hhea' table -> not an sfnt
|
||||
}
|
||||
HheaTable *hhea = reinterpret_cast<HheaTable*>(hheaData.Elements());
|
||||
const HheaTable* hhea =
|
||||
reinterpret_cast<const HheaTable*>(hb_blob_get_data(hheaTable, &len));
|
||||
if (len < sizeof(HheaTable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#define SET_UNSIGNED(field,src) aMetrics.field = uint16_t(src) * mFUnitsConvFactor
|
||||
#define SET_SIGNED(field,src) aMetrics.field = int16_t(src) * mFUnitsConvFactor
|
||||
@ -3227,27 +3466,26 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
SET_SIGNED(externalLeading, hhea->lineGap);
|
||||
|
||||
// 'post' table is required for underline metrics
|
||||
AutoFallibleTArray<uint8_t,sizeof(PostTable)> postData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kPostTableTag, postData))) {
|
||||
gfxFontEntry::AutoTable postTable(mFontEntry, kPostTableTag);
|
||||
if (!postTable) {
|
||||
return true; // no 'post' table -> sfnt is not valid
|
||||
}
|
||||
if (postData.Length() <
|
||||
offsetof(PostTable, underlineThickness) + sizeof(uint16_t)) {
|
||||
const PostTable *post =
|
||||
reinterpret_cast<const PostTable*>(hb_blob_get_data(postTable, &len));
|
||||
if (len < offsetof(PostTable, underlineThickness) + sizeof(uint16_t)) {
|
||||
return true; // bad post table -> sfnt is not valid
|
||||
}
|
||||
PostTable *post = reinterpret_cast<PostTable*>(postData.Elements());
|
||||
|
||||
SET_SIGNED(underlineOffset, post->underlinePosition);
|
||||
SET_UNSIGNED(underlineSize, post->underlineThickness);
|
||||
|
||||
// 'OS/2' table is optional, if not found we'll estimate xHeight
|
||||
// and aveCharWidth by measuring glyphs
|
||||
AutoFallibleTArray<uint8_t,sizeof(OS2Table)> os2data;
|
||||
if (NS_SUCCEEDED(mFontEntry->GetFontTable(kOS_2TableTag, os2data))) {
|
||||
OS2Table *os2 = reinterpret_cast<OS2Table*>(os2data.Elements());
|
||||
|
||||
if (os2data.Length() >= offsetof(OS2Table, sxHeight) +
|
||||
sizeof(int16_t) &&
|
||||
gfxFontEntry::AutoTable os2Table(mFontEntry, kOS_2TableTag);
|
||||
if (os2Table) {
|
||||
const OS2Table *os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
|
||||
uint16_t(os2->version) >= 2) {
|
||||
// version 2 and later includes the x-height field
|
||||
SET_SIGNED(xHeight, os2->sxHeight);
|
||||
@ -3255,8 +3493,7 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
aMetrics.xHeight = Abs(aMetrics.xHeight);
|
||||
}
|
||||
// this should always be present
|
||||
if (os2data.Length() >= offsetof(OS2Table, yStrikeoutPosition) +
|
||||
sizeof(int16_t)) {
|
||||
if (len >= offsetof(OS2Table, yStrikeoutPosition) + sizeof(int16_t)) {
|
||||
SET_SIGNED(aveCharWidth, os2->xAvgCharWidth);
|
||||
SET_SIGNED(subscriptOffset, os2->ySubscriptYOffset);
|
||||
SET_SIGNED(superscriptOffset, os2->ySuperscriptYOffset);
|
||||
@ -4791,6 +5028,7 @@ gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
|
||||
|
||||
gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
|
||||
language(aStyle.language),
|
||||
featureValueLookup(aStyle.featureValueLookup),
|
||||
size(aStyle.size), sizeAdjust(aStyle.sizeAdjust),
|
||||
languageOverride(aStyle.languageOverride),
|
||||
weight(aStyle.weight), stretch(aStyle.stretch),
|
||||
@ -4798,6 +5036,7 @@ gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
|
||||
style(aStyle.style)
|
||||
{
|
||||
featureSettings.AppendElements(aStyle.featureSettings);
|
||||
alternateValues.AppendElements(aStyle.alternateValues);
|
||||
}
|
||||
|
||||
int8_t
|
||||
|
@ -29,8 +29,10 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <algorithm>
|
||||
#include "nsUnicodeProperties.h"
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
typedef struct gr_face gr_face;
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
@ -50,8 +52,6 @@ class gfxTextObjectPaint;
|
||||
|
||||
class nsILanguageAtomService;
|
||||
|
||||
typedef struct hb_blob_t hb_blob_t;
|
||||
|
||||
#define FONT_MAX_SIZE 2000.0
|
||||
|
||||
#define NO_FONT_LANGUAGE_OVERRIDE 0
|
||||
@ -73,9 +73,23 @@ struct THEBES_API gfxFontStyle {
|
||||
// or inferred from the charset
|
||||
nsRefPtr<nsIAtom> language;
|
||||
|
||||
// Features are composed of (1) features from style rules (2) features
|
||||
// from feature setttings rules and (3) family-specific features. (1) and
|
||||
// (3) are guaranteed to be mutually exclusive
|
||||
|
||||
// custom opentype feature settings
|
||||
nsTArray<gfxFontFeature> featureSettings;
|
||||
|
||||
// Some font-variant property values require font-specific settings
|
||||
// defined via @font-feature-values rules. These are resolved after
|
||||
// font matching occurs.
|
||||
|
||||
// -- list of value tags for specific alternate features
|
||||
nsTArray<gfxAlternateValue> alternateValues;
|
||||
|
||||
// -- object used to look these up once the font is matched
|
||||
nsRefPtr<gfxFontFeatureValueSet> featureValueLookup;
|
||||
|
||||
// The logical size of the font, in pixels
|
||||
gfxFloat size;
|
||||
|
||||
@ -144,7 +158,9 @@ struct THEBES_API gfxFontStyle {
|
||||
(*reinterpret_cast<const uint32_t*>(&sizeAdjust) ==
|
||||
*reinterpret_cast<const uint32_t*>(&other.sizeAdjust)) &&
|
||||
(featureSettings == other.featureSettings) &&
|
||||
(languageOverride == other.languageOverride);
|
||||
(languageOverride == other.languageOverride) &&
|
||||
(alternateValues == other.alternateValues) &&
|
||||
(featureValueLookup == other.featureValueLookup);
|
||||
}
|
||||
|
||||
static void ParseFontFeatureSettings(const nsString& aFeatureString,
|
||||
@ -221,13 +237,17 @@ public:
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mHasSpaceFeaturesSubDefault(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mUVSOffset(0), mUVSData(nullptr),
|
||||
mUserFontData(nullptr),
|
||||
mSVGGlyphs(nullptr),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE)
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
mHBFace(nullptr),
|
||||
mGrFace(nullptr),
|
||||
mGrFaceRefCnt(0)
|
||||
{
|
||||
memset(&mHasSpaceFeaturesSub, 0, sizeof(mHasSpaceFeaturesSub));
|
||||
}
|
||||
@ -306,9 +326,46 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer) {
|
||||
return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
|
||||
}
|
||||
// Access to raw font table data (needed for Harfbuzz):
|
||||
// returns a pointer to data owned by the fontEntry or the OS,
|
||||
// which will remain valid until the blob is destroyed.
|
||||
// The data MUST be treated as read-only; we may be getting a
|
||||
// reference to a shared system font cache.
|
||||
//
|
||||
// The default implementation uses CopyFontTable to get the data
|
||||
// into a byte array, and maintains a cache of loaded tables.
|
||||
//
|
||||
// Subclasses should override this if they can provide more efficient
|
||||
// access than copying table data into our own buffers.
|
||||
//
|
||||
// Get blob that encapsulates a specific font table, or NULL if
|
||||
// the table doesn't exist in the font.
|
||||
//
|
||||
// Caller is responsible to call hb_blob_destroy() on the returned blob
|
||||
// (if non-NULL) when no longer required. For transient access to a table,
|
||||
// use of AutoTable (below) is generally preferred.
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
// Stack-based utility to return a specified table, automatically releasing
|
||||
// the blob when the AutoTable goes out of scope.
|
||||
class AutoTable {
|
||||
public:
|
||||
AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag)
|
||||
{
|
||||
mBlob = aFontEntry->GetFontTable(aTag);
|
||||
}
|
||||
~AutoTable() {
|
||||
if (mBlob) {
|
||||
hb_blob_destroy(mBlob);
|
||||
}
|
||||
}
|
||||
operator hb_blob_t*() const { return mBlob; }
|
||||
private:
|
||||
hb_blob_t* mBlob;
|
||||
// not implemented:
|
||||
AutoTable(const AutoTable&) MOZ_DELETE;
|
||||
AutoTable& operator=(const AutoTable&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
already_AddRefed<gfxFont> FindOrMakeFont(const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold);
|
||||
@ -331,6 +388,21 @@ public:
|
||||
hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
|
||||
FallibleTArray<uint8_t>* aTable);
|
||||
|
||||
// Shaper face accessors:
|
||||
// NOTE that harfbuzz and graphite handle ownership/lifetime of the face
|
||||
// object in completely different ways.
|
||||
|
||||
// Get HarfBuzz face corresponding to this font file.
|
||||
// Caller must release with hb_face_destroy() when finished with it,
|
||||
// and the font entry will be notified via ForgetHBFace.
|
||||
hb_face_t* GetHBFace();
|
||||
virtual void ForgetHBFace();
|
||||
|
||||
// Get Graphite face corresponding to this font file.
|
||||
// Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
|
||||
gr_face* GetGrFace();
|
||||
virtual void ReleaseGrFace(gr_face* aFace);
|
||||
|
||||
// For memory reporting
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
@ -357,6 +429,10 @@ public:
|
||||
bool mHasSpaceFeaturesKerning : 1;
|
||||
bool mHasSpaceFeaturesNonKerning : 1;
|
||||
bool mHasSpaceFeaturesSubDefault : 1;
|
||||
bool mHasGraphiteTables : 1;
|
||||
bool mCheckedForGraphiteTables : 1;
|
||||
bool mHasCmapTable : 1;
|
||||
bool mGrFaceInitialized : 1;
|
||||
|
||||
// bitvector of substitution space features per script
|
||||
uint32_t mHasSpaceFeaturesSub[(MOZ_NUM_SCRIPT_CODES + 31) / 32];
|
||||
@ -364,9 +440,6 @@ public:
|
||||
uint16_t mWeight;
|
||||
int16_t mStretch;
|
||||
|
||||
bool mHasGraphiteTables;
|
||||
bool mCheckedForGraphiteTables;
|
||||
bool mHasCmapTable;
|
||||
nsRefPtr<gfxCharacterMap> mCharacterMap;
|
||||
uint32_t mUVSOffset;
|
||||
nsAutoArrayPtr<uint8_t> mUVSData;
|
||||
@ -399,13 +472,17 @@ protected:
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mHasSpaceFeaturesSubDefault(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mUVSOffset(0), mUVSData(nullptr),
|
||||
mUserFontData(nullptr),
|
||||
mSVGGlyphs(nullptr),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE)
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
mHBFace(nullptr),
|
||||
mGrFace(nullptr),
|
||||
mGrFaceRefCnt(0)
|
||||
{ }
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) {
|
||||
@ -415,8 +492,52 @@ protected:
|
||||
|
||||
virtual void CheckForGraphiteTables();
|
||||
|
||||
private:
|
||||
// Copy a font table into aBuffer.
|
||||
// The caller will be responsible for ownership of the data.
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) {
|
||||
NS_NOTREACHED("forgot to override either GetFontTable or CopyFontTable?");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Shaper-specific face objects, shared by all instantiations of the same
|
||||
// physical font, regardless of size.
|
||||
// Usually, only one of these will actually be created for any given font
|
||||
// entry, depending on the font tables that are present.
|
||||
|
||||
// hb_face_t is refcounted internally, so each shaper that's using it will
|
||||
// bump the ref count when it acquires the face, and "destroy" (release) it
|
||||
// in its destructor. The font entry has only this non-owning reference to
|
||||
// the face; when the face is deleted, it will tell the font entry to forget
|
||||
// it, so that a new face will be created next time it is needed.
|
||||
hb_face_t* mHBFace;
|
||||
|
||||
static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData);
|
||||
|
||||
// Callback that the hb_face will use to tell us when it is being deleted.
|
||||
static void HBFaceDeletedCallback(void *aUserData);
|
||||
|
||||
// gr_face is -not- refcounted, so it will be owned directly by the font
|
||||
// entry, and we'll keep a count of how many references we've handed out;
|
||||
// each shaper is responsible to call ReleaseGrFace on its entry when
|
||||
// finished with it, so that we know when it can be deleted.
|
||||
gr_face* mGrFace;
|
||||
|
||||
// hashtable to map raw table data ptr back to its owning blob, for use by
|
||||
// graphite table-release callback
|
||||
nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap;
|
||||
|
||||
// number of current users of this entry's mGrFace
|
||||
nsrefcnt mGrFaceRefCnt;
|
||||
|
||||
static const void* GrGetTable(const void *aAppFaceHandle,
|
||||
unsigned int aName,
|
||||
size_t *aLen);
|
||||
static void GrReleaseTable(const void *aAppFaceHandle,
|
||||
const void *aTableBuffer);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Font table hashtable, to support GetFontTable for harfbuzz.
|
||||
*
|
||||
@ -676,8 +797,8 @@ protected:
|
||||
bool anItalic, int16_t aStretch);
|
||||
|
||||
bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
|
||||
FallibleTArray<uint8_t>& aNameTable,
|
||||
bool useFullName = false);
|
||||
hb_blob_t *aNameTable,
|
||||
bool useFullName = false);
|
||||
|
||||
// set whether this font family is in "bad" underline offset blacklist.
|
||||
void SetBadUnderlineFonts() {
|
||||
@ -1147,9 +1268,10 @@ public:
|
||||
|
||||
// returns true if features exist in output, false otherwise
|
||||
static bool
|
||||
MergeFontFeatures(const nsTArray<gfxFontFeature>& aStyleRuleFeatures,
|
||||
MergeFontFeatures(const gfxFontStyle *aStyle,
|
||||
const nsTArray<gfxFontFeature>& aFontFeatures,
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures);
|
||||
|
||||
protected:
|
||||
@ -1290,21 +1412,6 @@ public:
|
||||
return mFontEntry->HasGraphiteTables();
|
||||
}
|
||||
|
||||
// Access to raw font table data (needed for Harfbuzz):
|
||||
// returns a pointer to data owned by the fontEntry or the OS,
|
||||
// which will remain valid until released.
|
||||
//
|
||||
// Default implementations forward to the font entry,
|
||||
// and maintain a shared table.
|
||||
//
|
||||
// Subclasses should override this if they can provide more efficient
|
||||
// access than getting tables with mFontEntry->GetFontTable() and sharing
|
||||
// them via the entry.
|
||||
//
|
||||
// Get pointer to a specific font table, or NULL if
|
||||
// the table doesn't exist in the font
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
// Subclasses may choose to look up glyph ids for characters.
|
||||
// If they do not override this, gfxHarfBuzzShaper will fetch the cmap
|
||||
// table and use that.
|
||||
@ -1580,6 +1687,10 @@ public:
|
||||
virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont> GetScaledFont(mozilla::gfx::DrawTarget *aTarget)
|
||||
{ return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this); }
|
||||
|
||||
bool KerningDisabled() {
|
||||
return mKerningSet && !mKerningEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool HasSubstitutionRulesWithSpaceLookups(int32_t aRunScript) {
|
||||
|
@ -30,4 +30,165 @@
|
||||
#define NS_FONT_STRETCH_EXTRA_EXPANDED 3
|
||||
#define NS_FONT_STRETCH_ULTRA_EXPANDED 4
|
||||
|
||||
#define NS_FONT_KERNING_AUTO 0
|
||||
#define NS_FONT_KERNING_NONE 1
|
||||
#define NS_FONT_KERNING_NORMAL 2
|
||||
|
||||
#define NS_FONT_SYNTHESIS_WEIGHT 0x1
|
||||
#define NS_FONT_SYNTHESIS_STYLE 0x2
|
||||
|
||||
enum {
|
||||
eFeatureAlternates_historical,
|
||||
eFeatureAlternates_stylistic,
|
||||
eFeatureAlternates_styleset,
|
||||
eFeatureAlternates_character_variant,
|
||||
eFeatureAlternates_swash,
|
||||
eFeatureAlternates_ornaments,
|
||||
eFeatureAlternates_annotation,
|
||||
|
||||
eFeatureAlternates_numFeatures
|
||||
};
|
||||
|
||||
// alternates - simple enumerated values
|
||||
#define NS_FONT_VARIANT_ALTERNATES_HISTORICAL (1 << eFeatureAlternates_historical)
|
||||
|
||||
// alternates - values that use functional syntax
|
||||
#define NS_FONT_VARIANT_ALTERNATES_STYLISTIC (1 << eFeatureAlternates_stylistic)
|
||||
#define NS_FONT_VARIANT_ALTERNATES_STYLESET (1 << eFeatureAlternates_styleset)
|
||||
#define NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT (1 << eFeatureAlternates_character_variant)
|
||||
#define NS_FONT_VARIANT_ALTERNATES_SWASH (1 << eFeatureAlternates_swash)
|
||||
#define NS_FONT_VARIANT_ALTERNATES_ORNAMENTS (1 << eFeatureAlternates_ornaments)
|
||||
#define NS_FONT_VARIANT_ALTERNATES_ANNOTATION (1 << eFeatureAlternates_annotation)
|
||||
|
||||
#define NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK \
|
||||
NS_FONT_VARIANT_ALTERNATES_HISTORICAL
|
||||
|
||||
#define NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK ( \
|
||||
NS_FONT_VARIANT_ALTERNATES_STYLISTIC | \
|
||||
NS_FONT_VARIANT_ALTERNATES_STYLESET | \
|
||||
NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT | \
|
||||
NS_FONT_VARIANT_ALTERNATES_SWASH | \
|
||||
NS_FONT_VARIANT_ALTERNATES_ORNAMENTS | \
|
||||
NS_FONT_VARIANT_ALTERNATES_ANNOTATION )
|
||||
|
||||
#define NS_FONT_VARIANT_CAPS_NORMAL 0
|
||||
#define NS_FONT_VARIANT_CAPS_SMALLCAPS 1
|
||||
#define NS_FONT_VARIANT_CAPS_ALLSMALL 2
|
||||
#define NS_FONT_VARIANT_CAPS_PETITECAPS 3
|
||||
#define NS_FONT_VARIANT_CAPS_ALLPETITE 4
|
||||
#define NS_FONT_VARIANT_CAPS_TITLING 5
|
||||
#define NS_FONT_VARIANT_CAPS_UNICASE 6
|
||||
|
||||
enum {
|
||||
eFeatureEastAsian_jis78,
|
||||
eFeatureEastAsian_jis83,
|
||||
eFeatureEastAsian_jis90,
|
||||
eFeatureEastAsian_jis04,
|
||||
eFeatureEastAsian_simplified,
|
||||
eFeatureEastAsian_traditional,
|
||||
eFeatureEastAsian_full_width,
|
||||
eFeatureEastAsian_prop_width,
|
||||
eFeatureEastAsian_ruby,
|
||||
|
||||
eFeatureEastAsian_numFeatures
|
||||
};
|
||||
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_JIS78 (1 << eFeatureEastAsian_jis78)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_JIS83 (1 << eFeatureEastAsian_jis83)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_JIS90 (1 << eFeatureEastAsian_jis90)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_JIS04 (1 << eFeatureEastAsian_jis04)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED (1 << eFeatureEastAsian_simplified)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL (1 << eFeatureEastAsian_traditional)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH (1 << eFeatureEastAsian_full_width)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH (1 << eFeatureEastAsian_prop_width)
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_RUBY (1 << eFeatureEastAsian_ruby)
|
||||
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_VARIANT_MASK ( \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_JIS78 | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_JIS83 | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_JIS90 | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_JIS04 | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL )
|
||||
|
||||
#define NS_FONT_VARIANT_EAST_ASIAN_WIDTH_MASK ( \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH | \
|
||||
NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH )
|
||||
|
||||
enum {
|
||||
eFeatureLigatures_common,
|
||||
eFeatureLigatures_no_common,
|
||||
eFeatureLigatures_discretionary,
|
||||
eFeatureLigatures_no_discretionary,
|
||||
eFeatureLigatures_historical,
|
||||
eFeatureLigatures_no_historical,
|
||||
eFeatureLigatures_contextual,
|
||||
eFeatureLigatures_no_contextual,
|
||||
|
||||
eFeatureLigatures_numFeatures
|
||||
};
|
||||
|
||||
#define NS_FONT_VARIANT_LIGATURES_COMMON (1 << eFeatureLigatures_common)
|
||||
#define NS_FONT_VARIANT_LIGATURES_NO_COMMON (1 << eFeatureLigatures_no_common)
|
||||
#define NS_FONT_VARIANT_LIGATURES_DISCRETIONARY (1 << eFeatureLigatures_discretionary)
|
||||
#define NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY (1 << eFeatureLigatures_no_discretionary)
|
||||
#define NS_FONT_VARIANT_LIGATURES_HISTORICAL (1 << eFeatureLigatures_historical)
|
||||
#define NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL (1 << eFeatureLigatures_no_historical)
|
||||
#define NS_FONT_VARIANT_LIGATURES_CONTEXTUAL (1 << eFeatureLigatures_contextual)
|
||||
#define NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL (1 << eFeatureLigatures_no_contextual)
|
||||
|
||||
#define NS_FONT_VARIANT_LIGATURES_COMMON_MASK ( \
|
||||
NS_FONT_VARIANT_LIGATURES_COMMON | \
|
||||
NS_FONT_VARIANT_LIGATURES_NO_COMMON )
|
||||
|
||||
#define NS_FONT_VARIANT_LIGATURES_DISCRETIONARY_MASK ( \
|
||||
NS_FONT_VARIANT_LIGATURES_DISCRETIONARY | \
|
||||
NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY )
|
||||
|
||||
#define NS_FONT_VARIANT_LIGATURES_HISTORICAL_MASK ( \
|
||||
NS_FONT_VARIANT_LIGATURES_HISTORICAL | \
|
||||
NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL )
|
||||
|
||||
#define NS_FONT_VARIANT_LIGATURES_CONTEXTUAL_MASK \
|
||||
NS_FONT_VARIANT_LIGATURES_CONTEXTUAL | \
|
||||
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL
|
||||
|
||||
enum {
|
||||
eFeatureNumeric_lining,
|
||||
eFeatureNumeric_oldstyle,
|
||||
eFeatureNumeric_proportional,
|
||||
eFeatureNumeric_tabular,
|
||||
eFeatureNumeric_diagonal_fractions,
|
||||
eFeatureNumeric_stacked_fractions,
|
||||
eFeatureNumeric_slashedzero,
|
||||
eFeatureNumeric_ordinal,
|
||||
|
||||
eFeatureNumeric_numFeatures
|
||||
};
|
||||
|
||||
#define NS_FONT_VARIANT_NUMERIC_LINING (1 << eFeatureNumeric_lining)
|
||||
#define NS_FONT_VARIANT_NUMERIC_OLDSTYLE (1 << eFeatureNumeric_oldstyle)
|
||||
#define NS_FONT_VARIANT_NUMERIC_PROPORTIONAL (1 << eFeatureNumeric_proportional)
|
||||
#define NS_FONT_VARIANT_NUMERIC_TABULAR (1 << eFeatureNumeric_tabular)
|
||||
#define NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS (1 << eFeatureNumeric_diagonal_fractions)
|
||||
#define NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS (1 << eFeatureNumeric_stacked_fractions)
|
||||
#define NS_FONT_VARIANT_NUMERIC_SLASHZERO (1 << eFeatureNumeric_slashedzero)
|
||||
#define NS_FONT_VARIANT_NUMERIC_ORDINAL (1 << eFeatureNumeric_ordinal)
|
||||
|
||||
#define NS_FONT_VARIANT_NUMERIC_FIGURE_MASK \
|
||||
NS_FONT_VARIANT_NUMERIC_LINING | \
|
||||
NS_FONT_VARIANT_NUMERIC_OLDSTYLE
|
||||
|
||||
#define NS_FONT_VARIANT_NUMERIC_SPACING_MASK \
|
||||
NS_FONT_VARIANT_NUMERIC_PROPORTIONAL | \
|
||||
NS_FONT_VARIANT_NUMERIC_TABULAR
|
||||
|
||||
#define NS_FONT_VARIANT_NUMERIC_FRACTION_MASK \
|
||||
NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS | \
|
||||
NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS
|
||||
|
||||
#define NS_FONT_VARIANT_POSITION_NORMAL 0
|
||||
#define NS_FONT_VARIANT_POSITION_SUPER 1
|
||||
#define NS_FONT_VARIANT_POSITION_SUB 2
|
||||
|
||||
#endif
|
||||
|
81
gfx/thebes/gfxFontFeatures.cpp
Normal file
81
gfx/thebes/gfxFontFeatures.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "gfxFontFeatures.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
gfxFontFeatureValueSet::gfxFontFeatureValueSet()
|
||||
{
|
||||
mFontFeatureValues.Init(10);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFontFeatureValueSet::GetFontFeatureValuesFor(const nsAString& aFamily,
|
||||
uint32_t aVariantProperty,
|
||||
const nsAString& aName,
|
||||
nsTArray<uint32_t>& aValues)
|
||||
{
|
||||
nsAutoString family(aFamily), name(aName);
|
||||
ToLowerCase(family);
|
||||
ToLowerCase(name);
|
||||
FeatureValueHashKey key(family, aVariantProperty, name);
|
||||
|
||||
aValues.Clear();
|
||||
FeatureValueHashEntry *entry = mFontFeatureValues.GetEntry(key);
|
||||
if (entry) {
|
||||
NS_ASSERTION(entry->mValues.Length() > 0,
|
||||
"null array of font feature values");
|
||||
aValues.AppendElements(entry->mValues);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gfxFontFeatureValueSet::AddFontFeatureValues(const nsAString& aFamily,
|
||||
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aValues)
|
||||
{
|
||||
nsAutoString family(aFamily);
|
||||
ToLowerCase(family);
|
||||
|
||||
uint32_t i, numFeatureValues = aValues.Length();
|
||||
for (i = 0; i < numFeatureValues; i++) {
|
||||
const FeatureValues& fv = aValues.ElementAt(i);
|
||||
uint32_t alternate = fv.alternate;
|
||||
uint32_t j, numValues = fv.valuelist.Length();
|
||||
for (j = 0; j < numValues; j++) {
|
||||
const ValueList& v = fv.valuelist.ElementAt(j);
|
||||
nsAutoString name(v.name);
|
||||
ToLowerCase(name);
|
||||
FeatureValueHashKey key(family, alternate, name);
|
||||
FeatureValueHashEntry *entry = mFontFeatureValues.PutEntry(key);
|
||||
entry->mKey = key;
|
||||
entry->mValues = v.featureSelectors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFontFeatureValueSet::FeatureValueHashEntry::KeyEquals(
|
||||
const KeyTypePointer aKey) const
|
||||
{
|
||||
return aKey->mPropVal == mKey.mPropVal &&
|
||||
aKey->mFamily.Equals(mKey.mFamily) &&
|
||||
aKey->mName.Equals(mKey.mName);
|
||||
}
|
||||
|
||||
PLDHashNumber
|
||||
gfxFontFeatureValueSet::FeatureValueHashEntry::HashKey(
|
||||
const KeyTypePointer aKey)
|
||||
{
|
||||
return HashString(aKey->mFamily) + HashString(aKey->mName) +
|
||||
aKey->mPropVal * uint32_t(0xdeadbeef);
|
||||
}
|
||||
|
@ -7,6 +7,11 @@
|
||||
#ifndef GFX_FONT_FEATURES_H
|
||||
#define GFX_FONT_FEATURES_H
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
|
||||
// An OpenType feature tag and value pair
|
||||
struct gfxFontFeature {
|
||||
uint32_t mTag; // see http://www.microsoft.com/typography/otspec/featuretags.htm
|
||||
@ -26,4 +31,95 @@ operator==(const gfxFontFeature& a, const gfxFontFeature& b)
|
||||
return (a.mTag == b.mTag) && (a.mValue == b.mValue);
|
||||
}
|
||||
|
||||
struct gfxAlternateValue {
|
||||
uint32_t alternate; // constants in gfxFontConstants.h
|
||||
nsString value; // string value to be looked up
|
||||
};
|
||||
|
||||
inline bool
|
||||
operator<(const gfxAlternateValue& a, const gfxAlternateValue& b)
|
||||
{
|
||||
return (a.alternate < b.alternate) ||
|
||||
((a.alternate == b.alternate) && (a.value < b.value));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const gfxAlternateValue& a, const gfxAlternateValue& b)
|
||||
{
|
||||
return (a.alternate == b.alternate) && (a.value == b.value);
|
||||
}
|
||||
|
||||
class THEBES_API gfxFontFeatureValueSet {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxFontFeatureValueSet)
|
||||
|
||||
gfxFontFeatureValueSet();
|
||||
virtual ~gfxFontFeatureValueSet() {}
|
||||
|
||||
struct ValueList {
|
||||
ValueList(const nsAString& aName, const nsTArray<uint32_t>& aSelectors)
|
||||
: name(aName), featureSelectors(aSelectors)
|
||||
{}
|
||||
nsString name;
|
||||
nsTArray<uint32_t> featureSelectors;
|
||||
};
|
||||
|
||||
struct FeatureValues {
|
||||
uint32_t alternate;
|
||||
nsTArray<ValueList> valuelist;
|
||||
};
|
||||
|
||||
// returns true if found, false otherwise
|
||||
bool
|
||||
GetFontFeatureValuesFor(const nsAString& aFamily,
|
||||
uint32_t aVariantProperty,
|
||||
const nsAString& aName,
|
||||
nsTArray<uint32_t>& aValues);
|
||||
void
|
||||
AddFontFeatureValues(const nsAString& aFamily,
|
||||
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aValues);
|
||||
|
||||
protected:
|
||||
struct FeatureValueHashKey {
|
||||
nsString mFamily;
|
||||
uint32_t mPropVal;
|
||||
nsString mName;
|
||||
|
||||
FeatureValueHashKey()
|
||||
: mPropVal(0)
|
||||
{ }
|
||||
FeatureValueHashKey(const nsAString& aFamily,
|
||||
uint32_t aPropVal,
|
||||
const nsAString& aName)
|
||||
: mFamily(aFamily), mPropVal(aPropVal), mName(aName)
|
||||
{ }
|
||||
FeatureValueHashKey(const FeatureValueHashKey& aKey)
|
||||
: mFamily(aKey.mFamily), mPropVal(aKey.mPropVal), mName(aKey.mName)
|
||||
{ }
|
||||
};
|
||||
|
||||
class FeatureValueHashEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef const FeatureValueHashKey &KeyType;
|
||||
typedef const FeatureValueHashKey *KeyTypePointer;
|
||||
|
||||
FeatureValueHashEntry(KeyTypePointer aKey) { }
|
||||
FeatureValueHashEntry(const FeatureValueHashEntry& toCopy)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
}
|
||||
~FeatureValueHashEntry() { }
|
||||
|
||||
bool KeyEquals(const KeyTypePointer aKey) const;
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey);
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
FeatureValueHashKey mKey;
|
||||
nsTArray<uint32_t> mValues;
|
||||
};
|
||||
|
||||
nsTHashtable<FeatureValueHashEntry> mFontFeatureValues;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "nsMemory.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
#include "plbase64.h"
|
||||
#include "prlog.h"
|
||||
|
||||
@ -1215,17 +1217,18 @@ gfxFontUtils::GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength,
|
||||
uint32_t len = dirEntry->length;
|
||||
NS_ENSURE_TRUE(aLength > len && aLength - len >= dirEntry->offset,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
FallibleTArray<uint8_t> nameTable;
|
||||
if (!nameTable.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(nameTable.Elements(), aFontData + dirEntry->offset, len);
|
||||
|
||||
return GetFullNameFromTable(nameTable, aFullName);
|
||||
hb_blob_t *nameBlob =
|
||||
hb_blob_create((const char*)aFontData + dirEntry->offset, len,
|
||||
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
|
||||
nsresult rv = GetFullNameFromTable(nameBlob, aFullName);
|
||||
hb_blob_destroy(nameBlob);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::GetFullNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
gfxFontUtils::GetFullNameFromTable(hb_blob_t *aNameTable,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
nsAutoString name;
|
||||
@ -1257,7 +1260,7 @@ gfxFontUtils::GetFullNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::GetFamilyNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
gfxFontUtils::GetFamilyNameFromTable(hb_blob_t *aNameTable,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
nsAutoString name;
|
||||
@ -1283,14 +1286,14 @@ enum {
|
||||
};
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
int32_t aPlatformID, nsTArray<nsString>& aNames)
|
||||
{
|
||||
return ReadNames(aNameTable, aNameID, LANG_ALL, aPlatformID, aNames);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadCanonicalName(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
nsString& aName)
|
||||
{
|
||||
nsresult rv;
|
||||
@ -1458,7 +1461,7 @@ gfxFontUtils::GetCharsetForFontName(uint16_t aPlatform, uint16_t aScript, uint16
|
||||
// convert a raw name from the name table to an nsString, if possible;
|
||||
// return value indicates whether conversion succeeded
|
||||
bool
|
||||
gfxFontUtils::DecodeFontName(const uint8_t *aNameData, int32_t aByteLen,
|
||||
gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
|
||||
uint32_t aPlatformCode, uint32_t aScriptCode,
|
||||
uint32_t aLangCode, nsAString& aName)
|
||||
{
|
||||
@ -1508,7 +1511,7 @@ gfxFontUtils::DecodeFontName(const uint8_t *aNameData, int32_t aByteLen,
|
||||
}
|
||||
|
||||
int32_t destLength;
|
||||
rv = decoder->GetMaxLength(reinterpret_cast<const char*>(aNameData), aByteLen, &destLength);
|
||||
rv = decoder->GetMaxLength(aNameData, aByteLen, &destLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("decoder->GetMaxLength failed, invalid font name?");
|
||||
return false;
|
||||
@ -1516,7 +1519,7 @@ gfxFontUtils::DecodeFontName(const uint8_t *aNameData, int32_t aByteLen,
|
||||
|
||||
// make space for the converted string
|
||||
aName.SetLength(destLength);
|
||||
rv = decoder->Convert(reinterpret_cast<const char*>(aNameData), &aByteLen,
|
||||
rv = decoder->Convert(aNameData, &aByteLen,
|
||||
aName.BeginWriting(), &destLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("decoder->Convert failed, invalid font name?");
|
||||
@ -1528,17 +1531,17 @@ gfxFontUtils::DecodeFontName(const uint8_t *aNameData, int32_t aByteLen,
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
int32_t aLangID, int32_t aPlatformID,
|
||||
nsTArray<nsString>& aNames)
|
||||
{
|
||||
uint32_t nameTableLen = aNameTable.Length();
|
||||
uint32_t nameTableLen;
|
||||
const char *nameTable = hb_blob_get_data(aNameTable, &nameTableLen);
|
||||
NS_ASSERTION(nameTableLen != 0, "null name table");
|
||||
|
||||
if (nameTableLen == 0)
|
||||
if (!nameTableLen) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
uint8_t *nameTable = aNameTable.Elements();
|
||||
}
|
||||
|
||||
// -- name table data
|
||||
const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(nameTable);
|
||||
|
@ -33,6 +33,8 @@
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
typedef struct hb_blob_t hb_blob_t;
|
||||
|
||||
class gfxSparseBitSet {
|
||||
private:
|
||||
enum { BLOCK_SIZE = 32 }; // ==> 256 codepoints per block
|
||||
@ -829,12 +831,12 @@ public:
|
||||
// helper to get fullname from name table, constructing from family+style
|
||||
// if no explicit fullname is present
|
||||
static nsresult
|
||||
GetFullNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
GetFullNameFromTable(hb_blob_t *aNameTable,
|
||||
nsAString& aFullName);
|
||||
|
||||
// helper to get family name from name table
|
||||
static nsresult
|
||||
GetFamilyNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
GetFamilyNameFromTable(hb_blob_t *aNameTable,
|
||||
nsAString& aFamilyName);
|
||||
|
||||
// create a new name table and build a new font with that name table
|
||||
@ -845,20 +847,20 @@ public:
|
||||
|
||||
// read all names matching aNameID, returning in aNames array
|
||||
static nsresult
|
||||
ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
int32_t aPlatformID, nsTArray<nsString>& aNames);
|
||||
|
||||
// reads English or first name matching aNameID, returning in aName
|
||||
// platform based on OS
|
||||
static nsresult
|
||||
ReadCanonicalName(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
nsString& aName);
|
||||
|
||||
// convert a name from the raw name table data into an nsString,
|
||||
// provided we know how; return true if successful, or false
|
||||
// if we can't handle the encoding
|
||||
static bool
|
||||
DecodeFontName(const uint8_t *aBuf, int32_t aLength,
|
||||
DecodeFontName(const char *aBuf, int32_t aLength,
|
||||
uint32_t aPlatformCode, uint32_t aScriptCode,
|
||||
uint32_t aLangCode, nsAString& dest);
|
||||
|
||||
@ -934,7 +936,7 @@ public:
|
||||
|
||||
protected:
|
||||
static nsresult
|
||||
ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames);
|
||||
|
||||
// convert opentype name-table platform/encoding/language values to a charset name
|
||||
|
@ -199,7 +199,7 @@ GDIFontEntry::ReadCMAP()
|
||||
nsresult rv;
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
rv = CopyFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
@ -263,8 +263,8 @@ GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold
|
||||
}
|
||||
|
||||
nsresult
|
||||
GDIFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
GDIFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
if (!IsTrueType()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -280,8 +280,8 @@ protected:
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold);
|
||||
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer);
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
LOGFONTW mLogFont;
|
||||
};
|
||||
|
@ -40,69 +40,26 @@ using namespace mozilla; // for AutoSwap_* types
|
||||
|
||||
gfxGraphiteShaper::gfxGraphiteShaper(gfxFont *aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mGrFace(nullptr),
|
||||
mGrFace(mFont->GetFontEntry()->GetGrFace()),
|
||||
mGrFont(nullptr)
|
||||
{
|
||||
mTables.Init();
|
||||
mCallbackData.mFont = aFont;
|
||||
mCallbackData.mShaper = this;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
ReleaseTableFunc(const uint32_t& /* aKey */,
|
||||
gfxGraphiteShaper::TableRec& aData,
|
||||
void* /* aUserArg */)
|
||||
{
|
||||
hb_blob_destroy(aData.mBlob);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
gfxGraphiteShaper::~gfxGraphiteShaper()
|
||||
{
|
||||
if (mGrFont) {
|
||||
gr_font_destroy(mGrFont);
|
||||
}
|
||||
if (mGrFace) {
|
||||
gr_face_destroy(mGrFace);
|
||||
}
|
||||
mTables.Enumerate(ReleaseTableFunc, nullptr);
|
||||
mFont->GetFontEntry()->ReleaseGrFace(mGrFace);
|
||||
}
|
||||
|
||||
static const void*
|
||||
GrGetTable(const void* appFaceHandle, unsigned int name, size_t *len)
|
||||
/*static*/ float
|
||||
gfxGraphiteShaper::GrGetAdvance(const void* appFontHandle, uint16_t glyphid)
|
||||
{
|
||||
const gfxGraphiteShaper::CallbackData *cb =
|
||||
static_cast<const gfxGraphiteShaper::CallbackData*>(appFaceHandle);
|
||||
return cb->mShaper->GetTable(name, len);
|
||||
}
|
||||
|
||||
const void*
|
||||
gfxGraphiteShaper::GetTable(uint32_t aTag, size_t *aLength)
|
||||
{
|
||||
TableRec tableRec;
|
||||
|
||||
if (!mTables.Get(aTag, &tableRec)) {
|
||||
hb_blob_t *blob = mFont->GetFontTable(aTag);
|
||||
if (blob) {
|
||||
// mFont->GetFontTable() gives us a reference to the blob.
|
||||
// We will destroy (release) it in our destructor.
|
||||
tableRec.mBlob = blob;
|
||||
tableRec.mData = hb_blob_get_data(blob, &tableRec.mLength);
|
||||
mTables.Put(aTag, tableRec);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
*aLength = tableRec.mLength;
|
||||
return tableRec.mData;
|
||||
}
|
||||
|
||||
static float
|
||||
GrGetAdvance(const void* appFontHandle, gr_uint16 glyphid)
|
||||
{
|
||||
const gfxGraphiteShaper::CallbackData *cb =
|
||||
static_cast<const gfxGraphiteShaper::CallbackData*>(appFontHandle);
|
||||
const CallbackData *cb =
|
||||
static_cast<const CallbackData*>(appFontHandle);
|
||||
return FixedToFloat(cb->mFont->GetGlyphWidth(cb->mContext, glyphid));
|
||||
}
|
||||
|
||||
@ -152,7 +109,6 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
||||
mCallbackData.mContext = aContext;
|
||||
|
||||
if (!mGrFont) {
|
||||
mGrFace = gr_make_face(&mCallbackData, GrGetTable, gr_face_default);
|
||||
if (!mGrFace) {
|
||||
return false;
|
||||
}
|
||||
@ -170,8 +126,6 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
||||
}
|
||||
|
||||
if (!mGrFont) {
|
||||
gr_face_destroy(mGrFace);
|
||||
mGrFace = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -192,8 +146,13 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
||||
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
|
||||
|
||||
if (MergeFontFeatures(style->featureSettings, entry->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(), mergedFeatures)) {
|
||||
// if style contains font-specific features
|
||||
if (MergeFontFeatures(style,
|
||||
mFont->GetFontEntry()->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
mFont->GetFontEntry()->FamilyName(),
|
||||
mergedFeatures))
|
||||
{
|
||||
// enumerate result and insert into Graphite feature list
|
||||
GrFontFeatures f = {mGrFace, grFeatures};
|
||||
mergedFeatures.Enumerate(AddFeature, &f);
|
||||
|
@ -27,22 +27,8 @@ public:
|
||||
int32_t aScript,
|
||||
gfxShapedText *aShapedText);
|
||||
|
||||
const void* GetTable(uint32_t aTag, size_t *aLength);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
struct CallbackData {
|
||||
gfxFont *mFont;
|
||||
gfxGraphiteShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
struct TableRec {
|
||||
hb_blob_t *mBlob;
|
||||
const void *mData;
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsresult SetGlyphsFromSegment(gfxContext *aContext,
|
||||
gfxShapedText *aShapedText,
|
||||
@ -51,13 +37,20 @@ protected:
|
||||
const PRUnichar *aText,
|
||||
gr_segment *aSegment);
|
||||
|
||||
gr_face *mGrFace;
|
||||
gr_font *mGrFont;
|
||||
static float GrGetAdvance(const void* appFontHandle, uint16_t glyphid);
|
||||
|
||||
gr_face *mGrFace; // owned by the font entry; shaper must call
|
||||
// gfxFontEntry::ReleaseGrFace when finished with it
|
||||
gr_font *mGrFont; // owned by the shaper itself
|
||||
|
||||
struct CallbackData {
|
||||
gfxFont *mFont;
|
||||
gfxGraphiteShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
CallbackData mCallbackData;
|
||||
|
||||
nsDataHashtable<nsUint32HashKey,TableRec> mTables;
|
||||
|
||||
// Convert HTML 'lang' (BCP47) to Graphite language code
|
||||
static uint32_t GetGraphiteTagForLang(const nsCString& aLang);
|
||||
static nsTHashtable<nsUint32HashKey> sLanguageTags;
|
||||
|
@ -43,7 +43,8 @@ using namespace mozilla::unicode; // for Unicode property lookup
|
||||
|
||||
gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mHBFace(nullptr),
|
||||
mHBFace(aFont->GetFontEntry()->GetHBFace()),
|
||||
mHBFont(nullptr),
|
||||
mKernTable(nullptr),
|
||||
mHmtxTable(nullptr),
|
||||
mNumLongMetrics(0),
|
||||
@ -52,61 +53,30 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
mSubtableOffset(0),
|
||||
mUVSTableOffset(0),
|
||||
mUseFontGetGlyph(aFont->ProvidesGetGlyph()),
|
||||
mUseFontGlyphWidths(false)
|
||||
mUseFontGlyphWidths(false),
|
||||
mInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
gfxHarfBuzzShaper::~gfxHarfBuzzShaper()
|
||||
{
|
||||
hb_blob_destroy(mCmapTable);
|
||||
hb_blob_destroy(mHmtxTable);
|
||||
hb_blob_destroy(mKernTable);
|
||||
hb_face_destroy(mHBFace);
|
||||
}
|
||||
|
||||
/*
|
||||
* HarfBuzz callback access to font table data
|
||||
*/
|
||||
|
||||
// callback for HarfBuzz to get a font table (in hb_blob_t form)
|
||||
// from the shaper (passed as aUserData)
|
||||
static hb_blob_t *
|
||||
HBGetTable(hb_face_t *face, hb_tag_t aTag, void *aUserData)
|
||||
{
|
||||
gfxHarfBuzzShaper *shaper = static_cast<gfxHarfBuzzShaper*>(aUserData);
|
||||
gfxFont *font = shaper->GetFont();
|
||||
|
||||
// bug 589682 - ignore the GDEF table in buggy fonts (applies to
|
||||
// Italic and BoldItalic faces of Times New Roman)
|
||||
if (aTag == TRUETYPE_TAG('G','D','E','F') &&
|
||||
font->GetFontEntry()->IgnoreGDEF()) {
|
||||
return nullptr;
|
||||
if (mCmapTable) {
|
||||
hb_blob_destroy(mCmapTable);
|
||||
}
|
||||
|
||||
// bug 721719 - ignore the GSUB table in buggy fonts (applies to Roboto,
|
||||
// at least on some Android ICS devices; set in gfxFT2FontList.cpp)
|
||||
if (aTag == TRUETYPE_TAG('G','S','U','B') &&
|
||||
font->GetFontEntry()->IgnoreGSUB()) {
|
||||
return nullptr;
|
||||
if (mHmtxTable) {
|
||||
hb_blob_destroy(mHmtxTable);
|
||||
}
|
||||
if (mKernTable) {
|
||||
hb_blob_destroy(mKernTable);
|
||||
}
|
||||
if (mHBFont) {
|
||||
hb_font_destroy(mHBFont);
|
||||
}
|
||||
if (mHBFace) {
|
||||
hb_face_destroy(mHBFace);
|
||||
}
|
||||
|
||||
return font->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
/*
|
||||
* HarfBuzz font callback functions; font_data is a ptr to a
|
||||
* FontCallbackData struct
|
||||
*/
|
||||
|
||||
struct FontCallbackData {
|
||||
FontCallbackData(gfxHarfBuzzShaper *aShaper, gfxContext *aContext)
|
||||
: mShaper(aShaper), mContext(aContext)
|
||||
{ }
|
||||
|
||||
gfxHarfBuzzShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
#define UNICODE_BMP_LIMIT 0x10000
|
||||
|
||||
hb_codepoint_t
|
||||
@ -173,8 +143,8 @@ HBGetGlyph(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data)
|
||||
{
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
*glyph = fcd->mShaper->GetGlyph(unicode, variation_selector);
|
||||
return *glyph != 0;
|
||||
}
|
||||
@ -238,8 +208,8 @@ static hb_position_t
|
||||
HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph, void *user_data)
|
||||
{
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
|
||||
}
|
||||
|
||||
@ -498,7 +468,7 @@ gfxHarfBuzzShaper::GetHKerning(uint16_t aFirstGlyph,
|
||||
}
|
||||
|
||||
if (!mKernTable) {
|
||||
mKernTable = mFont->GetFontTable(TRUETYPE_TAG('k','e','r','n'));
|
||||
mKernTable = mFont->GetFontEntry()->GetFontTable(TRUETYPE_TAG('k','e','r','n'));
|
||||
if (!mKernTable) {
|
||||
mKernTable = hb_blob_get_empty();
|
||||
}
|
||||
@ -642,8 +612,8 @@ HBGetHKerning(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
void *user_data)
|
||||
{
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
return fcd->mShaper->GetHKerning(first_glyph, second_glyph);
|
||||
}
|
||||
|
||||
@ -851,12 +821,15 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mHBFace) {
|
||||
mCallbackData.mContext = aContext;
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
|
||||
if (!mInitialized) {
|
||||
mInitialized = true;
|
||||
mCallbackData.mShaper = this;
|
||||
|
||||
mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
|
||||
|
||||
// set up the harfbuzz face etc the first time we use the font
|
||||
|
||||
if (!sHBFontFuncs) {
|
||||
// static function callback pointers, initialized by the first
|
||||
// harfbuzz shaper used
|
||||
@ -897,11 +870,9 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
mHBFace = hb_face_create_for_tables(HBGetTable, this, nullptr);
|
||||
|
||||
if (!mUseFontGetGlyph) {
|
||||
// get the cmap table and find offset to our subtable
|
||||
mCmapTable = mFont->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
if (!mCmapTable) {
|
||||
NS_WARNING("failed to load cmap, glyphs will be missing");
|
||||
return false;
|
||||
@ -920,8 +891,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
// the hmtx table directly;
|
||||
// read mNumLongMetrics from hhea table without caching its blob,
|
||||
// and preload/cache the hmtx table
|
||||
hb_blob_t *hheaTable =
|
||||
mFont->GetFontTable(TRUETYPE_TAG('h','h','e','a'));
|
||||
gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
|
||||
if (hheaTable) {
|
||||
uint32_t len;
|
||||
const HMetricsHeader* hhea =
|
||||
@ -935,7 +905,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
// in that case, we won't be able to use this font
|
||||
// (this method will return FALSE below if mHmtx is null)
|
||||
mHmtxTable =
|
||||
mFont->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
|
||||
entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
|
||||
if (hb_blob_get_length(mHmtxTable) <
|
||||
mNumLongMetrics * sizeof(HLongMetric)) {
|
||||
// hmtx table is not large enough for the claimed
|
||||
@ -946,8 +916,13 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
hb_blob_destroy(hheaTable);
|
||||
}
|
||||
|
||||
mHBFont = hb_font_create(mHBFace);
|
||||
hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
|
||||
hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
|
||||
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
|
||||
hb_font_set_scale(mHBFont, scale, scale);
|
||||
}
|
||||
|
||||
if ((!mUseFontGetGlyph && mCmapFormat <= 0) ||
|
||||
@ -956,23 +931,17 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
return false;
|
||||
}
|
||||
|
||||
FontCallbackData fcd(this, aContext);
|
||||
hb_font_t *font = hb_font_create(mHBFace);
|
||||
hb_font_set_funcs(font, sHBFontFuncs, &fcd, nullptr);
|
||||
hb_font_set_ppem(font, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
|
||||
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
|
||||
hb_font_set_scale(font, scale, scale);
|
||||
|
||||
nsAutoTArray<hb_feature_t,20> features;
|
||||
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
const gfxFontStyle *style = mFont->GetStyle();
|
||||
|
||||
nsAutoTArray<hb_feature_t,20> features;
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
|
||||
|
||||
if (MergeFontFeatures(style->featureSettings,
|
||||
mFont->GetFontEntry()->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(), mergedFeatures)) {
|
||||
if (MergeFontFeatures(style,
|
||||
entry->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
entry->FamilyName(),
|
||||
mergedFeatures))
|
||||
{
|
||||
// enumerate result and insert into hb_feature array
|
||||
mergedFeatures.Enumerate(AddFeature, &features);
|
||||
}
|
||||
@ -1008,7 +977,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
reinterpret_cast<const uint16_t*>(aText),
|
||||
length, 0, length);
|
||||
|
||||
hb_shape(font, buffer, features.Elements(), features.Length());
|
||||
hb_shape(mHBFont, buffer, features.Elements(), features.Length());
|
||||
|
||||
if (isRightToLeft) {
|
||||
hb_buffer_reverse(buffer);
|
||||
@ -1019,7 +988,6 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to store glyphs into gfxShapedWord");
|
||||
hb_buffer_destroy(buffer);
|
||||
hb_font_destroy(font);
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
@ -18,6 +18,15 @@ public:
|
||||
gfxHarfBuzzShaper(gfxFont *aFont);
|
||||
virtual ~gfxHarfBuzzShaper();
|
||||
|
||||
/*
|
||||
* For HarfBuzz font callback functions, font_data is a ptr to a
|
||||
* FontCallbackData struct
|
||||
*/
|
||||
struct FontCallbackData {
|
||||
gfxHarfBuzzShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
virtual bool ShapeText(gfxContext *aContext,
|
||||
const PRUnichar *aText,
|
||||
uint32_t aOffset,
|
||||
@ -54,9 +63,15 @@ protected:
|
||||
nsTArray<nsPoint>& aPositions,
|
||||
uint32_t aAppUnitsPerDevUnit);
|
||||
|
||||
// harfbuzz face object, created on first use (caches font tables)
|
||||
// harfbuzz face object: we acquire a reference from the font entry
|
||||
// on shaper creation, and release it in our destructor
|
||||
hb_face_t *mHBFace;
|
||||
|
||||
// size-specific font object, owned by the gfxHarfBuzzShaper
|
||||
hb_font_t *mHBFont;
|
||||
|
||||
FontCallbackData mCallbackData;
|
||||
|
||||
// Following table references etc are declared "mutable" because the
|
||||
// harfbuzz callback functions take a const ptr to the shaper, but
|
||||
// wish to cache tables here to avoid repeatedly looking them up
|
||||
@ -87,6 +102,8 @@ protected:
|
||||
// Whether the font implements GetGlyphWidth, or we should read tables
|
||||
// directly to get ideal widths
|
||||
bool mUseFontGlyphWidths;
|
||||
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
#endif /* GFX_HARFBUZZSHAPER_H */
|
||||
|
@ -189,13 +189,17 @@ gfxMacFont::InitMetrics()
|
||||
// return the true value for OpenType/CFF fonts (it normalizes to 1000,
|
||||
// which then leads to metrics errors when we read the 'hmtx' table to
|
||||
// get glyph advances for HarfBuzz, see bug 580863)
|
||||
const uint32_t kHeadTableTag = TRUETYPE_TAG('h','e','a','d');
|
||||
AutoFallibleTArray<uint8_t,sizeof(HeadTable)> headData;
|
||||
if (NS_SUCCEEDED(mFontEntry->GetFontTable(kHeadTableTag, headData)) &&
|
||||
headData.Length() >= sizeof(HeadTable)) {
|
||||
HeadTable *head = reinterpret_cast<HeadTable*>(headData.Elements());
|
||||
upem = head->unitsPerEm;
|
||||
} else {
|
||||
CFDataRef headData =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('h','e','a','d'));
|
||||
if (headData) {
|
||||
if (size_t(::CFDataGetLength(headData)) >= sizeof(HeadTable)) {
|
||||
const HeadTable *head =
|
||||
reinterpret_cast<const HeadTable*>(::CFDataGetBytePtr(headData));
|
||||
upem = head->unitsPerEm;
|
||||
}
|
||||
::CFRelease(headData);
|
||||
}
|
||||
if (!upem) {
|
||||
upem = ::CGFontGetUnitsPerEm(mCGFont);
|
||||
}
|
||||
|
||||
@ -348,35 +352,6 @@ gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxMacFont::DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
::CFRelease((CFDataRef)aUserData);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxMacFont::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
CFDataRef dataRef = ::CGFontCopyTableForTag(mCGFont, aTag);
|
||||
if (dataRef) {
|
||||
return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef),
|
||||
::CFDataGetLength(dataRef),
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
(void*)dataRef, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
// for downloaded fonts, there may be layout tables cached in the entry
|
||||
// even though they're absent from the sanitized platform font
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to initialize font metrics via platform APIs (CG/CT),
|
||||
// and set mIsValid = TRUE on success.
|
||||
// We ONLY call this for local (platform) fonts that are not sfnt format;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user