Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2013-05-20 16:21:45 -04:00
commit 153a6ea11e
195 changed files with 6535 additions and 1651 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -121,10 +121,7 @@ public:
return nullptr;
}
JSObject* global;
mGlobal->GetJSObject(&global);
return global;
return mGlobal->GetJSObject();
}
protected:
nsresult Init();

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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*

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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()

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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;
}
//----------------------------------------------------------------------

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)) {

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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;
}

View 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;
}

View File

@ -0,0 +1,7 @@
<html>
<head>
</head>
<body>
App Body. Version: VERSIONTOKEN
</body>
</html>

View 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"
}

View 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>

View File

@ -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);

View File

@ -232,6 +232,8 @@ DOMCI_CLASS(AsyncScrollEventDetail)
DOMCI_CLASS(LockedFile)
DOMCI_CLASS(CSSFontFeatureValuesRule)
#ifdef MOZ_TIME_MANAGER
DOMCI_CLASS(MozTimeManager)
#endif

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -69,6 +69,7 @@ interface nsIDOMCSSPrimitiveValue;
interface nsIDOMCSSRule;
interface nsIDOMCSSRuleList;
interface nsIDOMMozCSSKeyframeRule;
interface nsIDOMCSSFontFeatureValuesRule;
interface nsIDOMCSSStyleSheet;
interface nsIDOMCSSStyleDeclaration;
interface nsIDOMCounter;

View File

@ -8,6 +8,7 @@ XPIDL_SOURCES += [
'nsIDOMCSSCharsetRule.idl',
'nsIDOMCSSConditionRule.idl',
'nsIDOMCSSFontFaceRule.idl',
'nsIDOMCSSFontFeatureValuesRule.idl',
'nsIDOMCSSGroupingRule.idl',
'nsIDOMCSSImportRule.idl',
'nsIDOMCSSMediaRule.idl',

View 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
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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=')'

View File

@ -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);

View File

@ -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

View File

@ -11,8 +11,6 @@
*/
interface SVGAnimatedRect {
[GetterThrows]
readonly attribute SVGRect? baseVal;
[GetterThrows]
readonly attribute SVGRect? animVal;
};

View File

@ -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"))

View File

@ -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"

View File

@ -297,7 +297,8 @@ public:
enum {
RendererAdreno200,
RendererAdreno205,
RendererAdreno320,
RendererAdrenoTM205,
RendererAdrenoTM320,
RendererSGX530,
RendererSGX540,
RendererOther

View File

@ -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;

View File

@ -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) {}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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 =

View File

@ -34,6 +34,7 @@ CPPSRCS = \
gfxDrawable.cpp \
gfxImageSurface.cpp \
gfxFont.cpp \
gfxFontFeatures.cpp \
gfxFontMissingGlyphs.cpp \
gfxFontTest.cpp \
gfxFontUtils.cpp \

View File

@ -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;
}

View File

@ -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;

View File

@ -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()
{

View File

@ -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();

View File

@ -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)
{

View File

@ -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; }

View File

@ -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) {

View File

@ -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

View File

@ -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)
{

View File

@ -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()

View File

@ -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

View File

@ -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) {

View File

@ -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

View 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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
};

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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