Re-pull m-c in preparation for pushing back.
Re-pull m-c in preparation for pushing back.
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -180,17 +180,16 @@ include $(topsrcdir)/config/rules.mk
file_XHR_pass2.txt \
file_XHR_pass3.txt \
file_XHR_pass3.txt^headers^ \
file_XHR_fail1.txt \
file_XHR_fail1.txt^headers^ \
test_bug428847.html \
file_bug428847-1.xhtml \
file_bug428847-2.xhtml \
- test_bug425201.html \
test_bug431701.html \
test_bug431833.html \
test_bug435425.html \
bug435425.sjs \
bug435425_redirect.sjs \
test_bug438519.html \
test_bug444722.html \
test_bug451376.html \
deleted file mode 100644
--- a/content/base/test/test_bug425201.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=425201
--->
-<head>
- <title>Test for Bug 425201</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=425201">Mozilla Bug 425201</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 425201 **/
-
-var req = new XMLHttpRequest();
-
-var threw = false;
-try {
- req.open("GET", "http://www.example.com/", false);
-}
-catch (e) {
- threw = true;
-}
-
-ok(threw, "Open should have thrown");
-
-threw = false;
-try {
- req.send(null);
-}
-catch (e) {
- threw = true;
-}
-
-ok(threw, "Send should have thrown");
-
-</script>
-</pre>
-</body>
-</html>
--- a/content/base/test/test_bug428847.html
+++ b/content/base/test/test_bug428847.html
@@ -12,18 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
<body onload="runtests();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428847">Mozilla Bug 428847</a>
<script class="testbody" type="text/javascript">
var iframe1Loaded = false;
var iframe2Loaded = false;
function runtests()
{
- is(iframe1Loaded, true,
- "Iframe with cross-origin xslt stylesheet failed to load");
+ //is(iframe1Loaded, true,
+ // "Iframe with cross-origin xslt stylesheet failed to load");
is(iframe2Loaded, false,
"Iframe with invalid xslt stylesheet URI didn't fail to load");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -1970,17 +1970,17 @@ nsCanvasRenderingContext2D::SetFont(cons
gfxFontStyle style(fontStyle->mFont.style,
fontStyle->mFont.weight,
NSAppUnitsToFloatPixels(fontSize, aupcp),
langGroup,
fontStyle->mFont.sizeAdjust,
fontStyle->mFont.systemFont,
fontStyle->mFont.familyNameQuirks);
- CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style);
+ CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style, presShell->GetPresContext()->GetUserFontSet());
NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
CurrentState().font = font;
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetFont(nsAString& font)
{
--- a/content/html/content/public/nsHTMLAudioElement.h
+++ b/content/html/content/public/nsHTMLAudioElement.h
@@ -31,26 +31,24 @@
* 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 "nsIDOMHTMLAudioElement.h"
-#include "nsIJSNativeInitializer.h"
#include "nsHTMLMediaElement.h"
#include "nsVideoDecoder.h"
typedef PRUint16 nsMediaNetworkState;
typedef PRUint16 nsMediaReadyState;
class nsHTMLAudioElement : public nsHTMLMediaElement,
- public nsIDOMHTMLAudioElement,
- public nsIJSNativeInitializer
+ public nsIDOMHTMLAudioElement
{
public:
nsHTMLAudioElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
virtual ~nsHTMLAudioElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@@ -64,20 +62,16 @@ public:
NS_FORWARD_NSIDOMHTMLELEMENT(nsHTMLMediaElement::)
// nsIDOMHTMLMediaElement
NS_FORWARD_NSIDOMHTMLMEDIAELEMENT(nsHTMLMediaElement::)
// nsIDOMHTMLAudioElement
NS_DECL_NSIDOMHTMLAUDIOELEMENT
- // nsIJSNativeInitializer
- NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
- JSObject* aObj, PRUint32 argc, jsval* argv);
-
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
protected:
virtual nsresult InitializeDecoder(nsAString& aChosenMediaResource);
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -150,13 +150,12 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../events/src \
-I$(srcdir)/../../../xbl/src \
-I$(srcdir)/../../../../layout/style \
-I$(srcdir)/../../../../layout/tables \
- -I$(srcdir)/../../../../dom/src/base \
-I$(srcdir) \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -50,57 +50,36 @@
#include "nsNodeInfoManager.h"
#include "plbase64.h"
#include "nsNetUtil.h"
#include "prmem.h"
#include "nsNetUtil.h"
#include "nsXPCOMStrings.h"
#include "prlock.h"
#include "nsThreadUtils.h"
-#include "nsJSUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsIRenderingContext.h"
#include "nsITimer.h"
#include "nsEventDispatcher.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMProgressEvent.h"
#include "nsHTMLMediaError.h"
-nsGenericHTMLElement*
-NS_NewHTMLAudioElement(nsINodeInfo *aNodeInfo, PRBool aFromParser)
-{
- /*
- * nsHTMLAudioElement's will be created without a nsINodeInfo passed in
- * if someone says "var audio = new Audio();" in JavaScript, in a case like
- * that we request the nsINodeInfo from the document's nodeinfo list.
- */
- nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
- if (!nodeInfo) {
- nsCOMPtr<nsIDocument> doc =
- do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
- NS_ENSURE_TRUE(doc, nsnull);
-
- nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::audio, nsnull,
- kNameSpaceID_None);
- NS_ENSURE_TRUE(nodeInfo, nsnull);
- }
-
- return new nsHTMLAudioElement(nodeInfo);
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Audio)
NS_IMPL_ADDREF_INHERITED(nsHTMLAudioElement, nsHTMLMediaElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLAudioElement, nsHTMLMediaElement)
NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLAudioElement, nsHTMLMediaElement)
-NS_INTERFACE_TABLE_INHERITED2(nsHTMLAudioElement, nsIDOMHTMLAudioElement, nsIJSNativeInitializer)
+ NS_INTERFACE_TABLE_INHERITED1(nsHTMLAudioElement, nsIDOMHTMLAudioElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLAudioElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLAudioElement)
nsHTMLAudioElement::nsHTMLAudioElement(nsINodeInfo *aNodeInfo, PRBool aFromParser)
: nsHTMLMediaElement(aNodeInfo, aFromParser)
{
@@ -134,26 +113,8 @@ void nsHTMLAudioElement::UnbindFromTree(
nsresult nsHTMLAudioElement::InitializeDecoder(nsAString& aChosenMediaResource)
{
if (mDecoder)
mDecoder->ElementAvailable(this);
return nsHTMLMediaElement::InitializeDecoder(aChosenMediaResource);
}
-
-NS_IMETHODIMP
-nsHTMLAudioElement::Initialize(nsISupports* aOwner, JSContext* aContext,
- JSObject *aObj, PRUint32 argc, jsval *argv)
-{
- if (argc <= 0) {
- // Nothing to do here if we don't get any arguments.
- return NS_OK;
- }
-
- // The only (optional) argument is the url of the audio
- JSString* jsstr = JS_ValueToString(aContext, argv[0]);
- if (!jsstr)
- return NS_ERROR_FAILURE;
-
- nsDependentJSString str(jsstr);
- return SetAttr(kNameSpaceID_None, nsGkAtoms::src, str, PR_TRUE);
-}
--- a/content/media/video/test/Makefile.in
+++ b/content/media/video/test/Makefile.in
@@ -38,27 +38,24 @@ DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = content/media/video/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
-_TEST_FILES = test_audio1.html \
- test_audio2.html \
- test_autoplay.html \
+_TEST_FILES = test_autoplay.html \
test_constants.html \
test_controls.html \
test_currentTime.html \
test_defaultPlaybackRate.html \
test_networkState.html \
test_paused.html \
test_playbackRate.html \
test_readyState.html \
test_start.html \
- sound.ogg \
# test_bug448534.html \
320x240.ogg \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
deleted file mode 100644
index edda4e9128435b0cc9ba500c9daca90e2be30acf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/content/media/video/test/test_audio1.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Media test: Audio Constructor Test 1</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>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-var timeout = setTimeout(function () {
- ok(false, "Test timed out");
- SimpleTest.finish();
- }, 30000);
-var a1 = new Audio();
-a1.onload = function() {
- ok(a1.networkState == a1.LOADED, "Audio onload");
- clearTimeout(timeout);
- SimpleTest.finish();
-}
-a1.src = 'sound.ogg';
-
-SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/content/media/video/test/test_audio2.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Media test: Audio Constructor Test 2</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>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-var timeout = setTimeout(function () {
- ok(false, "Test timed out");
- SimpleTest.finish();
- }, 30000);
-var a1 = new Audio('sound.ogg');
-a1.onload = function() {
- ok(a1.networkState == a1.LOADED, "Audio onload");
- clearTimeout(timeout);
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-</body>
-</html>
--- a/gfx/public/nsDeviceContext.h
+++ b/gfx/public/nsDeviceContext.h
@@ -56,17 +56,17 @@ class NS_GFX nsFontCache
{
public:
nsFontCache();
virtual ~nsFontCache();
virtual nsresult Init(nsIDeviceContext* aContext);
virtual nsresult GetDeviceContext(nsIDeviceContext *&aContext) const;
virtual nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIFontMetrics *&aMetrics);
+ nsIFontMetrics *&aMetrics, gfxUserFontSet *aUserFontSet = nsnull);
nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
nsresult Compact();
nsresult Flush();
/* printer device context classes may create their own
* subclasses of nsFontCache (and override this method) and override
* DeviceContextImpl::CreateFontCache (see bug 81311).
*/
@@ -95,18 +95,19 @@ public:
NS_IMETHOD Init(nsNativeWidget aWidget);
NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext){return NS_ERROR_NOT_IMPLEMENTED;}
NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIFontMetrics*& aMetrics);
- NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics);
+ nsIFontMetrics*& aMetrics, gfxUserFontSet *aUserFontSet = nsnull);
+ NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics,
+ gfxUserFontSet *aUserFontSet = nsnull);
NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
PRBool& aAliased);
NS_IMETHOD CreateFontCache();
NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
--- a/gfx/public/nsIDeviceContext.h
+++ b/gfx/public/nsIDeviceContext.h
@@ -47,16 +47,17 @@
// XXX we need only gfxTypes.h, but we cannot include it directly.
#include "gfxPoint.h"
class nsIView;
class nsIFontMetrics;
class nsIWidget;
class nsIDeviceContextSpec;
class nsIAtom;
+class gfxUserFontSet;
struct nsFont;
//a cross platform way of specifying a native device context
typedef void * nsNativeDeviceContext;
/* error codes for printer device contexts */
#define NS_ERROR_GFX_PRINTER_BASE (1) /* adjustable :-) */
@@ -325,29 +326,33 @@ public:
NS_IMETHOD GetSystemFont(nsSystemFontID aID, nsFont *aFont) const = 0;
/**
* Get the nsIFontMetrics that describe the properties of
* an nsFont.
* @param aFont font description to obtain metrics for
* @param aLangGroup the language group of the document
* @param aMetrics out parameter for font metrics
+ * @param aUserFontSet user font set
* @return error status
*/
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIFontMetrics*& aMetrics) = 0;
+ nsIFontMetrics*& aMetrics,
+ gfxUserFontSet *aUserFontSet = nsnull) = 0;
/**
* Get the nsIFontMetrics that describe the properties of
* an nsFont.
* @param aFont font description to obtain metrics for
* @param aMetrics out parameter for font metrics
+ * @param aUserFontSet user font set
* @return error status
*/
- NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics) = 0;
+ NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics,
+ gfxUserFontSet *aUserFontSet = nsnull) = 0;
/**
* Check to see if a particular named font exists.
* @param aFontName character string of font face name
* @return NS_OK if font is available, else font is unavailable
*/
NS_IMETHOD CheckFontExistence(const nsString& aFaceName) = 0;
NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName) = 0;
--- a/gfx/public/nsIFontMetrics.h
+++ b/gfx/public/nsIFontMetrics.h
@@ -40,16 +40,17 @@
#include "nsISupports.h"
#include "nsCoord.h"
#include "nsFont.h"
class nsString;
class nsIDeviceContext;
class nsIAtom;
+class gfxUserFontSet;
// IID for the nsIFontMetrics interface
#define NS_IFONT_METRICS_IID \
{ 0xc74cb770, 0xa33e, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
//----------------------------------------------------------------------
@@ -82,17 +83,17 @@ public:
/**
* Initialize the font metrics. Call this after creating the font metrics.
* Font metrics you get from the font cache do NOT need to be initialized
*
* @see nsIDeviceContext#GetMetricsFor()
*/
NS_IMETHOD Init(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIDeviceContext *aContext) = 0;
+ nsIDeviceContext *aContext, gfxUserFontSet *aUserFontSet = nsnull) = 0;
/**
* Destroy this font metrics. This breaks the association between
* the font metrics and the device context.
*/
NS_IMETHOD Destroy() = 0;
/**
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -45,16 +45,17 @@
#include "nsVoidArray.h"
#include "nsIFontMetrics.h"
#include "nsHashtable.h"
#include "nsILanguageAtomService.h"
#include "nsIServiceManager.h"
#include "nsUnicharUtils.h"
#include "nsCRT.h"
#include "nsIRenderingContext.h"
+#include "gfxUserFontSet.h"
NS_IMPL_ISUPPORTS3(DeviceContextImpl, nsIDeviceContext, nsIObserver, nsISupportsWeakReference)
DeviceContextImpl::DeviceContextImpl()
{
mAppUnitsPerDevPixel = -1;
mAppUnitsPerInch = -1;
mAppUnitsPerDevNotScaledPixel = -1;
@@ -208,48 +209,51 @@ DeviceContextImpl::GetLocaleLangGroup(vo
}
if (!mLocaleLangGroup) {
mLocaleLangGroup = do_GetAtom("x-western");
}
}
}
NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
- nsIAtom* aLangGroup, nsIFontMetrics*& aMetrics)
+ nsIAtom* aLangGroup, nsIFontMetrics*& aMetrics, gfxUserFontSet *aUserFontSet)
{
if (nsnull == mFontCache) {
nsresult rv = CreateFontCache();
if (NS_FAILED(rv)) {
aMetrics = nsnull;
return rv;
}
// XXX temporary fix for performance problem -- erik
GetLocaleLangGroup();
}
// XXX figure out why aLangGroup is NULL sometimes
if (!aLangGroup) {
aLangGroup = mLocaleLangGroup;
}
- return mFontCache->GetMetricsFor(aFont, aLangGroup, aMetrics);
+ return mFontCache->GetMetricsFor(aFont, aLangGroup, aMetrics, aUserFontSet);
}
-NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics)
+NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
+ nsIFontMetrics*& aMetrics,
+ gfxUserFontSet *aUserFontSet)
{
if (nsnull == mFontCache) {
nsresult rv = CreateFontCache();
if (NS_FAILED(rv)) {
aMetrics = nsnull;
return rv;
}
// XXX temporary fix for performance problem -- erik
GetLocaleLangGroup();
}
- return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aMetrics);
+ return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup,
+ aMetrics, aUserFontSet);
}
NS_IMETHODIMP DeviceContextImpl::GetDepth(PRUint32& aDepth)
{
aDepth = 24;
return NS_OK;
}
@@ -464,17 +468,17 @@ nsFontCache::GetDeviceContext(nsIDeviceC
{
aContext = mContext;
NS_IF_ADDREF(aContext);
return NS_OK;
}
nsresult
nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIFontMetrics *&aMetrics)
+ nsIFontMetrics *&aMetrics, gfxUserFontSet *aUserFontSet)
{
// First check our cache
// start from the end, which is where we put the most-recent-used element
nsIFontMetrics* fm;
PRInt32 n = mFontMetrics.Count() - 1;
for (PRInt32 i = n; i >= 0; --i) {
fm = static_cast<nsIFontMetrics*>(mFontMetrics[i]);
@@ -492,17 +496,17 @@ nsFontCache::GetMetricsFor(const nsFont&
}
}
// It's not in the cache. Get font metrics and then cache them.
aMetrics = nsnull;
nsresult rv = CreateFontMetricsInstance(&fm);
if (NS_FAILED(rv)) return rv;
- rv = fm->Init(aFont, aLangGroup, mContext);
+ rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
if (NS_SUCCEEDED(rv)) {
// the mFontMetrics list has the "head" at the end, because append is
// cheaper than insert
mFontMetrics.AppendElement(fm);
aMetrics = fm;
NS_ADDREF(aMetrics);
return NS_OK;
}
@@ -511,17 +515,17 @@ nsFontCache::GetMetricsFor(const nsFont&
// One reason why Init() fails is because the system is running out of resources.
// e.g., on Win95/98 only a very limited number of GDI objects are available.
// Compact the cache and try again.
Compact();
rv = CreateFontMetricsInstance(&fm);
if (NS_FAILED(rv)) return rv;
- rv = fm->Init(aFont, aLangGroup, mContext);
+ rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
if (NS_SUCCEEDED(rv)) {
mFontMetrics.AppendElement(fm);
aMetrics = fm;
NS_ADDREF(aMetrics);
return NS_OK;
}
fm->Destroy();
NS_RELEASE(fm);
--- a/gfx/src/thebes/nsThebesFontMetrics.cpp
+++ b/gfx/src/thebes/nsThebesFontMetrics.cpp
@@ -39,16 +39,17 @@
#include "nsThebesFontMetrics.h"
#include "nsFont.h"
#include "nsString.h"
#include <stdio.h>
#include "gfxTextRunCache.h"
#include "gfxPlatform.h"
+#include "gfxUserFontSet.h"
NS_IMPL_ISUPPORTS1(nsThebesFontMetrics, nsIFontMetrics)
#include <stdlib.h>
nsThebesFontMetrics::nsThebesFontMetrics()
{
mFontStyle = nsnull;
@@ -58,17 +59,18 @@ nsThebesFontMetrics::nsThebesFontMetrics
nsThebesFontMetrics::~nsThebesFontMetrics()
{
delete mFontStyle;
//delete mFontGroup;
}
NS_IMETHODIMP
nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIDeviceContext *aContext)
+ nsIDeviceContext *aContext,
+ gfxUserFontSet *aUserFontSet)
{
mFont = aFont;
mLangGroup = aLangGroup;
mDeviceContext = (nsThebesDeviceContext*)aContext;
mP2A = mDeviceContext->AppUnitsPerDevPixel();
mIsRightToLeft = PR_FALSE;
mTextRunRTL = PR_FALSE;
@@ -81,17 +83,18 @@ nsThebesFontMetrics::Init(const nsFont&
langGroup.Assign(lg);
}
mFontStyle = new gfxFontStyle(aFont.style, aFont.weight, size, langGroup,
aFont.sizeAdjust, aFont.systemFont,
aFont.familyNameQuirks);
mFontGroup =
- gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle);
+ gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle,
+ aUserFontSet);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::Destroy()
{
return NS_OK;
--- a/gfx/src/thebes/nsThebesFontMetrics.h
+++ b/gfx/src/thebes/nsThebesFontMetrics.h
@@ -52,17 +52,18 @@ class nsThebesFontMetrics : public nsITh
{
public:
nsThebesFontMetrics();
virtual ~nsThebesFontMetrics();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(const nsFont& aFont, nsIAtom* aLangGroup,
- nsIDeviceContext *aContext);
+ nsIDeviceContext *aContext,
+ gfxUserFontSet *aUserFontSet = nsnull);
NS_IMETHOD Destroy();
NS_IMETHOD GetXHeight(nscoord& aResult);
NS_IMETHOD GetSuperscriptOffset(nscoord& aResult);
NS_IMETHOD GetSubscriptOffset(nscoord& aResult);
NS_IMETHOD GetStrikeout(nscoord& aOffset, nscoord& aSize);
NS_IMETHOD GetUnderline(nscoord& aOffset, nscoord& aSize);
NS_IMETHOD GetHeight(nscoord &aHeight);
NS_IMETHOD GetInternalLeading(nscoord &aLeading);
--- a/gfx/thebes/public/Makefile.in
+++ b/gfx/thebes/public/Makefile.in
@@ -26,16 +26,17 @@ EXPORTS = gfxASurface.h \
gfxPlatform.h \
gfxPoint.h \
gfxRect.h \
gfxSkipChars.h \
gfxTypes.h \
gfxTextRunCache.h \
gfxTextRunWordCache.h \
gfxUtils.h \
+ gfxUserFontSet.h \
$(NULL)
EXPORTS += gfxFontTest.h
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXPORTS += gfxWindowsFonts.h \
gfxWindowsPlatform.h \
gfxWindowsSurface.h \
--- a/gfx/thebes/public/gfxAtsuiFonts.h
+++ b/gfx/thebes/public/gfxAtsuiFonts.h
@@ -108,17 +108,18 @@ protected:
void InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef);
virtual PRBool SetupCairoFont(gfxContext *aContext);
};
class THEBES_API gfxAtsuiFontGroup : public gfxFontGroup {
public:
gfxAtsuiFontGroup(const nsAString& families,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet);
virtual ~gfxAtsuiFontGroup() {};
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
@@ -132,30 +133,34 @@ public:
PRBool aWrapped, gfxTextRun *aTextRun);
gfxAtsuiFont* GetFontAt(PRInt32 aFontIndex) {
return static_cast<gfxAtsuiFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
}
PRBool HasFont(ATSUFontID fid);
- inline gfxAtsuiFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList, PRUint32 aCh) {
+ inline gfxAtsuiFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList,
+ PRUint32 aCh)
+ {
PRUint32 len = aFontList.Length();
for (PRUint32 i = 0; i < len; i++) {
gfxAtsuiFont* font = static_cast<gfxAtsuiFont*>(aFontList.ElementAt(i).get());
if (font->TestCharacterMap(aCh))
return font;
}
return nsnull;
}
- // search through pref fonts for a character, return nsnull if no matching pref font
- already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
-
- already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
+ // search through pref fonts for a character, return nsnull if no matching pref font
+ already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
+
+ already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
+
+ void UpdateFontList();
protected:
static PRBool FindATSUFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure);
PRUint32 GuessMaximumStringLength();
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -46,28 +46,28 @@
#include "gfxPoint.h"
#include "gfxFontUtils.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "gfxSkipChars.h"
#include "gfxRect.h"
#include "nsExpirationTracker.h"
-#include "nsMathUtils.h"
-#include "nsBidiUtils.h"
#ifdef DEBUG
#include <stdio.h>
#endif
class gfxContext;
class gfxTextRun;
class nsIAtom;
class gfxFont;
class gfxFontGroup;
+class gfxUserFontSet;
+class gfxUserFontData;
#define FONT_STYLE_NORMAL 0
#define FONT_STYLE_ITALIC 1
#define FONT_STYLE_OBLIQUE 2
#define FONT_WEIGHT_NORMAL 400
#define FONT_WEIGHT_BOLD 700
@@ -135,87 +135,108 @@ struct THEBES_API gfxFontStyle {
(systemFont == other.systemFont) &&
(familyNameQuirks == other.familyNameQuirks) &&
(weight == other.weight) &&
(langGroup.Equals(other.langGroup)) &&
(sizeAdjust == other.sizeAdjust);
}
};
-
class gfxFontEntry {
public:
THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry)
gfxFontEntry(const nsAString& aName) :
- mName(aName), mCmapInitialized(PR_FALSE)
+ mName(aName), mIsProxy(PR_FALSE), mIsValid(PR_TRUE),
+ mIsBadUnderlineFont(PR_FALSE),
+ mCmapInitialized(PR_FALSE), mUserFontData(nsnull)
{ }
gfxFontEntry(const gfxFontEntry& aEntry) :
- mName(aEntry.mName), mItalic(aEntry.mItalic), mFixedPitch(aEntry.mFixedPitch),
- mUnicodeFont(aEntry.mUnicodeFont), mSymbolFont(aEntry.mSymbolFont), mTrueType(aEntry.mTrueType),
- mIsType1(aEntry.mIsType1), mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
- mCharacterMap(aEntry.mCharacterMap)
+ mName(aEntry.mName), mItalic(aEntry.mItalic),
+ mFixedPitch(aEntry.mFixedPitch), mUnicodeFont(aEntry.mUnicodeFont),
+ mSymbolFont(aEntry.mSymbolFont), mTrueType(aEntry.mTrueType),
+ mIsType1(aEntry.mIsType1), mIsProxy(aEntry.mIsProxy),
+ mIsValid(aEntry.mIsValid), mIsBadUnderlineFont(aEntry.mIsBadUnderlineFont),
+ mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
+ mCharacterMap(aEntry.mCharacterMap), mUserFontData(aEntry.mUserFontData)
{ }
virtual ~gfxFontEntry();
// unique name for the face, *not* the family
const nsString& Name() const { return mName; }
PRInt32 Weight() { return mWeight; }
PRBool IsFixedPitch() { return mFixedPitch; }
PRBool IsItalic() { return mItalic; }
- PRBool IsBold() { return mWeight >= 6; } // bold == weights 600 and above
+ PRBool IsBold() { return mWeight >= 600; } // bold == weights 600 and above
inline PRBool HasCharacter(PRUint32 ch) {
if (mCharacterMap.test(ch))
return PR_TRUE;
return TestCharacterMap(ch);
}
virtual PRBool TestCharacterMap(PRUint32 aCh);
virtual nsresult ReadCMAP() { return 0; }
- nsString mName;
+ nsString mName;
PRPackedBool mItalic : 1;
PRPackedBool mFixedPitch : 1;
PRPackedBool mUnicodeFont : 1;
PRPackedBool mSymbolFont : 1;
PRPackedBool mTrueType : 1;
PRPackedBool mIsType1 : 1;
+ PRPackedBool mIsProxy : 1;
+ PRPackedBool mIsValid : 1;
+
+ PRPackedBool mIsBadUnderlineFont : 1;
PRUint16 mWeight;
+ PRUint16 mStretch;
PRPackedBool mCmapInitialized;
gfxSparseBitSet mCharacterMap;
+ gfxUserFontData* mUserFontData;
+
+protected:
+ gfxFontEntry() :
+ mIsProxy(PR_FALSE), mIsValid(PR_TRUE),
+ mCmapInitialized(PR_FALSE), mUserFontData(nsnull)
+ { }
};
class gfxFontFamily {
public:
THEBES_INLINE_DECL_REFCOUNTING(gfxFontFamily)
gfxFontFamily(const nsAString& aName) :
mName(aName) { }
virtual ~gfxFontFamily() { }
const nsString& Name() { return mName; }
- // choose a specific face to match a style using CSS font matching rules (weight matching occurs here)
- gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, PRBool& aNeedsBold);
+ // choose a specific face to match a style using CSS font matching
+ // rules (weight matching occurs here)
+ gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
+ PRBool& aNeedsBold);
protected:
- // fills in an array with weights of faces that match style, returns number of weights in array
- virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontStyle& aFontStyle) { return PR_FALSE; }
+ // fills in an array with weights of faces that match style, returns
+ // number of weights in array
+ virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
+ const gfxFontStyle& aFontStyle)
+ { return PR_FALSE; }
nsString mName;
};
struct gfxTextRange {
gfxTextRange(PRUint32 aStart, PRUint32 aEnd) : start(aStart), end(aEnd) { }
PRUint32 Length() const { return end - start; }
nsRefPtr<gfxFont> font;
@@ -346,17 +367,17 @@ public:
// returns INVALID_WIDTH => not a contained glyph
// Otherwise the glyph has no before-bearing or vertical bearings,
// and the result is its width measured from the baseline origin, in
// appunits.
PRUint16 GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID) const {
return mContainedGlyphWidths.Get(aGlyphID);
}
-
+
PRBool IsGlyphKnown(PRUint32 aGlyphID) const {
return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
mTightGlyphExtents.GetEntry(aGlyphID) != nsnull;
}
PRBool IsGlyphKnownWithTightExtents(PRUint32 aGlyphID) const {
return mTightGlyphExtents.GetEntry(aGlyphID) != nsnull;
}
@@ -633,17 +654,17 @@ public:
virtual void SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID,
PRBool aNeedTight, gfxGlyphExtents *aExtents);
// This is called by the default Draw() implementation above.
virtual PRBool SetupCairoFont(gfxContext *aContext) = 0;
PRBool IsSyntheticBold() { return mSyntheticBoldOffset != 0; }
PRUint32 GetSyntheticBoldOffset() { return mSyntheticBoldOffset; }
-
+
gfxFontEntry *GetFontEntry() { return mFontEntry.get(); }
PRBool HasCharacter(PRUint32 ch) {
if (!mIsValid)
return PR_FALSE;
return mFontEntry->HasCharacter(ch);
}
protected:
@@ -670,17 +691,17 @@ public:
// Flags in the mask 0x0000F000 are reserved for per-platform fonts
// Flags in the mask 0x00000FFF are set by the textrun creator.
enum {
CACHE_TEXT_FLAGS = 0xF0000000,
USER_TEXT_FLAGS = 0x0FFF0000,
PLATFORM_TEXT_FLAGS = 0x0000F000,
TEXTRUN_TEXT_FLAGS = 0x00000FFF,
SETTABLE_FLAGS = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
-
+
/**
* When set, the text string pointer used to create the text run
* is guaranteed to be available during the lifetime of the text run.
*/
TEXT_IS_PERSISTENT = 0x0001,
/**
* When set, the text is known to be all-ASCII (< 128).
*/
@@ -1380,16 +1401,19 @@ public:
// appunits width of the ligature part; includes before-spacing
// when the part is at the start of the ligature, and after-spacing
// when the part is as the end of the ligature
gfxFloat mPartWidth;
PRPackedBool mClipBeforePart;
PRPackedBool mClipAfterPart;
};
+
+ // user font set generation when text run was created
+ PRUint64 GetUserFontSetGeneration() { return mUserFontSetGeneration; }
#ifdef DEBUG
// number of entries referencing this textrun in the gfxTextRunWordCache
PRUint32 mCachedWords;
void Dump(FILE* aOutput);
#endif
@@ -1483,26 +1507,25 @@ private:
void *mUserData;
gfxFontGroup *mFontGroup; // addrefed
gfxSkipChars mSkipChars;
nsExpirationState mExpirationState;
PRUint32 mAppUnitsPerDevUnit;
PRUint32 mFlags;
PRUint32 mCharacterCount;
PRUint32 mHashCode;
+ PRUint64 mUserFontSetGeneration; // user font set generation when text run created
};
class THEBES_API gfxFontGroup : public gfxTextRunFactory {
protected:
- gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle);
+ gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nsnull);
public:
- virtual ~gfxFontGroup() {
- mFonts.Clear();
- }
+ virtual ~gfxFontGroup();
virtual gfxFont *GetFontAt(PRInt32 i) {
return static_cast<gfxFont*>(mFonts[i]);
}
virtual PRUint32 FontListLength() const {
return mFonts.Length();
}
@@ -1514,30 +1537,18 @@ public:
const gfxFontStyle *GetStyle() const { return &mStyle; }
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle) = 0;
/**
* The listed characters should not be passed in to MakeTextRun and should
* be treated as invisible and zero-width.
*/
- static PRBool IsInvalidChar(PRUnichar ch) {
- if (ch >= 32) {
- return ch == 0x0085/*NEL*/ ||
- ((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
- (ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/ ||
- IS_BIDI_CONTROL_CHAR(ch)));
- }
- // We could just blacklist all control characters, but it seems better
- // to only blacklist the ones we know cause problems for native font
- // engines.
- return ch == 0x0B || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' ||
- (ch >= 0x1c && ch <= 0x1f);
- }
-
+ static PRBool IsInvalidChar(PRUnichar ch);
+
/**
* Make a textrun for an empty string. This is fast; if you call it,
* don't bother caching the result.
*/
gfxTextRun *MakeEmptyTextRun(const Parameters *aParams, PRUint32 aFlags);
/**
* Make a textrun for a single ASCII space. This is fast; if you call it,
* don't bother caching the result.
@@ -1562,17 +1573,17 @@ public:
const Parameters *aParams, PRUint32 aFlags) = 0;
/* helper function for splitting font families on commas and
* calling a function for each family to fill the mFonts array
*/
typedef PRBool (*FontCreationCallback) (const nsAString& aName,
const nsACString& aGenericName,
void *closure);
- static PRBool ForEachFont(const nsAString& aFamilies,
+ /*static*/ PRBool ForEachFont(const nsAString& aFamilies,
const nsACString& aLangGroup,
FontCreationCallback fc,
void *closure);
PRBool ForEachFont(FontCreationCallback fc, void *closure);
const nsString& GetFamilies() { return mFamilies; }
// This returns the preferred underline for this font group.
@@ -1590,37 +1601,50 @@ public:
already_AddRefed<gfxFont> FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFont *aPrevMatchedFont);
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh) { return nsnull; }
virtual already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh) { return nsnull; }
void ComputeRanges(nsTArray<gfxTextRange>& mRanges, const PRUnichar *aString, PRUint32 begin, PRUint32 end);
+ gfxUserFontSet* GetUserFontSet();
+ void SetUserFontSet(gfxUserFontSet *aUserFontSet);
+
+ // With downloadable fonts, the composition of the font group can change as fonts are downloaded
+ // for each change in state of the user font set, the generation value is bumped to avoid picking up
+ // previously created text runs in the text run word cache. For font groups based on stylesheets
+ // with no @font-face rule, this always returns 0.
+ PRUint64 GetGeneration();
+
+ virtual void UpdateFontList() { }
protected:
nsString mFamilies;
gfxFontStyle mStyle;
nsTArray< nsRefPtr<gfxFont> > mFonts;
gfxFloat mUnderlineOffset;
+ gfxUserFontSet* mUserFontSet;
+ PRUint64 mCurrGeneration; // track the current user font set generation, rebuild font list if needed
+
// Init this font group's font metrics. If there no bad fonts, you don't need to call this.
// But if there are one or more bad fonts which have bad underline offset,
// you should call this with the *first* bad font.
void InitMetricsForBadFont(gfxFont* aBadFont);
/* If aResolveGeneric is true, then CSS/Gecko generic family names are
* replaced with preferred fonts.
*
* If aResolveFontName is true then fc() is called only for existing fonts
* and with actual font names. If false then fc() is called with each
* family name in aFamilies (after resolving CSS/Gecko generic family names
* if aResolveGeneric).
*/
- static PRBool ForEachFontInternal(const nsAString& aFamilies,
+ /*static*/ PRBool ForEachFontInternal(const nsAString& aFamilies,
const nsACString& aLangGroup,
PRBool aResolveGeneric,
PRBool aResolveFontName,
FontCreationCallback fc,
void *closure);
static PRBool FontResolverProc(const nsAString& aName, void *aClosure);
--- a/gfx/thebes/public/gfxFontTest.h
+++ b/gfx/thebes/public/gfxFontTest.h
@@ -39,16 +39,17 @@
#define GFX_FONT_TEST_H
#include "nsString.h"
#include "nsTArray.h"
#include "cairo.h"
#include "gfxFont.h"
+#include "gfxUserFontSet.h"
struct THEBES_API gfxFontTestItem {
gfxFontTestItem(const nsCString& fontName,
cairo_glyph_t *cglyphs, int nglyphs)
: platformFont(fontName)
{
glyphs = new cairo_glyph_t[nglyphs];
memcpy (glyphs, cglyphs, sizeof(cairo_glyph_t) * nglyphs);
--- a/gfx/thebes/public/gfxFontUtils.h
+++ b/gfx/thebes/public/gfxFontUtils.h
@@ -307,43 +307,58 @@ public:
const PRUint8 *buf = (PRUint8*) aBuf;
PRUint32 index = aIndex << 1;
return (buf[index] << 8) | buf[index+1];
}
static inline PRUint32
ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
{
- return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
+ return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
+ (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
}
static nsresult
- ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
+ ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength,
+ gfxSparseBitSet& aCharacterMap);
static nsresult
- ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
+ ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength,
+ gfxSparseBitSet& aCharacterMap);
static nsresult
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
+
+#ifdef XP_WIN
+ // given a TrueType/OpenType data file, produce a EOT-format header
+ // for use with Windows T2Embed API AddFontResource type API's
+ // effectively hide existing fonts with matching names aHeaderLen is
+ // the size of the header buffer on input, the actual size of the
+ // EOT header on output aIsCFF returns whether the font has PS style
+ // glyphs or not (as opposed to TrueType glyphs)
+ static nsresult
+ MakeEOTHeader(nsIFile *aFontData, nsTArray<PRUint8> *aHeader, PRBool *aIsCFF);
+#endif
static inline bool IsJoiner(PRUint32 ch) {
return (ch == 0x200C ||
ch == 0x200D ||
ch == 0x2060);
}
static inline bool IsInvalid(PRUint32 ch) {
return (ch == 0xFFFD);
}
static PRUint8 CharRangeBit(PRUint32 ch);
// for a given font list pref name, set up a list of font names
- static void GetPrefsFontList(const char *aPrefName, nsTArray<nsString>& aFontList);
+ static void GetPrefsFontList(const char *aPrefName,
+ nsTArray<nsString>& aFontList);
};
// helper class for loading in font info spaced out at regular intervals
class gfxFontInfoLoader {
public:
@@ -395,17 +410,18 @@ public:
} else {
mState = stateTimerOnInterval;
timerInterval = mInterval;
}
InitLoader();
// start timer
- mTimer->InitWithFuncCallback(LoaderTimerCallback, this, aDelay, nsITimer::TYPE_REPEATING_SLACK);
+ mTimer->InitWithFuncCallback(LoaderTimerCallback, this, aDelay,
+ nsITimer::TYPE_REPEATING_SLACK);
}
// cancel the timer and cleanup
void CancelLoader() {
if (mState == stateInitial)
return;
mState = stateTimerOff;
if (mTimer) {
--- a/gfx/thebes/public/gfxOS2Fonts.h
+++ b/gfx/thebes/public/gfxOS2Fonts.h
@@ -90,17 +90,17 @@ private:
PRUint32 mSpaceGlyph;
int mHinting;
PRBool mAntialias;
};
class THEBES_API gfxOS2FontGroup : public gfxFontGroup {
public:
- gfxOS2FontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle);
+ gfxOS2FontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle, gfxUserFontSet *aUserFontSet);
virtual ~gfxOS2FontGroup();
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
// create and initialize the textRun using FreeType font
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
--- a/gfx/thebes/public/gfxOS2Platform.h
+++ b/gfx/thebes/public/gfxOS2Platform.h
@@ -66,17 +66,18 @@ public:
nsStringArray& aListOfFonts);
nsresult UpdateFontList();
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure, PRBool& aAborted);
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle
+ gfxUserFontSet *aUserFontSet);
// Given a string and a font we already have, find the font that
// supports the most code points and most closely resembles aFont.
// This simple version involves looking at the fonts on the machine to see
// which code points they support.
already_AddRefed<gfxOS2Font> FindFontForChar(PRUint32 aCh, gfxOS2Font *aFont);
// return true if it's already known that we don't have a font for this char
--- a/gfx/thebes/public/gfxPangoFonts.h
+++ b/gfx/thebes/public/gfxPangoFonts.h
@@ -68,17 +68,18 @@ public:
~gfxPangoFontEntry() {}
};
class THEBES_API gfxPangoFontGroup : public gfxFontGroup {
public:
gfxPangoFontGroup (const nsAString& families,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet);
virtual ~gfxPangoFontGroup ();
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
// Create and initialize a textrun using Pango
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
--- a/gfx/thebes/public/gfxPlatform.h
+++ b/gfx/thebes/public/gfxPlatform.h
@@ -54,16 +54,20 @@
typedef void* cmsHPROFILE;
typedef void* cmsHTRANSFORM;
class gfxImageSurface;
class gfxFont;
class gfxFontGroup;
struct gfxFontStyle;
+class gfxUserFontSet;
+struct gfxDownloadedFontData;
+class gfxFontEntry;
+class nsIURI;
// pref lang id's for font prefs
// !!! needs to match the list of pref font.default.xx entries listed in all.js !!!
enum eFontPrefLang {
eFontPrefLang_Western = 0,
eFontPrefLang_CentEuro = 1,
eFontPrefLang_Japanese = 2,
@@ -179,17 +183,40 @@ public:
* If the name doesn't in the system, aFamilyName will be empty string, but not failed.
*/
virtual nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) = 0;
/**
* Create the appropriate platform font group
*/
virtual gfxFontGroup *CreateFontGroup(const nsAString& aFamilies,
- const gfxFontStyle *aStyle) = 0;
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet) = 0;
+
+
+ /**
+ * Look up a local platform font using the full font face name (needed to support @font-face src local() )
+ */
+ virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName) { return nsnull; }
+
+ /**
+ * Activate a platform font (needed to support @font-face src url() )
+ *
+ * Note: MakePlatformFont implementation is responsible for removing font file data, since data may need to
+ * persist beyond this call.
+ */
+ virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData) { return nsnull; }
+
+ /**
+ * Whether to allow downloadable fonts via @font-face rules
+ */
+ virtual PRBool DownloadableFontsEnabled();
+
+ // check whether format is supported on a platform or not (if unclear, returns true)
+ virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags) { return PR_FALSE; }
void GetPrefFonts(const char *aLangGroup, nsString& array, PRBool aAppendUnicode = PR_TRUE);
/**
* Iterate over pref fonts given a list of lang groups. For a single lang
* group, multiple pref fonts are possible. If error occurs, returns PR_FALSE,
* PR_TRUE otherwise. Callback returns PR_FALSE to abort process.
*/
--- a/gfx/thebes/public/gfxPlatformGtk.h
+++ b/gfx/thebes/public/gfxPlatformGtk.h
@@ -74,17 +74,18 @@ public:
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure, PRBool& aAborted);
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet);
#ifndef MOZ_PANGO
FontFamily *FindFontFamily(const nsAString& aName);
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
#endif
static double DPI() {
if (sDPI < 0.0) {
--- a/gfx/thebes/public/gfxPlatformMac.h
+++ b/gfx/thebes/public/gfxPlatformMac.h
@@ -61,17 +61,24 @@ public:
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure, PRBool& aAborted);
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet);
+
+ gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
+
+ gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
+
+ PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
nsresult GetFontList(const nsACString& aLangGroup,
const nsACString& aGenericFamily,
nsStringArray& aListOfFonts);
nsresult UpdateFontList();
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
void GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxUserFontSet.h
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** 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 Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Daggett <jdaggett@mozilla.com>
+ *
+ * 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 ***** */
+
+#ifndef GFX_USER_FONT_SET_H
+#define GFX_USER_FONT_SET_H
+
+#include "gfxTypes.h"
+#include "gfxFont.h"
+#include "gfxFontUtils.h"
+#include "nsRefPtrHashtable.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsIURI.h"
+#include "nsIFile.h"
+
+class nsIURI;
+class gfxMixedFontFamily;
+
+// parsed CSS @font-face rule information
+// lifetime: from when @font-face rule processed until font is loaded
+struct gfxFontFaceSrc {
+ PRPackedBool mIsLocal; // url or local
+ nsString mLocalName; // full font name if local
+ nsCOMPtr<nsIURI> mURI; // uri if url
+
+ // format hint flags, union of all possible formats
+ // (e.g. TrueType, EOT, SVG, etc.)
+ // see FLAG_FORMAT_* enum values below
+ PRUint32 mFormatFlags;
+};
+
+// data needed to initialize platform font
+// After download completes, platform-specific code is responsible for
+// removing temp file and managing cache token. Depending on the
+// platform, these may need to persist after the platform font has been
+// created.
+// lifetime: time during which font is downloaded and active
+struct gfxDownloadedFontData {
+ nsCOMPtr<nsIFile> mFontFile; // file containing font data
+ nsCOMPtr<nsISupports> mDownloader; // need to a ref to this to prevent file from being deleted
+
+ // format hint flags, union of all possible formats
+ PRUint32 mFormatFlags; // opentype, truetype, svg, etc. (if known)
+};
+
+// subclassed by loader code to contain needed context info
+// lifetime: user font set lifetime
+class gfxFontLoaderContext {
+public:
+ gfxFontLoaderContext() { }
+ virtual ~gfxFontLoaderContext() { }
+};
+
+// subclassed to store platform-specific code cleaned out when font entry is deleted
+// lifetime: from when platform font is created until it is deactivated
+class gfxUserFontData {
+public:
+ gfxUserFontData() { }
+ virtual ~gfxUserFontData() { }
+};
+
+// initially contains a set of proxy font entry objects, replaced with
+// platform/user fonts as downloaded
+
+class gfxMixedFontFamily : public gfxFontFamily {
+
+public:
+ gfxMixedFontFamily(const nsAString& aName)
+ : gfxFontFamily(aName)
+ { }
+
+ virtual ~gfxMixedFontFamily() { }
+
+ void AddFontEntry(gfxFontEntry *aFontEntry) {
+ nsRefPtr<gfxFontEntry> fe = aFontEntry;
+ mAvailableFonts.AppendElement(fe);
+ }
+
+ void ReplaceFontEntry(gfxFontEntry *aOldFontEntry, gfxFontEntry *aNewFontEntry)
+ {
+ PRUint32 numFonts = mAvailableFonts.Length();
+ for (PRUint32 i = 0; i < numFonts; i++) {
+ gfxFontEntry *fe = mAvailableFonts[i];
+ if (fe == aOldFontEntry) {
+ mAvailableFonts[i] = aNewFontEntry;
+ return;
+ }
+ }
+ }
+
+ void RemoveFontEntry(gfxFontEntry *aFontEntry)
+ {
+ PRUint32 numFonts = mAvailableFonts.Length();
+ for (PRUint32 i = 0; i < numFonts; i++) {
+ gfxFontEntry *fe = mAvailableFonts[i];
+ if (fe == aFontEntry) {
+ mAvailableFonts.RemoveElementAt(i);
+ return;
+ }
+ }
+ }
+
+ // temp method to determine if all proxies are loaded
+ PRBool AllLoaded()
+ {
+ PRUint32 numFonts = mAvailableFonts.Length();
+ for (PRUint32 i = 0; i < numFonts; i++) {
+ gfxFontEntry *fe = mAvailableFonts[i];
+ if (fe->mIsProxy)
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+ }
+
+ nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
+
+protected:
+ PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
+ const gfxFontStyle& aFontStyle);
+
+};
+
+class gfxProxyFontEntry;
+
+class THEBES_API gfxUserFontSet {
+
+public:
+ class LoaderContext;
+ typedef PRBool (*LoaderCallback) (gfxFontEntry *aFontToLoad, nsIURI *aSrcURL,
+ LoaderContext *aContextData);
+
+ class LoaderContext {
+ public:
+ LoaderContext(LoaderCallback aLoader)
+ : mUserFontSet(nsnull), mLoaderProc(aLoader) { }
+ virtual ~LoaderContext() { }
+
+ gfxUserFontSet* mUserFontSet;
+ LoaderCallback mLoaderProc;
+ };
+
+ THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
+
+ gfxUserFontSet(LoaderContext *aContext);
+ virtual ~gfxUserFontSet();
+
+ enum {
+ // no flags ==> unknown
+ FLAG_FORMAT_OPENTYPE = 1,
+ FLAG_FORMAT_TRUETYPE = 2,
+ FLAG_FORMAT_TRUETYPE_AAT = 4,
+ FLAG_FORMAT_EOT = 8,
+ FLAG_FORMAT_SVG = 16
+ };
+
+ enum LoadStatus {
+ STATUS_LOADING = 0,
+ STATUS_LOADED,
+ STATUS_FORMAT_NOT_SUPPORTED,
+ STATUS_ERROR,
+ STATUS_END_OF_LIST
+ };
+
+
+ // add in a font face
+ // weight, stretch - 0 == unknown, [1, 9] otherwise
+ // italic style = constants in gfxFont.h (e.g. FONT_STYLE_NORMAL)
+ // TODO: support for unicode ranges not yet implemented
+ void AddFontFace(const nsAString& aFamilyName,
+ const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
+ PRUint32 aWeight = 0,
+ PRUint32 aStretch = 0,
+ PRUint32 aItalicStyle = 0,
+ gfxSparseBitSet *aUnicodeRanges = nsnull);
+
+ // lookup a font entry for a given style, returns null if not loaded
+ gfxFontEntry *FindFontEntry(const nsAString& aName,
+ const gfxFontStyle& aFontStyle, PRBool& aNeedsBold);
+
+ // when download has been completed, pass back data here
+ // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
+ // returns true if platform font creation sucessful (or local()
+ // reference was next in line)
+ PRBool OnLoadComplete(gfxFontEntry *aFontToLoad,
+ const gfxDownloadedFontData& aFontData,
+ nsresult aDownloadStatus);
+
+ // generation - each time a face is loaded, generation is
+ // incremented so that the change can be recognized
+ PRUint64 GetGeneration() { return mGeneration; }
+
+protected:
+ // for a given proxy font entry, attempt to load the next resource
+ // in the src list
+ LoadStatus LoadNext(gfxProxyFontEntry *aProxyEntry);
+
+ // increment the generation on font load
+ void IncrementGeneration();
+
+ // remove family
+ void RemoveFamily(const nsAString& aFamilyName);
+
+ // font families defined by @font-face rules
+ nsRefPtrHashtable<nsStringHashKey, gfxMixedFontFamily> mFontFamilies;
+
+ PRUint64 mGeneration;
+
+ // owned by user font set obj, deleted within destructor
+ nsAutoPtr<LoaderContext> mLoaderContext;
+};
+
+// acts a placeholder until the real font is downloaded
+
+class gfxProxyFontEntry : public gfxFontEntry {
+
+public:
+ gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
+ PRUint32 aWeight,
+ PRUint32 aStretch,
+ PRUint32 aItalicStyle,
+ gfxSparseBitSet *aUnicodeRanges);
+
+ virtual ~gfxProxyFontEntry();
+
+ PRPackedBool mIsLoading;
+ nsTArray<gfxFontFaceSrc> mSrcList;
+ PRUint32 mSrcIndex; // index of loading src item
+ gfxMixedFontFamily* mFamily;
+};
+
+
+#endif /* GFX_USER_FONT_SET_H */
--- a/gfx/thebes/public/gfxWindowsFonts.h
+++ b/gfx/thebes/public/gfxWindowsFonts.h
@@ -78,17 +78,17 @@ enum gfxWindowsFontType {
* each FontEntry (maps more directly to a font face) which holds font type, charset info
* and character map info.
*/
class FontEntry;
class FontFamily : public gfxFontFamily
{
public:
FontFamily(const nsAString& aName) :
- gfxFontFamily(aName), mHasStyles(PR_FALSE), mIsBadUnderlineFont(PR_FALSE) { }
+ gfxFontFamily(aName), mIsBadUnderlineFontFamily(PR_FALSE), mHasStyles(PR_FALSE) { }
FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
private:
friend class gfxWindowsPlatform;
void FindStyleVariations();
@@ -96,48 +96,72 @@ private:
const NEWTEXTMETRICEXW *nmetrics,
DWORD fontType, LPARAM data);
protected:
PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontStyle& aFontStyle);
public:
nsTArray<nsRefPtr<FontEntry> > mVariations;
- PRPackedBool mIsBadUnderlineFont;
+ PRPackedBool mIsBadUnderlineFontFamily;
private:
- PRBool mHasStyles;
+ PRPackedBool mHasStyles;
};
class FontEntry : public gfxFontEntry
{
public:
- FontEntry(const nsString& aFaceName) :
+ FontEntry(const nsAString& aFaceName) :
gfxFontEntry(aFaceName), mFontType(GFX_FONT_TYPE_UNKNOWN),
- mIsBadUnderlineFont(PR_FALSE), mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
+ mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
mCharset(0), mUnicodeRanges(0)
{
mUnicodeFont = PR_FALSE;
mSymbolFont = PR_FALSE;
}
FontEntry(const FontEntry& aFontEntry) :
gfxFontEntry(aFontEntry),
mWindowsFamily(aFontEntry.mWindowsFamily),
mWindowsPitch(aFontEntry.mWindowsPitch),
mFontType(aFontEntry.mFontType),
- mIsBadUnderlineFont(aFontEntry.mIsBadUnderlineFont),
mForceGDI(aFontEntry.mForceGDI),
mUnknownCMAP(aFontEntry.mUnknownCMAP),
mCharset(aFontEntry.mCharset),
mUnicodeRanges(aFontEntry.mUnicodeRanges)
{
}
+ static FontEntry* CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc = 0, LOGFONTW *aLogFont = nsnull);
+
+ static void FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic);
+
+ static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, DWORD fontType)
+ {
+ gfxWindowsFontType feType;
+ if (metrics.ntmFlags & NTM_TYPE1)
+ feType = GFX_FONT_TYPE_TYPE1;
+ else if (metrics.ntmFlags & NTM_PS_OPENTYPE)
+ feType = GFX_FONT_TYPE_PS_OPENTYPE;
+ else if (metrics.ntmFlags & NTM_TT_OPENTYPE)
+ feType = GFX_FONT_TYPE_TT_OPENTYPE;
+ else if (fontType == TRUETYPE_FONTTYPE)
+ feType = GFX_FONT_TYPE_TRUETYPE;
+ else if (fontType == RASTER_FONTTYPE)
+ feType = GFX_FONT_TYPE_RASTER;
+ else if (fontType == DEVICE_FONTTYPE)
+ feType = GFX_FONT_TYPE_DEVICE;
+ else
+ feType = GFX_FONT_TYPE_UNKNOWN;
+
+ return feType;
+ }
+
PRBool IsType1() const {
return (mFontType == GFX_FONT_TYPE_TYPE1);
}
PRBool IsTrueType() const {
return (mFontType == GFX_FONT_TYPE_TRUETYPE ||
mFontType == GFX_FONT_TYPE_PS_OPENTYPE ||
mFontType == GFX_FONT_TYPE_TT_OPENTYPE);
@@ -227,26 +251,22 @@ public:
return PR_FALSE;
}
PRBool SupportsRange(PRUint8 range) {
return mUnicodeRanges[range];
}
- // whether this font family is in "bad" underline offset blacklist.
- PRBool IsBadUnderlineFont() { return mIsBadUnderlineFont != 0; }
-
PRBool TestCharacterMap(PRUint32 aCh);
PRUint8 mWindowsFamily;
PRUint8 mWindowsPitch;
gfxWindowsFontType mFontType;
- PRPackedBool mIsBadUnderlineFont : 1;
PRPackedBool mForceGDI : 1;
PRPackedBool mUnknownCMAP : 1;
std::bitset<256> mCharset;
std::bitset<128> mUnicodeRanges;
};
/**********************************************************************
@@ -312,17 +332,17 @@ private:
*
* class gfxWindowsFontGroup
*
**********************************************************************/
class THEBES_API gfxWindowsFontGroup : public gfxFontGroup {
public:
- gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle);
+ gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle, gfxUserFontSet *aUserFontSet);
virtual ~gfxWindowsFontGroup();
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
@@ -344,18 +364,20 @@ public:
virtual gfxWindowsFont *GetFontAt(PRInt32 i);
void GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list);
void FamilyListToArrayList(const nsString& aFamilies,
const nsCString& aLangGroup,
nsTArray<nsRefPtr<FontEntry> > *list);
+ void UpdateFontList();
protected:
+ void InitFontList();
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const char *aString, PRUint32 aLength);
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
void InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
--- a/gfx/thebes/public/gfxWindowsPlatform.h
+++ b/gfx/thebes/public/gfxWindowsPlatform.h
@@ -70,17 +70,33 @@ public:
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure, PRBool& aAborted);
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle);
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet);
+
+ /**
+ * Look up a local platform font using the full font face name (needed to support @font-face src local() )
+ */
+ virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
+
+ /**
+ * Activate a platform font (needed to support @font-face src url() )
+ */
+ virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
+
+ /**
+ * Check whether format is supported on a platform or not (if unclear, returns true)
+ */
+ virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
/* Given a string and a font we already have find the font that
* supports the most code points and most closely resembles aFont
*
* this involves looking at the fonts on your machine and seeing which
* code points they support as well as looking at things like the font
* family, style, weight, etc.
*/
--- a/gfx/thebes/src/Makefile.in
+++ b/gfx/thebes/src/Makefile.in
@@ -33,16 +33,17 @@ CPPSRCS = \
gfxMatrix.cpp \
gfxPath.cpp \
gfxPattern.cpp \
gfxPlatform.cpp \
gfxRect.cpp \
gfxSkipChars.cpp \
gfxTextRunCache.cpp \
gfxTextRunWordCache.cpp \
+ gfxUserFontSet.cpp \
$(NULL)
EXTRA_DSO_LDOPTS += \
$(MOZ_CAIRO_LIBS) \
$(MOZ_UNICHARUTIL_LIBS) \
$(XPCOM_LIBS) \
$(NSPR_LIBS) \
$(ZLIB_LIBS) \
--- a/gfx/thebes/src/gfxAtsuiFonts.cpp
+++ b/gfx/thebes/src/gfxAtsuiFonts.cpp
@@ -53,16 +53,17 @@
#include "gfxFontTest.h"
#include "gfxFontUtils.h"
#include "cairo-quartz.h"
#include "gfxQuartzSurface.h"
#include "gfxQuartzFontCache.h"
+#include "gfxUserFontSet.h"
#include "nsUnicodeRange.h"
// Uncomment this to dump all text runs created to stdout
// #define DUMP_TEXT_RUNS
#ifdef DUMP_TEXT_RUNS
static PRLogModuleInfo *gAtsuiTextRunLog = PR_NewLogModule("atsuiTextRun");
@@ -268,18 +269,18 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFo
InitMetrics(aFontID, aFontRef);
return;
}
mAdjustedSize = size;
}
mMetrics.emHeight = size;
- mMetrics.maxAscent = NS_ceil(atsMetrics.ascent * size);
- mMetrics.maxDescent = NS_ceil(- (atsMetrics.descent * size));
+ mMetrics.maxAscent = atsMetrics.ascent * size;
+ mMetrics.maxDescent = - (atsMetrics.descent * size);
mMetrics.maxHeight = mMetrics.maxAscent + mMetrics.maxDescent;
if (mMetrics.maxHeight - mMetrics.emHeight > 0)
mMetrics.internalLeading = mMetrics.maxHeight - mMetrics.emHeight;
else
mMetrics.internalLeading = 0.0;
mMetrics.externalLeading = atsMetrics.leading * size;
@@ -317,17 +318,17 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFo
PRUint32 glyphID;
mMetrics.spaceWidth = GetCharWidth(' ', &glyphID);
mSpaceGlyph = glyphID;
mMetrics.zeroOrAveCharWidth = GetCharWidth('0', &glyphID);
if (glyphID == 0) // no zero in this font
mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth;
- SanitizeMetrics(&mMetrics, GetFontEntry()->FamilyEntry()->IsBadUnderlineFontFamily());
+ SanitizeMetrics(&mMetrics, GetFontEntry()->mIsBadUnderlineFont);
#if 0
fprintf (stderr, "Font: %p size: %f (fixed: %d)", this, size, gfxQuartzFontCache::SharedFontCache()->IsFixedPitch(aFontID));
fprintf (stderr, " emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
fprintf (stderr, " maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance);
fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.externalLeading, mMetrics.internalLeading);
fprintf (stderr, " spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight);
fprintf (stderr, " uOff: %f uSize: %f stOff: %f stSize: %f suOff: %f suSize: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize, mMetrics.superscriptOffset, mMetrics.subscriptOffset);
@@ -435,16 +436,21 @@ gfxAtsuiFont::SetupGlyphExtents(gfxConte
metrics.topLeft.y <= mMetrics.maxDescent) {
PRUint32 appUnitsWidth =
PRUint32(NS_ceil((metrics.topLeft.x + metrics.width)*appUnitsPerDevUnit));
if (appUnitsWidth < gfxGlyphExtents::INVALID_WIDTH) {
aExtents->SetContainedGlyphWidthAppUnits(aGlyphID, PRUint16(appUnitsWidth));
return;
}
}
+#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
+ if (!aNeedTight) {
+ ++gGlyphExtentsSetupFallBackToTight;
+ }
+#endif
double d2a = appUnitsPerDevUnit;
gfxRect bounds(metrics.topLeft.x*d2a, (metrics.topLeft.y - metrics.height)*d2a,
metrics.width*d2a, metrics.height*d2a);
aExtents->SetTightGlyphExtents(aGlyphID, bounds);
}
PRBool
@@ -496,19 +502,21 @@ GetOrMakeFont(MacOSFontEntry *aFontEntry
font = newFont;
gfxFontCache::GetCache()->AddNew(font);
}
gfxFont *f = nsnull;
font.swap(f);
return static_cast<gfxAtsuiFont *>(f);
}
+
gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
- const gfxFontStyle *aStyle)
- : gfxFontGroup(families, aStyle)
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
+ : gfxFontGroup(families, aStyle, aUserFontSet)
{
ForEachFont(FindATSUFont, this);
if (mFonts.Length() == 0) {
// XXX this will generate a list of the lang groups for which we have no
// default fonts for on the mac; we should fix this!
// Known:
// ja x-beng x-devanagari x-tamil x-geor x-ethi x-gujr x-mlym x-armn
@@ -531,17 +539,17 @@ gfxAtsuiFontGroup::gfxAtsuiFontGroup(con
}
}
mPageLang = gfxPlatform::GetFontPrefLangFor(mStyle.langGroup.get());
if (!mStyle.systemFont) {
for (PRUint32 i = 0; i < mFonts.Length(); ++i) {
gfxAtsuiFont* font = static_cast<gfxAtsuiFont*>(mFonts[i].get());
- if (font->GetFontEntry()->FamilyEntry()->IsBadUnderlineFontFamily()) {
+ if (font->GetFontEntry()->mIsBadUnderlineFont) {
gfxFloat first = mFonts[0]->GetMetrics().underlineOffset;
gfxFloat bad = font->GetMetrics().underlineOffset;
mUnderlineOffset = PR_MIN(first, bad);
break;
}
}
}
}
@@ -549,35 +557,48 @@ gfxAtsuiFontGroup::gfxAtsuiFontGroup(con
PRBool
gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure)
{
gfxAtsuiFontGroup *fontGroup = (gfxAtsuiFontGroup*) closure;
const gfxFontStyle *fontStyle = fontGroup->GetStyle();
- gfxQuartzFontCache *fc = gfxQuartzFontCache::SharedFontCache();
PRBool needsBold;
- MacOSFontEntry *fe = fc->FindFontForFamily(aName, fontStyle, needsBold);
+ MacOSFontEntry *fe = nsnull;
+
+ // first, look up in the user font set
+ gfxUserFontSet *fs = fontGroup->GetUserFontSet();
+ gfxFontEntry *gfe;
+ if (fs && (gfe = fs->FindFontEntry(aName, *fontStyle, needsBold))) {
+ // assume for now platform font if not SVG
+ fe = static_cast<MacOSFontEntry*> (gfe);
+ }
+
+ // nothing in the user font set ==> check system fonts
+ if (!fe) {
+ gfxQuartzFontCache *fc = gfxQuartzFontCache::SharedFontCache();
+ fe = fc->FindFontForFamily(aName, fontStyle, needsBold);
+ }
if (fe && !fontGroup->HasFont(fe->GetFontID())) {
nsRefPtr<gfxAtsuiFont> font = GetOrMakeFont(fe, fontStyle, needsBold);
if (font) {
fontGroup->mFonts.AppendElement(font);
}
}
return PR_TRUE;
}
gfxFontGroup *
gfxAtsuiFontGroup::Copy(const gfxFontStyle *aStyle)
{
- return new gfxAtsuiFontGroup(mFamilies, aStyle);
+ return new gfxAtsuiFontGroup(mFamilies, aStyle, mUserFontSet);
}
static void
SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
{
TextBreakLocatorRef locator;
OSStatus status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakClusterMask,
&locator);
@@ -928,16 +949,29 @@ gfxAtsuiFontGroup::WhichSystemFontSuppor
nsRefPtr<gfxAtsuiFont> atsuiFont = GetOrMakeFont(fe, &mStyle, PR_FALSE); // ignore bolder considerations in system fallback case...
nsRefPtr<gfxFont> font = (gfxFont*) atsuiFont;
return font.forget();
}
return nsnull;
}
+void
+gfxAtsuiFontGroup::UpdateFontList()
+{
+ // if user font set is set, check to see if font list needs updating
+ if (mUserFontSet && mCurrGeneration != GetGeneration()) {
+ // xxx - can probably improve this to detect when all fonts were found, so no need to update list
+ mFonts.Clear();
+ ForEachFont(FindATSUFont, this);
+ mCurrGeneration = GetGeneration();
+ }
+}
+
+
/**
* Simple wrapper for ATSU "direct data arrays"
*/
class AutoLayoutDataArrayPtr {
public:
AutoLayoutDataArrayPtr(ATSULineRef aLineRef,
ATSUDirectDataSelector aSelector)
: mLineRef(aLineRef), mSelector(aSelector)
@@ -1387,18 +1421,18 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRu
#ifdef DUMP_TEXT_RUNS
NS_ConvertUTF16toUTF8 str(layoutString, aLengthInTextRun);
NS_ConvertUTF16toUTF8 families(mFamilies);
PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,\
("InitTextRun %p fontgroup %p (%s) lang: %s len %d TEXTRUN \"%s\" ENDTEXTRUN\n",
aRun, this, families.get(), mStyle.langGroup.get(), aLengthInTextRun, str.get()) );
PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,
- ("InitTextRun font: %s\n",
- NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get()) );
+ ("InitTextRun font: %s user font set: %p (%8.8x)\n",
+ NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get(), mUserFontSet, PRUint32(mCurrGeneration)) );
#endif
if (aRun->GetFlags() & TEXT_DISABLE_OPTIONAL_LIGATURES) {
status = ATSUCreateAndCopyStyle(mainStyle, &mainStyle);
if (status == noErr) {
stylesToDispose.AppendElement(mainStyle);
DisableCommonLigatures(mainStyle);
}
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -44,17 +44,19 @@
#include "gfxFont.h"
#include "gfxPlatform.h"
#include "prtypes.h"
#include "gfxTypes.h"
#include "gfxContext.h"
#include "gfxFontMissingGlyphs.h"
+#include "gfxUserFontSet.h"
#include "nsMathUtils.h"
+#include "nsBidiUtils.h"
#include "cairo.h"
#include "gfxFontTest.h"
#include "nsCRT.h"
gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
@@ -69,34 +71,38 @@ static PRUint32 gFontCount = 0;
static PRUint32 gGlyphExtentsCount = 0;
static PRUint32 gGlyphExtentsWidthsTotalSize = 0;
static PRUint32 gGlyphExtentsSetupEagerSimple = 0;
static PRUint32 gGlyphExtentsSetupEagerTight = 0;
static PRUint32 gGlyphExtentsSetupLazyTight = 0;
static PRUint32 gGlyphExtentsSetupFallBackToTight = 0;
#endif
-gfxFontEntry::~gfxFontEntry() {
-
+gfxFontEntry::~gfxFontEntry()
+{
+ if (mUserFontData)
+ delete mUserFontData;
}
PRBool gfxFontEntry::TestCharacterMap(PRUint32 aCh) {
if (!mCmapInitialized) ReadCMAP();
return mCharacterMap.test(aCh);
}
gfxFontEntry *gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle, PRBool& aNeedsBold)
{
gfxFontEntry *weightList[10] = { 0 };
aNeedsBold = PR_FALSE;
- FindWeightsForStyle(weightList, aFontStyle);
+ PRBool foundWeights = FindWeightsForStyle(weightList, aFontStyle);
+ if (!foundWeights)
+ return nsnull;
PRInt8 baseWeight, weightDistance;
aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
// 500 isn't quite bold so we want to treat it as 400 if we don't
// have a 500 weight
if (baseWeight == 5 && weightDistance == 0) {
// If we have a 500 weight then use it
@@ -851,20 +857,42 @@ gfxGlyphExtents::SetTightGlyphExtents(PR
if (!entry)
return;
entry->x = aExtentsAppUnits.pos.x;
entry->y = aExtentsAppUnits.pos.y;
entry->width = aExtentsAppUnits.size.width;
entry->height = aExtentsAppUnits.size.height;
}
-gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
+gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet)
: mFamilies(aFamilies), mStyle(*aStyle), mUnderlineOffset(UNDERLINE_OFFSET_NOT_SET)
{
+ mUserFontSet = nsnull;
+ SetUserFontSet(aUserFontSet);
+}
+gfxFontGroup::~gfxFontGroup() {
+ mFonts.Clear();
+ SetUserFontSet(nsnull);
+}
+
+
+PRBool
+gfxFontGroup::IsInvalidChar(PRUnichar ch) {
+ if (ch >= 32) {
+ return ch == 0x0085/*NEL*/ ||
+ ((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
+ (ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/ ||
+ IS_BIDI_CONTROL_CHAR(ch)));
+ }
+ // We could just blacklist all control characters, but it seems better
+ // to only blacklist the ones we know cause problems for native font
+ // engines.
+ return ch == 0x0B || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' ||
+ (ch >= 0x1c && ch <= 0x1f);
}
PRBool
gfxFontGroup::ForEachFont(FontCreationCallback fc,
void *closure)
{
return ForEachFontInternal(mFamilies, mStyle.langGroup,
PR_TRUE, PR_TRUE, fc, closure);
@@ -984,21 +1012,28 @@ gfxFontGroup::ForEachFontInternal(const
}
if (generic) {
ForEachFontInternal(family, lang, PR_FALSE, aResolveFontName, fc, closure);
} else if (!family.IsEmpty()) {
NS_LossyConvertUTF16toASCII gf(genericFamily);
if (aResolveFontName) {
ResolveData data(fc, gf, closure);
- PRBool aborted;
- gfxPlatform *pf = gfxPlatform::GetPlatform();
- nsresult rv = pf->ResolveFontName(family,
+ PRBool aborted, needsBold;
+ nsresult rv;
+
+ if (mUserFontSet && mUserFontSet->FindFontEntry(family, mStyle, needsBold)) {
+ gfxFontGroup::FontResolverProc(family, &data);
+ rv = NS_OK;
+ } else {
+ gfxPlatform *pf = gfxPlatform::GetPlatform();
+ rv = pf->ResolveFontName(family,
gfxFontGroup::FontResolverProc,
&data, aborted);
+ }
if (NS_FAILED(rv) || aborted)
return PR_FALSE;
}
else {
if (!fc(family, gf, closure))
return PR_FALSE;
}
}
@@ -1084,17 +1119,17 @@ gfxFontGroup::FindFontForChar(PRUint32 a
nsRefPtr<gfxFont> font = GetFontAt(i);
if (font->HasCharacter(aCh))
return font.forget();
}
// if match, return
if (selectedFont)
return selectedFont.forget();
-
+
// if character is in Private Use Area, don't do matching against pref or system fonts
if ((aCh >= 0xE000 && aCh <= 0xF8FF) || (aCh >= 0xF0000 && aCh <= 0x10FFFD))
return nsnull;
// 2. search pref fonts
if ((selectedFont = WhichPrefFontSupportsChar(aCh))) {
return selectedFont.forget();
}
@@ -1164,16 +1199,39 @@ void gfxFontGroup::ComputeRanges(nsTArra
r.font = font;
aRanges.AppendElement(r);
}
}
}
aRanges[aRanges.Length()-1].end = len;
}
+gfxUserFontSet*
+gfxFontGroup::GetUserFontSet()
+{
+ return mUserFontSet;
+}
+
+void
+gfxFontGroup::SetUserFontSet(gfxUserFontSet *aUserFontSet)
+{
+ NS_IF_RELEASE(mUserFontSet);
+ mUserFontSet = aUserFontSet;
+ NS_IF_ADDREF(mUserFontSet);
+ mCurrGeneration = GetGeneration();
+}
+
+PRUint64
+gfxFontGroup::GetGeneration()
+{
+ if (!mUserFontSet)
+ return 0;
+ return mUserFontSet->GetGeneration();
+}
+
#define DEFAULT_PIXEL_FONT_SIZE 16.0f
gfxFontStyle::gfxFontStyle() :
style(FONT_STYLE_NORMAL), systemFont(PR_TRUE), familyNameQuirks(PR_FALSE),
weight(FONT_WEIGHT_NORMAL), size(DEFAULT_PIXEL_FONT_SIZE),
langGroup(NS_LITERAL_CSTRING("x-western")), sizeAdjust(0.0f)
{
@@ -1326,16 +1384,18 @@ gfxTextRun::gfxTextRun(const gfxTextRunF
PRUnichar *newText = reinterpret_cast<PRUnichar*>(mCharacterGlyphs + aLength);
memcpy(newText, aText, aLength*sizeof(PRUnichar));
mText.mDouble = newText;
}
}
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
AccountStorageForTextRun(this, 1);
#endif
+
+ mUserFontSetGeneration = mFontGroup->GetGeneration();
}
gfxTextRun::~gfxTextRun()
{
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
AccountStorageForTextRun(this, -1);
#endif
NS_RELEASE(mFontGroup);
--- a/gfx/thebes/src/gfxFontUtils.cpp
+++ b/gfx/thebes/src/gfxFontUtils.cpp
@@ -40,16 +40,18 @@
#include "nsIPref.h" // for pref handling code
#include "nsServiceManagerUtils.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsISupportsPrimitives.h"
+#include "nsIStreamBufferAccess.h"
+#include "nsILocalFile.h"
#define NO_RANGE_FOUND 126 // bit 126 in the font unicode ranges is required to be 0
/* Unicode subrange table
* from: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
*
* Use something like:
* perl -pi -e 's/^(\d+)\s+([\dA-Fa-f]+)\s+-\s+([\dA-Fa-f]+)\s+\b(.*)/ { \1, 0x\2, 0x\3,\"\4\" },/' < unicoderanges.txt
@@ -464,9 +466,563 @@ void gfxFontUtils::GetPrefsFontList(cons
// append it to the list
aFontList.AppendElement(fontname);
++p;
}
}
+// for now, this is only needed on Windows
+#ifdef XP_WIN
+
+// TrueType/OpenType table handling code
+
+// need byte aligned structs
+#pragma pack(1)
+
+struct AutoSwap_PRUint16 {
+ operator PRUint16() { return NS_SWAP16(value); }
+ operator PRUint32() { return NS_SWAP16(value); }
+ PRUint16 value;
+};
+
+struct AutoSwap_PRInt16 {
+ operator PRInt16() { return NS_SWAP16(value); }
+ operator PRUint32() { return NS_SWAP16(value); }
+ PRInt16 value;
+};
+
+struct AutoSwap_PRUint32 {
+ operator PRUint32() { return NS_SWAP32(value); }
+ PRUint32 value;
+};
+
+struct AutoSwap_PRUint64 {
+ operator PRUint64() { return NS_SWAP64(value); }
+ PRUint64 value;
+};
+
+struct SFNTHeader {
+ AutoSwap_PRUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0.
+ AutoSwap_PRUint16 numTables; // Number of tables.
+ AutoSwap_PRUint16 searchRange; // (Maximum power of 2 <= numTables) x 16.
+ AutoSwap_PRUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
+ AutoSwap_PRUint16 rangeShift; // NumTables x 16-searchRange.
+};
+
+struct TableDirEntry {
+ AutoSwap_PRUint32 tag; // 4 -byte identifier.
+ AutoSwap_PRUint32 checkSum; // CheckSum for this table.
+ AutoSwap_PRUint32 offset; // Offset from beginning of TrueType font file.
+ AutoSwap_PRUint32 length; // Length of this table.
+};
+
+struct HeadTable {
+ enum {
+ HEAD_MAGIC_NUMBER = 0x5F0F3CF5
+ };
+
+ AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
+ AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
+ AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
+ AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
+ AutoSwap_PRUint16 flags;
+ AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
+ AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
+ AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
+ AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
+ AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
+ AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
+ AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
+ AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
+ AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
+ AutoSwap_PRInt16 fontDirectionHint;
+ AutoSwap_PRInt16 indexToLocFormat;
+ AutoSwap_PRInt16 glyphDataFormat;
+};
+
+// name table has a header, followed by name records, followed by string data
+struct NameHeader {
+ AutoSwap_PRUint16 format; // Format selector (=0).
+ AutoSwap_PRUint16 count; // Number of name records.
+ AutoSwap_PRUint16 stringOffset; // Offset to start of string storage (from start of table)
+};
+
+struct NameRecord {
+ AutoSwap_PRUint16 platformID; // Platform ID
+ AutoSwap_PRUint16 encodingID; // Platform-specific encoding ID
+ AutoSwap_PRUint16 languageID; // Language ID
+ AutoSwap_PRUint16 nameID; // Name ID.
+ AutoSwap_PRUint16 length; // String length (in bytes).
+ AutoSwap_PRUint16 offset; // String offset from start of storage area (in bytes).
+
+ enum {
+ NAME_ID_FAMILY = 1,
+ NAME_ID_STYLE = 2,
+ NAME_ID_FULL = 4,
+ NAME_ID_VERSION = 5,
+ PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically
+ PLATFORM_ID_MICROSOFT = 3,
+ ENCODING_ID_MICROSOFT_UNICODEBMP = 1, // with Microsoft platformID, BMP-only Unicode encoding
+ LANG_ID_MICROSOFT_EN_US = 0x0409 // with Microsoft platformID, EN US lang code
+ };
+};
+
+struct OS2Table {
+ AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
+ AutoSwap_PRInt16 xAvgCharWidth;
+ AutoSwap_PRUint16 usWeightClass;
+ AutoSwap_PRUint16 usWidthClass;
+ AutoSwap_PRUint16 fsType;
+ AutoSwap_PRInt16 ySubscriptXSize;
+ AutoSwap_PRInt16 ySubscriptYSize;
+ AutoSwap_PRInt16 ySubscriptXOffset;
+ AutoSwap_PRInt16 ySubscriptYOffset;
+ AutoSwap_PRInt16 ySuperscriptXSize;
+ AutoSwap_PRInt16 ySuperscriptYSize;
+ AutoSwap_PRInt16 ySuperscriptXOffset;
+ AutoSwap_PRInt16 ySuperscriptYOffset;
+ AutoSwap_PRInt16 yStrikeoutSize;
+ AutoSwap_PRInt16 yStrikeoutPosition;
+ AutoSwap_PRInt16 sFamilyClass;
+ PRUint8 panose[10];
+ AutoSwap_PRUint32 unicodeRange1;
+ AutoSwap_PRUint32 unicodeRange2;
+ AutoSwap_PRUint32 unicodeRange3;
+ AutoSwap_PRUint32 unicodeRange4;
+ PRUint8 achVendID[4];
+ AutoSwap_PRUint16 fsSelection;
+ AutoSwap_PRUint16 usFirstCharIndex;
+ AutoSwap_PRUint16 usLastCharIndex;
+ AutoSwap_PRInt16 sTypoAscender;
+ AutoSwap_PRInt16 sTypoDescender;
+ AutoSwap_PRInt16 sTypoLineGap;
+ AutoSwap_PRUint16 usWinAscent;
+ AutoSwap_PRUint16 usWinDescent;
+ AutoSwap_PRUint32 codePageRange1;
+ AutoSwap_PRUint32 codePageRange2;
+ AutoSwap_PRInt16 sxHeight;
+ AutoSwap_PRInt16 sCapHeight;
+ AutoSwap_PRUint16 usDefaultChar;
+ AutoSwap_PRUint16 usBreakChar;
+ AutoSwap_PRUint16 usMaxContext;
+};
+
+// Embedded OpenType (EOT) handling
+// needed for dealing with downloadable fonts on Windows
+//
+// EOT version 0x00020001
+// based on http://www.w3.org/Submission/2008/SUBM-EOT-20080305/
+//
+// EOT header consists of a fixed-size portion containing general font
+// info, followed by a variable-sized portion containing name data,
+// followed by the actual TT/OT font data (non-byte values are always
+// stored in big-endian format)
+//
+// EOT header is stored in *little* endian order!!
+
+struct EOTFixedHeader {
+
+ PRUint32 eotSize; // Total structure length in PRUint8s (including string and font data)
+ PRUint32 fontDataSize; // Length of the OpenType font (FontData) in PRUint8s
+ PRUint32 version; // Version number of this format - 0x00010000
+ PRUint32 flags; // Processing Flags
+ PRUint8 panose[10]; // The PANOSE value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#pan
+ PRUint8 charset; // In Windows this is derived from TEXTMETRIC.tmCharSet. This value specifies the character set of the font. DEFAULT_CHARSET (0x01) indicates no preference. - See http://msdn2.microsoft.com/en-us/library/ms534202.aspx
+ PRUint8 italic; // If the bit for ITALIC is set in OS/2.fsSelection, the value will be 0x01 - See http://www.microsoft.com/typography/otspec/os2.htm#fss
+ PRUint32 weight; // The weight value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#wtc
+ PRUint16 fsType; // Type flags that provide information about embedding permissions - See http://www.microsoft.com/typography/otspec/os2.htm#fst
+ PRUint16 magicNumber; // Magic number for EOT file - 0x504C. Used to check for data corruption.
+ PRUint32 unicodeRange1; // OS/2.UnicodeRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
+ PRUint32 unicodeRange2; // OS/2.UnicodeRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
+ PRUint32 unicodeRange3; // OS/2.UnicodeRange3 (bits 64-95) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
+ PRUint32 unicodeRange4; // OS/2.UnicodeRange4 (bits 96-127) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
+ PRUint32 codePageRange1; // CodePageRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
+ PRUint32 codePageRange2; // CodePageRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
+ PRUint32 checkSumAdjustment; // head.CheckSumAdjustment - See http://www.microsoft.com/typography/otspec/head.htm
+ PRUint32 reserved[4]; // Reserved - must be 0
+ PRUint16 padding1; // Padding to maintain long alignment. Padding value must always be set to 0x0000.
+
+ enum {
+ EOT_VERSION = 0x00020001,
+ EOT_MAGIC_NUMBER = 0x504c,
+ EOT_DEFAULT_CHARSET = 0x01,
+ EOT_EMBED_PRINT_PREVIEW = 0x0004,
+ EOT_FAMILY_NAME_INDEX = 0, // order of names in variable portion of EOT header
+ EOT_STYLE_NAME_INDEX = 1,
+ EOT_VERSION_NAME_INDEX = 2,
+ EOT_FULL_NAME_INDEX = 3,
+ EOT_NUM_NAMES = 4
+ };
+
+};
+
+// EOT variable-sized header (version 0x00020001 - contains 4 name
+// fields, each with the structure):
+//
+// // number of bytes in the name array
+// PRUint16 size;
+// // array of UTF-16 chars, total length = <size> bytes
+// // note: english version of name record string
+// PRUint8 name[size];
+//
+// This structure is used for the following names, each separated by two
+// bytes of padding (always 0 with no padding after the rootString):
+//
+// familyName - based on name ID = 1
+// styleName - based on name ID = 2
+// versionName - based on name ID = 5
+// fullName - based on name ID = 4
+// rootString - used to restrict font usage to a specific domain
+//
+
+class AutoCloseFile {
+public:
+ AutoCloseFile(PRFileDesc *aFileDesc)
+ : mFile(aFileDesc) { }
+ ~AutoCloseFile() { PR_Close(mFile); }
+ PRFileDesc *mFile;
+};
+
+static PRFileDesc *
+OpenFontFile(nsIFile *aFontData)
+{
+ // open up the font file
+ nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFontData);
+ if (!localFile)
+ return nsnull;
+
+ PRFileDesc *fd;
+ nsresult rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
+ if (NS_FAILED(rv) || !fd)
+ return nsnull;
+
+ return fd;
+}
+
+static PRBool
+IsValidVersion(PRUint32 version)
+{
+ // normally 0x00010000, CFF-style OT fonts == 'OTTO' and Apple TT fonts = 'true'
+ return version == 0x10000 || version == 'OTTO' || version == 'true';
+}
+
+// copy and swap UTF-16 values, assume no surrogate pairs, can be in place
+static void
+CopySwapUTF16(PRUint16 *aInBuf, PRUint16 *aOutBuf, PRUint32 aLen)
+{
+ PRUint16 *end = aInBuf + aLen;
+ while (aInBuf < end) {
+ PRUint16 value = *aInBuf;
+ *aOutBuf = (value >> 8) | (value & 0xff) << 8;
+ aOutBuf++;
+ aInBuf++;
+ }
+}
+
+// name table stores set of name record structures, followed by
+// large block containing all the strings. name record offset and length
+// indicates the offset and length within that block.
+// http://www.microsoft.com/typography/otspec/name.htm
+struct NameRecordData {
+ PRUint32 offset;
+ PRUint32 length;
+};
+
+#if DEBUG
+static void DumpEOTHeader(PRUint8 *aHeader, PRUint32 aHeaderLen)
+{
+ PRUint32 offset = 0;
+ PRUint8 *ch = aHeader;
+
+ printf("\n\nlen == %d\n\n", aHeaderLen);
+ while (offset < aHeaderLen) {
+ printf("%7.7x ", offset);
+ int i;
+ for (i = 0; i < 16; i++) {
+ printf("%2.2x ", *ch++);
+ }
+ printf("\n");
+ offset += 16;
+ }
+}
+#endif
+
+nsresult
+gfxFontUtils::MakeEOTHeader(nsIFile *aFontData, nsTArray<PRUint8> *aHeader,
+ PRBool *aIsCFF)
+{
+ PRInt32 bytesRead;
+
+ // assume TrueType
+ *aIsCFF = PR_FALSE;
+
+ NS_ASSERTION(aHeader, "null header");
+ NS_ASSERTION(aHeader->Length() == 0, "non-empty header passed in");
+ NS_ASSERTION(aIsCFF, "null boolean ptr");
+
+ if (!aHeader->AppendElements(sizeof(EOTFixedHeader)))
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ EOTFixedHeader *eotHeader = reinterpret_cast<EOTFixedHeader*> (aHeader->Elements());
+ memset(eotHeader, 0, sizeof(EOTFixedHeader));
+
+ // open the font file
+ PRFileDesc *fd = OpenFontFile(aFontData);
+ if (!fd)
+ return NS_ERROR_FAILURE;
+
+ AutoCloseFile autoCloseFile(fd);
+
+ PRFileInfo64 fileInfo;
+ if (PR_GetOpenFileInfo64(fd, &fileInfo) != PR_SUCCESS
+ || fileInfo.size > PRInt64(0xFFFFFFFF))
+ return NS_ERROR_FAILURE;
+
+ PRUint32 fontDataSize = PRUint32(fileInfo.size);
+
+ // set up header fields
+ eotHeader->fontDataSize = fontDataSize;
+ eotHeader->version = EOTFixedHeader::EOT_VERSION;
+ eotHeader->flags = 0; // don't specify any special processing
+ eotHeader->charset = EOTFixedHeader::EOT_DEFAULT_CHARSET;
+ eotHeader->fsType = EOTFixedHeader::EOT_EMBED_PRINT_PREVIEW;
+ eotHeader->magicNumber = EOTFixedHeader::EOT_MAGIC_NUMBER;
+
+ // read in the sfnt header
+ SFNTHeader sfntHeader;
+ bytesRead = PR_Read(fd, &sfntHeader, sizeof(SFNTHeader));
+ if (bytesRead != sizeof(SFNTHeader) || !IsValidVersion(sfntHeader.sfntVersion))
+ return NS_ERROR_FAILURE;
+
+ // iterate through the table headers to find the head, name and OS/2 tables
+ PRBool foundHead = PR_FALSE, foundOS2 = PR_FALSE, foundName = PR_FALSE, foundGlyphs = PR_FALSE;
+ PRUint32 headOffset, headLen, nameOffset, nameLen, os2Offset, os2Len;
+ PRUint32 i, numTables;
+
+ numTables = sfntHeader.numTables;
+ for (i = 0; i < numTables; i++) {
+ TableDirEntry dirEntry;
+ bytesRead = PR_Read(fd, &dirEntry, sizeof(TableDirEntry));
+ if (bytesRead != sizeof(TableDirEntry))
+ return NS_ERROR_FAILURE;
+
+ switch (dirEntry.tag) {
+
+ case 'head':
+ foundHead = PR_TRUE;
+ headOffset = dirEntry.offset;
+ headLen = dirEntry.length;
+ if (headLen < sizeof(HeadTable))
+ return NS_ERROR_FAILURE;
+ break;
+
+ case 'name':
+ foundName = PR_TRUE;
+ nameOffset = dirEntry.offset;
+ nameLen = dirEntry.length;
+ break;
+
+ case 'OS/2':
+ foundOS2 = PR_TRUE;
+ os2Offset = dirEntry.offset;
+ os2Len = dirEntry.length;
+ break;
+
+ case 'glyf': // TrueType-style quadratic glyph table
+ foundGlyphs = PR_TRUE;
+ break;
+
+ case 'CFF ': // PS-style cubic glyph table
+ foundGlyphs = PR_TRUE;
+ *aIsCFF = PR_TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ if (foundHead && foundName && foundOS2 && foundGlyphs)
+ break;
+ }
+
+ // require these three tables on Windows
+ if (!foundHead || !foundName || !foundOS2)
+ return NS_ERROR_FAILURE;
+
+ // read in the data from those tables
+ PROffset64 offset;
+
+ // -- head table data
+ HeadTable headData;
+ offset = PR_Seek64(fd, PROffset64(headOffset), PR_SEEK_SET);
+ if (offset == -1)
+ return NS_ERROR_FAILURE;
+ bytesRead = PR_Read(fd, &headData, sizeof(HeadTable));
+ if (bytesRead != sizeof(HeadTable) || headData.magicNumber != HeadTable::HEAD_MAGIC_NUMBER)
+ return NS_ERROR_FAILURE;
+
+ eotHeader->checkSumAdjustment = headData.checkSumAdjustment;
+
+ // -- name table data
+
+ // -- first, read name table header
+ NameHeader nameHeader;
+
+ offset = PR_Seek64(fd, PROffset64(nameOffset), PR_SEEK_SET);
+ if (offset == -1)
+ return NS_ERROR_FAILURE;
+ bytesRead = PR_Read(fd, &nameHeader, sizeof(NameHeader));
+ if (bytesRead != sizeof(NameHeader))
+ return NS_ERROR_FAILURE;
+
+ // -- seek point is now at the start of name records
+
+ // -- iterate through name records, look for specific name ids with
+ // matching platform/encoding/etc. and store offset/lengths
+ NameRecordData names[EOTFixedHeader::EOT_NUM_NAMES] = {0};
+ PRUint32 nameCount = nameHeader.count;
+
+ for (i = 0; i < nameCount; i++) {
+ NameRecord nameRecord;
+
+ bytesRead = PR_Read(fd, &nameRecord, sizeof(NameRecord));
+ if (bytesRead != sizeof(NameRecord))
+ return NS_ERROR_FAILURE;
+
+ // looking for Microsoft English US name strings, skip others
+ if (PRUint32(nameRecord.platformID) != NameRecord::PLATFORM_ID_MICROSOFT ||
+ PRUint32(nameRecord.encodingID) != NameRecord::ENCODING_ID_MICROSOFT_UNICODEBMP ||
+ PRUint32(nameRecord.languageID) != NameRecord::LANG_ID_MICROSOFT_EN_US)
+ continue;
+
+ switch ((PRUint32)nameRecord.nameID) {
+
+ case NameRecord::NAME_ID_FAMILY:
+ names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].offset = nameRecord.offset;
+ names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length = nameRecord.length;
+ break;
+
+ case NameRecord::NAME_ID_STYLE:
+ names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].offset = nameRecord.offset;
+ names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length = nameRecord.length;
+ break;
+
+ case NameRecord::NAME_ID_FULL:
+ names[EOTFixedHeader::EOT_FULL_NAME_INDEX].offset = nameRecord.offset;
+ names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length = nameRecord.length;
+ break;
+
+ case NameRecord::NAME_ID_VERSION:
+ names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].offset = nameRecord.offset;
+ names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length = nameRecord.length;
+ break;
+
+ default:
+ break;
+ }
+
+ if (names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length)
+ break;
+ }
+
+ if (!(names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length &&
+ names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length))
+ {
+ return NS_ERROR_FAILURE;
+ }
+
+ // -- expand buffer if needed to include variable-length portion
+ PRUint32 eotVariableLength = 0;
+ eotVariableLength = (names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length & (~1)) +
+ (names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length & (~1)) +
+ (names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length & (~1)) +
+ (names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length & (~1)) +
+ EOTFixedHeader::EOT_NUM_NAMES * (2 /* size */
+ + 2 /* padding */) +
+ 2 /* null root string size */;
+
+ if (!aHeader->AppendElements(eotVariableLength))
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // append the string data to the end of the EOT header
+ PRUint8 *eotEnd = aHeader->Elements() + sizeof(EOTFixedHeader);
+ PROffset64 strOffset;
+ PRUint32 strLen;
+
+ for (i = 0; i < EOTFixedHeader::EOT_NUM_NAMES; i++) {
+ PRUint32 namelen = names[i].length;
+ PRUint32 nameoff = names[i].offset; // offset from base of string storage
+
+ strOffset = nameOffset + PRUint32(nameHeader.stringOffset) + nameoff;
+ offset = PR_Seek64(fd, strOffset, PR_SEEK_SET);
+ if (offset == -1)
+ return NS_ERROR_FAILURE;
+
+ // output 2-byte str size
+ strLen = namelen & (~1); // UTF-16 string len must be even
+ *((PRUint16*) eotEnd) = PRUint16(strLen);
+ eotEnd += 2;
+
+ // read in actual string and swap bytes from big-endian
+ // (TrueType/OpenType) to little-endian (EOT)
+ bytesRead = PR_Read(fd, eotEnd, strLen);
+ if (PRUint32(bytesRead) != strLen)
+ return NS_ERROR_FAILURE;
+
+ // length is number of UTF-16 chars, not bytes
+ CopySwapUTF16(reinterpret_cast<PRUint16*>(eotEnd),
+ reinterpret_cast<PRUint16*>(eotEnd),
+ (strLen >> 1));
+ eotEnd += strLen;
+
+ // add 2-byte zero padding to the end of each string
+ *eotEnd++ = 0;
+ *eotEnd++ = 0;
+
+ // Note: Microsoft's WEFT tool produces name strings which
+ // include an extra null at the end of each string, in addition
+ // to the 2-byte zero padding that separates the string fields.
+ // Don't think this is important to imitate...
+ }
+
+ // append null root string size
+ *eotEnd++ = 0;
+ *eotEnd++ = 0;
+
+ NS_ASSERTION(eotEnd == aHeader->Elements() + aHeader->Length(),
+ "header length calculation incorrect");
+
+ // -- OS/2 table data
+ OS2Table os2Data;
+ offset = PR_Seek64(fd, PROffset64(os2Offset), PR_SEEK_SET);
+ if (offset == -1)
+ return NS_ERROR_FAILURE;
+ bytesRead = PR_Read(fd, &os2Data, sizeof(OS2Table));
+ if (bytesRead != sizeof(OS2Table))
+ return NS_ERROR_FAILURE;
+
+ memcpy(eotHeader->panose, os2Data.panose, sizeof(eotHeader->panose));
+
+ eotHeader->italic = (PRUint16) os2Data.fsSelection & 0x01;
+ eotHeader->weight = os2Data.usWeightClass;
+ eotHeader->unicodeRange1 = os2Data.unicodeRange1;
+ eotHeader->unicodeRange2 = os2Data.unicodeRange2;
+ eotHeader->unicodeRange3 = os2Data.unicodeRange3;
+ eotHeader->unicodeRange4 = os2Data.unicodeRange4;
+ eotHeader->codePageRange1 = os2Data.codePageRange1;
+ eotHeader->codePageRange2 = os2Data.codePageRange2;
+
+ eotHeader->eotSize = aHeader->Length() + fontDataSize;
+
+ // DumpEOTHeader(aHeader->Elements(), aHeader->Length());
+
+ return NS_OK;
+}
+
+#endif
--- a/gfx/thebes/src/gfxOS2Fonts.cpp
+++ b/gfx/thebes/src/gfxOS2Fonts.cpp
@@ -452,18 +452,19 @@ already_AddRefed<gfxOS2Font> gfxOS2Font:
return static_cast<gfxOS2Font *>(f);
}
/**********************************************************************
* class gfxOS2FontGroup
**********************************************************************/
gfxOS2FontGroup::gfxOS2FontGroup(const nsAString& aFamilies,
- const gfxFontStyle* aStyle)
- : gfxFontGroup(aFamilies, aStyle)
+ const gfxFontStyle* aStyle,
+ gfxUserFontSet *aUserFontSet)
+ : gfxFontGroup(aFamilies, aStyle, aUserFontSet)
{
#ifdef DEBUG_thebes_2
printf("gfxOS2FontGroup[%#x]::gfxOS2FontGroup(\"%s\", %#x)\n",
(unsigned)this, NS_LossyConvertUTF16toASCII(aFamilies).get(),
(unsigned)aStyle);
#endif
// check for WarpSans and as we cannot display that (yet), replace
@@ -505,17 +506,17 @@ gfxOS2FontGroup::~gfxOS2FontGroup()
{
#ifdef DEBUG_thebes_2
printf("gfxOS2FontGroup[%#x]::~gfxOS2FontGroup()\n", (unsigned)this);
#endif
}
gfxFontGroup *gfxOS2FontGroup::Copy(const gfxFontStyle *aStyle)
{
- return new gfxOS2FontGroup(mFamilies, aStyle);
+ return new gfxOS2FontGroup(mFamilies, aStyle, mUserFontSet);
}
/**
* We use this to append an LTR or RTL Override character to the start of the
* string. This forces Pango to honour our direction even if there are neutral
* characters in the string.
*/
static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
--- a/gfx/thebes/src/gfxOS2Platform.cpp
+++ b/gfx/thebes/src/gfxOS2Platform.cpp
@@ -159,19 +159,20 @@ gfxOS2Platform::ResolveFontName(const ns
nsresult
gfxOS2Platform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
}
gfxFontGroup *
gfxOS2Platform::CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle)
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
{
- return new gfxOS2FontGroup(aFamilies, aStyle);
+ return new gfxOS2FontGroup(aFamilies, aStyle, aUserFontSet);
}
already_AddRefed<gfxOS2Font>
gfxOS2Platform::FindFontForChar(PRUint32 aCh, gfxOS2Font *aFont)
{
#ifdef DEBUG_thebes
printf("gfxOS2Platform::FindFontForChar(%d, ...)\n", aCh);
#endif
--- a/gfx/thebes/src/gfxPangoFonts.cpp
+++ b/gfx/thebes/src/gfxPangoFonts.cpp
@@ -779,33 +779,34 @@ FontCallback (const nsAString& fontName,
if (sa->IndexOf(fontName) < 0) {
sa->AppendString(fontName);
}
return PR_TRUE;
}
gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
- const gfxFontStyle *aStyle)
- : gfxFontGroup(families, aStyle),
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
+ : gfxFontGroup(families, aStyle, aUserFontSet),
mBasePangoFont(nsnull), mAdjustedSize(0)
{
mFonts.AppendElements(1);
}
gfxPangoFontGroup::~gfxPangoFontGroup()
{
if (mBasePangoFont)
g_object_unref(mBasePangoFont);
}
gfxFontGroup *
gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
{
- return new gfxPangoFontGroup(mFamilies, aStyle);
+ return new gfxPangoFontGroup(mFamilies, aStyle, mUserFontSet);
}
// A string of family names suitable for fontconfig
void
gfxPangoFontGroup::GetFcFamilies(nsAString& aFcFamilies)
{
nsStringArray familyArray;
--- a/gfx/thebes/src/gfxPlatform.cpp
+++ b/gfx/thebes/src/gfxPlatform.cpp
@@ -51,16 +51,17 @@
#elif defined(XP_OS2)
#include "gfxOS2Platform.h"
#endif
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "gfxTextRunCache.h"
#include "gfxTextRunWordCache.h"
+#include "gfxUserFontSet.h"
#include "nsIPref.h"
#include "nsServiceManagerUtils.h"
#include "nsWeakReference.h"
#include "cairo.h"
#include "lcms.h"
@@ -299,16 +300,39 @@ gfxPlatform::GetFontList(const nsACStrin
}
nsresult
gfxPlatform::UpdateFontList()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
+#define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
+
+PRBool
+gfxPlatform::DownloadableFontsEnabled()
+{
+ static PRBool initialized = PR_FALSE;
+ static PRBool allowDownloadableFonts = PR_FALSE;
+
+ if (initialized == PR_FALSE) {
+ initialized = PR_TRUE;
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ if (prefs) {
+ PRBool allow;
+ nsresult rv = prefs->GetBoolPref(GFX_DOWNLOADABLE_FONTS_ENABLED, &allow);
+ if (NS_SUCCEEDED(rv))
+ allowDownloadableFonts = allow;
+ }
+ }
+
+ return allowDownloadableFonts;
+}
+
+
static void
AppendGenericFontFromPref(nsString& aFonts, const char *aLangGroup, const char *aGenericName)
{
nsresult rv;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs)
return;
--- a/gfx/thebes/src/gfxPlatformGtk.cpp
+++ b/gfx/thebes/src/gfxPlatformGtk.cpp
@@ -262,19 +262,20 @@ gfxPlatformGtk::ResolveFontName(const ns
nsresult
gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
}
gfxFontGroup *
gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle)
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
{
- return new gfxPangoFontGroup(aFamilies, aStyle);
+ return new gfxPangoFontGroup(aFamilies, aStyle, aUserFontSet);
}
#else
nsresult
gfxPlatformGtk::GetFontList(const nsACString& aLangGroup,
const nsACString& aGenericFamily,
nsStringArray& aListOfFonts)
--- a/gfx/thebes/src/gfxPlatformMac.cpp
+++ b/gfx/thebes/src/gfxPlatformMac.cpp
@@ -39,16 +39,17 @@
#include "gfxPlatformMac.h"
#include "gfxImageSurface.h"
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
#include "gfxQuartzFontCache.h"
#include "gfxAtsuiFonts.h"
+#include "gfxUserFontSet.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsServiceManagerUtils.h"
#include "nsCRT.h"
#include "lcms.h"
@@ -110,19 +111,46 @@ nsresult
gfxPlatformMac::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
gfxQuartzFontCache::SharedFontCache()->GetStandardFamilyName(aFontName, aFamilyName);
return NS_OK;
}
gfxFontGroup *
gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle)
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
+{
+ return new gfxAtsuiFontGroup(aFamilies, aStyle, aUserFontSet);
+}
+
+gfxFontEntry*
+gfxPlatformMac::LookupLocalFont(const nsAString& aFontName)
+{
+ return gfxQuartzFontCache::SharedFontCache()->LookupLocalFont(aFontName);
+}
+
+gfxFontEntry*
+gfxPlatformMac::MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData)
{
- return new gfxAtsuiFontGroup(aFamilies, aStyle);
+ return gfxQuartzFontCache::SharedFontCache()->MakePlatformFont(aProxyEntry, aFontData);
+}
+
+PRBool
+gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
+{
+ // reject based on format flags
+ if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
+ return PR_FALSE;
+ }
+
+ // reject based on filetype in URI
+
+ // otherwise, return true
+ return PR_TRUE;
}
nsresult
gfxPlatformMac::GetFontList(const nsACString& aLangGroup,
const nsACString& aGenericFamily,
nsStringArray& aListOfFonts)
{
gfxQuartzFontCache::SharedFontCache()->
--- a/gfx/thebes/src/gfxQuartzFontCache.h
+++ b/gfx/thebes/src/gfxQuartzFontCache.h
@@ -78,39 +78,40 @@ public:
const nsString& FamilyName();
PRUint32 Traits() { return mTraits; }
ATSUFontID GetFontID();
nsresult ReadCMAP();
- MacOSFamilyEntry* FamilyEntry() { return mFamily; }
protected:
+ // for use with data fonts
+ MacOSFontEntry(ATSUFontID aFontID, PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle, gfxUserFontData *aUserFontData);
+
PRUint32 mTraits;
MacOSFamilyEntry *mFamily;
+ ATSUFontID mATSUFontID;
PRPackedBool mATSUIDInitialized;
- ATSUFontID mATSUFontID;
};
// helper class for adding other family names back into font cache
class AddOtherFamilyNameFunctor;
// a single font family, referencing one or more faces
class MacOSFamilyEntry : public gfxFontFamily
{
public:
friend class gfxQuartzFontCache;
// name is canonical font family name returned from NSFontManager
- MacOSFamilyEntry(nsString &aName) :
- gfxFontFamily(aName), mOtherFamilyNamesInitialized(PR_FALSE), mHasOtherFamilyNames(PR_FALSE),
- mIsBadUnderlineFontFamily(PR_FALSE)
+ MacOSFamilyEntry(nsAString &aName) :
+ gfxFontFamily(aName), mOtherFamilyNamesInitialized(PR_FALSE), mHasOtherFamilyNames(PR_FALSE)
{}
virtual ~MacOSFamilyEntry() {}
virtual void LocalizedName(nsAString& aLocalizedName);
virtual PRBool HasOtherFamilyNames();
nsTArray<nsRefPtr<MacOSFontEntry> >& GetFontList() { return mAvailableFonts; }
@@ -127,50 +128,52 @@ public:
// iterates over faces looking for a match with a given characters
// used as part of the font fallback process
void FindFontForChar(FontSearch *aMatchData);
// read in other family names, if any, and use functor to add each into cache
virtual void ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFunctor);
// search for a specific face using the Postscript name
- MacOSFontEntry* FindFont(const nsString& aPostscriptName);
+ MacOSFontEntry* FindFont(const nsAString& aPostscriptName);
// read in cmaps for all the faces
void ReadCMAP() {
PRUint32 i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++)
mAvailableFonts[i]->ReadCMAP();
}
-
- // whether this font family is in "bad" underline offset blacklist.
- PRBool IsBadUnderlineFontFamily() { return mIsBadUnderlineFontFamily != 0; }
+ // set whether this font family is in "bad" underline offset blacklist.
+ void SetBadUnderlineFont(PRBool aIsBadUnderlineFont) {
+ PRUint32 i, numFonts = mAvailableFonts.Length();
+ for (i = 0; i < numFonts; i++)
+ mAvailableFonts[i]->mIsBadUnderlineFont = aIsBadUnderlineFont;
+ }
protected:
// add font entries into array that match specified traits, returned in array listed by weight
// i.e. aFontsForWeights[4] ==> pointer to the font entry for a 400-weight face on return
// returns true if one or more faces found
PRBool FindFontsWithTraits(gfxFontEntry* aFontsForWeights[], PRUint32 aPosTraitsMask,
PRUint32 aNegTraitsMask);
PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontStyle& aFontStyle);
nsTArray<nsRefPtr<MacOSFontEntry> > mAvailableFonts;
PRPackedBool mOtherFamilyNamesInitialized;
PRPackedBool mHasOtherFamilyNames;
- PRPackedBool mIsBadUnderlineFontFamily;
};
// special-case situation where specific faces need to be treated as separate font family
class SingleFaceFamily : public MacOSFamilyEntry
{
public:
- SingleFaceFamily(nsString &aName) :
+ SingleFaceFamily(nsAString &aName) :
MacOSFamilyEntry(aName)
{}
virtual ~SingleFaceFamily() {}
virtual void LocalizedName(nsAString& aLocalizedName);
// read in other family names, if any, and use functor to add each into cache
@@ -217,16 +220,20 @@ public:
static PRInt32 AppleWeightToCSSWeight(PRInt32 aAppleWeight);
PRBool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> > *array);
void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> >& array);
void AddOtherFamilyName(MacOSFamilyEntry *aFamilyEntry, nsAString& aOtherFamilyName);
+ gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
+
+ gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
+
private:
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
void* userArg);
static gfxQuartzFontCache *sSharedFontCache;
gfxQuartzFontCache();
@@ -239,17 +246,17 @@ private:
void InitOtherFamilyNames();
// special case font faces treated as font families (set via prefs)
void InitSingleFaceList();
// commonly used fonts for which the name table should be loaded at startup
void PreloadNamesList();
- // initialize the MacOSFamilyEntry::mIsBadUnderlineFontFamily from pref.
+ // initialize the bad underline blacklist from pref.
void InitBadUnderlineList();
// eliminate faces which have the same ATSUI id
void EliminateDuplicateFaces(const nsAString& aFamilyName);
// explicitly set font traits for all faces to fixed-pitch
void SetFixedPitch(const nsAString& aFamilyName);
@@ -288,11 +295,18 @@ private:
// flag set after InitOtherFamilyNames is called upon first name lookup miss
PRPackedBool mOtherFamilyNamesInitialized;
// data used as part of the font cmap loading process
nsTArray<nsRefPtr<MacOSFamilyEntry> > mFontFamiliesToLoad;
PRUint32 mStartIndex;
PRUint32 mIncrement;
PRUint32 mNumFamilies;
+
+ // keep track of ATS generation to prevent unneeded updates when loading downloaded fonts
+ PRUint32 mATSGeneration;
+
+ enum {
+ kATSGenerationInitial = -1
+ };
};
#endif /* GFXQUARTZFONTCACHE_H_ */
--- a/gfx/thebes/src/gfxQuartzFontCache.mm
+++ b/gfx/thebes/src/gfxQuartzFontCache.mm
@@ -39,20 +39,28 @@
#include <Carbon.h>
#import <AppKit/AppKit.h>
#include "gfxPlatformMac.h"
#include "gfxQuartzFontCache.h"
#include "gfxAtsuiFonts.h"
+#include "gfxUserFontSet.h"
#include "nsIPref.h" // for pref changes callback notification
#include "nsServiceManagerUtils.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsISimpleEnumerator.h"
+
+#include <unistd.h>
+#include <time.h>
+
// _atsFontID is private; add it in our new category to NSFont
@interface NSFont (MozillaCategory)
- (ATSUFontID)_atsFontID;
@end
// font info loader constants
static const PRUint32 kDelayBeforeLoadingCmaps = 8 * 1000; // 8secs
static const PRUint32 kIntervalBetweenLoadingCmaps = 150; // 150ms
@@ -108,22 +116,57 @@ gfxQuartzFontCache::GenerateFontListKey(
/* MacOSFontEntry */
#pragma mark-
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
PRInt32 aAppleWeight, PRUint32 aTraits, MacOSFamilyEntry *aFamily)
: gfxFontEntry(aPostscriptName), mTraits(aTraits), mFamily(aFamily), mATSUFontID(0),
mATSUIDInitialized(0)
{
- mWeight = gfxQuartzFontCache::AppleWeightToCSSWeight(aAppleWeight);
+ mWeight = gfxQuartzFontCache::AppleWeightToCSSWeight(aAppleWeight) * 100;
mItalic = (mTraits & NSItalicFontMask ? 1 : 0);
mFixedPitch = (mTraits & NSFixedPitchFontMask ? 1 : 0);
}
+MacOSFontEntry::MacOSFontEntry(ATSUFontID aFontID, PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle, gfxUserFontData *aUserFontData)
+{
+ // xxx - stretch is basically ignored for now
+
+ mATSUIDInitialized = PR_TRUE;
+ mATSUFontID = aFontID;
+ mUserFontData = aUserFontData;
+ mWeight = aWeight;
+ mStretch = aStretch;
+ mFixedPitch = PR_FALSE; // xxx - do we need this for downloaded fonts?
+ mItalic = (aItalicStyle & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+
+ mTraits = (mItalic ? NSItalicFontMask : NSUnitalicFontMask) |
+ (mFixedPitch ? NSFixedPitchFontMask : 0) |
+ (mWeight >= 600 ? NSBoldFontMask : NSUnboldFontMask);
+
+ // get the postscript name
+ OSStatus err;
+ NSString *psname = NULL;
+
+ // now lookup the Postscript name
+ err = ATSFontGetPostScriptName((ATSFontRef) aFontID, kATSOptionFlagsDefault, (CFStringRef*) (&psname));
+ if (err == noErr) {
+ GetStringForNSString(psname, mName);
+ [psname release];
+ } else {
+ mIsValid = PR_FALSE;
+#if DEBUG
+ char warnBuf[1024];
+ sprintf(warnBuf, "ATSFontGetPostScriptName err = %d", (PRInt32)err);
+ NS_WARNING(warnBuf);
+#endif
+ }
+}
+
const nsString&
MacOSFontEntry::FamilyName()
{
return mFamily->Name();
}
ATSUFontID MacOSFontEntry::GetFontID()
{
@@ -169,17 +212,24 @@ MacOSFontEntry::ReadCMAP()
if (mCmapInitialized) return NS_OK;
ATSUFontID fontID = GetFontID();
// attempt this once, if errors occur leave a blank cmap
mCmapInitialized = PR_TRUE;
status = ATSFontGetTable(fontID, 'cmap', 0, 0, 0, &size);
cmapSize = size;
- //printf( "cmap size: %s %d\n", NS_ConvertUTF16toUTF8(mName).get(), size );
+ //printf( "cmap size: %s %d", NS_ConvertUTF16toUTF8(mName).get(), size );
+#if DEBUG
+ if (status != noErr) {
+ char warnBuf[1024];
+ sprintf(warnBuf, "ATSFontGetTable returned %d for (%s)", (PRInt32)status, NS_ConvertUTF16toUTF8(mName).get());
+ NS_WARNING(warnBuf);
+ }
+#endif
NS_ENSURE_TRUE(status == noErr, NS_ERROR_FAILURE);
nsAutoTArray<PRUint8,16384> buffer;
if (!buffer.AppendElements(size))
return NS_ERROR_OUT_OF_MEMORY;
PRUint8 *cmap = buffer.Elements();
status = ATSFontGetTable(fontID, 'cmap', 0, size, cmap, &size);
@@ -293,17 +343,17 @@ static const PRUint32 kTraits_NonNormalW
MacOSFontEntry*
MacOSFamilyEntry::FindFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold)
{
return static_cast<MacOSFontEntry*> (FindFontForStyle(*aStyle, aNeedsBold));
}
MacOSFontEntry*
-MacOSFamilyEntry::FindFont(const nsString& aPostscriptName)
+MacOSFamilyEntry::FindFont(const nsAString& aPostscriptName)
{
// find the font using a simple linear search
PRUint32 numFonts = mAvailableFonts.Length();
for (PRUint32 i = 0; i < numFonts; i++) {
MacOSFontEntry *fe = mAvailableFonts[i];
if (fe->Name() == aPostscriptName)
return fe;
}
@@ -334,29 +384,29 @@ MacOSFamilyEntry::FindFontForChar(FontSe
// omitting from original windows code -- family name, lang group, pitch
// not available in current FontEntry implementation
if (aMatchData->fontToMatch) {
const gfxFontStyle *style = aMatchData->fontToMatch->GetStyle();
// italics
if (fe->IsItalic() &&
- (style->style == FONT_STYLE_ITALIC || style->style == FONT_STYLE_ITALIC)) {
+ (style->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0) {
rank += 5;
}
// weight
PRInt8 baseWeight, weightDistance;
style->ComputeWeightAndOffset(&baseWeight, &weightDistance);
// xxx - not entirely correct, the one unit of weight distance reflects
// the "next bolder/lighter face"
PRUint32 targetWeight = (baseWeight * 100) + (weightDistance * 100);
- PRUint32 entryWeight = fe->Weight() * 100;
+ PRUint32 entryWeight = fe->Weight();
if (entryWeight == targetWeight) {
rank += 5;
} else {
PRUint32 diffWeight = abs(entryWeight - targetWeight);
if (diffWeight <= 100) // favor faces close in weight
rank += 2;
}
} else {
@@ -388,17 +438,18 @@ MacOSFamilyEntry::FindFontsWithTraits(gf
for (PRUint32 i = 0; i < numFonts; i++) {
MacOSFontEntry *fe = mAvailableFonts[i];
// if traits match, add to list of fonts
PRUint32 traits = fe->Traits();
// aPosTraitsMask == 0 ==> match all
if ((!aPosTraitsMask || (traits & aPosTraitsMask)) && !(traits & aNegTraitsMask)) {
- PRInt32 weight = fe->Weight();
+ PRInt32 weight = fe->Weight() / 100;
+ NS_ASSERTION(weight >= 1 && weight <= 9, "bogus font weight value!");
// always prefer the first font for a given weight, helps deal a bit with
// families with lots of faces (e.g. Minion Pro)
if (!aFontsForWeights[weight]) {
aFontsForWeights[weight] = fe;
found = PR_TRUE;
}
}
@@ -407,23 +458,24 @@ MacOSFamilyEntry::FindFontsWithTraits(gf
}
PRBool
MacOSFamilyEntry::FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontStyle& aFontStyle)
{
// short-circuit the single face per family case
if (mAvailableFonts.Length() == 1) {
MacOSFontEntry *fe = mAvailableFonts[0];
- PRUint32 weight = fe->Weight();
+ PRUint32 weight = fe->Weight() / 100;
+ NS_ASSERTION(weight >= 1 && weight <= 9, "bogus font weight value!");
aFontsForWeights[weight] = fe;
return PR_TRUE;
}
PRBool found = PR_FALSE;
- PRBool isItalic = (aFontStyle.style == FONT_STYLE_ITALIC || aFontStyle.style == FONT_STYLE_OBLIQUE);
+ PRBool isItalic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
// match italic faces
if (isItalic) {
// first search for italic normal width fonts
found = FindFontsWithTraits(aFontsForWeights, NSItalicFontMask, kTraits_NonNormalWidthMask);
// if not found, italic any width ones
if (!found) {
@@ -624,16 +676,18 @@ void SingleFaceFamily::ReadOtherFamilyNa
/* gfxQuartzFontCache */
#pragma mark-
gfxQuartzFontCache *gfxQuartzFontCache::sSharedFontCache = nsnull;
gfxQuartzFontCache::gfxQuartzFontCache()
: mStartIndex(0), mIncrement(kNumFontsPerSlice), mNumFamilies(0)
{
+ mATSGeneration = PRUint32(kATSGenerationInitial);
+
mFontFamilies.Init(100);
mOtherFamilyNames.Init(30);
mOtherFamilyNamesInitialized = PR_FALSE;
mPrefFonts.Init(10);
InitFontList();
::ATSFontNotificationSubscribe(ATSNotification,
kATSFontNotifyOptionDefault,
@@ -647,16 +701,25 @@ gfxQuartzFontCache::gfxQuartzFontCache()
}
const PRUint32 kNonNormalTraits = NSItalicFontMask | NSBoldFontMask | NSNarrowFontMask | NSExpandedFontMask | NSCondensedFontMask | NSCompressedFontMask;
void
gfxQuartzFontCache::InitFontList()
{
+ ATSGeneration currentGeneration = ATSGeneration();
+
+ // need to ignore notifications after adding each font
+ if (mATSGeneration == currentGeneration)
+ return;
+
+ mATSGeneration = currentGeneration;
+ PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit) updating to generation: %d", mATSGeneration));
+
mFontFamilies.Clear();
mOtherFamilyNames.Clear();
mOtherFamilyNamesInitialized = PR_FALSE;
mPrefFonts.Clear();
mCodepointsWithNoFonts.reset();
CancelLoader();
// iterate over available families
@@ -913,17 +976,17 @@ gfxQuartzFontCache::InitBadUnderlineList
PRUint32 numFonts = blacklist.Length();
for (PRUint32 i = 0; i < numFonts; i++) {
PRBool found;
nsAutoString key;
GenerateFontListKey(blacklist[i], key);
MacOSFamilyEntry *familyEntry = mFontFamilies.GetWeak(key, &found);
if (familyEntry)
- familyEntry->mIsBadUnderlineFontFamily = 1;
+ familyEntry->SetBadUnderlineFont(PR_TRUE);
}
}
PRBool
gfxQuartzFontCache::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
{
MacOSFamilyEntry *family = FindFamily(aFontName);
if (family) {
@@ -1200,16 +1263,168 @@ gfxQuartzFontCache::AddOtherFamilyName(M
if (!mOtherFamilyNames.GetWeak(key, &found)) {
mOtherFamilyNames.Put(key, aFamilyEntry);
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit-otherfamily) canonical family: %s, other family: %s\n",
NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(),
NS_ConvertUTF16toUTF8(aOtherFamilyName).get()));
}
}
+gfxFontEntry*
+gfxQuartzFontCache::LookupLocalFont(const nsAString& aFontName)
+{
+ NSString *faceName = GetNSStringForString(aFontName);
+ NSFont *font = [NSFont fontWithName:faceName size:0.0];
+
+ if (font) {
+ nsAutoString availableFamilyName;
+ NSString *availableFamily = [font familyName];
+ GetStringForNSString(availableFamily, availableFamilyName);
+
+ MacOSFamilyEntry *familyEntry = FindFamily(availableFamilyName);
+ if (familyEntry) {
+ MacOSFontEntry *fontEntry = familyEntry->FindFont(aFontName);
+ return fontEntry;
+ }
+ }
+
+ // didn't find the font
+ return nsnull;
+}
+
+// grumble, another non-publised Apple API dependency (found in Webkit code)
+// activated with this value, font will not be found via system lookup routines
+// it can only be used via the created ATSUFontID
+// needed to prevent one doc from finding a font used in a separate doc
+
+enum {
+ kPrivateATSFontContextPrivate = 3
+};
+
+class MacOSUserFontData : public gfxUserFontData {
+public:
+ MacOSUserFontData(ATSFontContainerRef aContainerRef, nsIFile *aFontFile,
+ nsISupports *aDownloader)
+ : mContainerRef(aContainerRef), mFontFile(aFontFile),
+ mDownloader(aDownloader)
+ { }
+
+ virtual ~MacOSUserFontData()
+ {
+ // deactivate font
+ if (mContainerRef)
+ ATSFontDeactivate(mContainerRef, NULL, kATSOptionFlagsDefault);
+
+ if (mFontFile) {
+ mFontFile->Remove(PR_FALSE); // ignore errors
+ }
+ }
+
+ ATSFontContainerRef mContainerRef;
+ nsCOMPtr<nsIFile> mFontFile;
+
+ // maintaining a ref to this keeps temp file around or cache file pinned
+ nsCOMPtr<nsISupports> mDownloader;
+};
+
+static OSStatus
+MakeFSSpec(FSSpec *aFSSpec, NSString *path)
+{
+ FSRef fsref;
+ OSStatus err = FSPathMakeRef((UInt8*)([path fileSystemRepresentation]), &fsref, NULL);
+
+ if (err == noErr)
+ err = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, aFSSpec, NULL);
+
+ return err;
+}
+
+gfxFontEntry*
+gfxQuartzFontCache::MakePlatformFont(const gfxFontEntry *aProxyEntry,
+ const gfxDownloadedFontData* aFontData)
+{
+ OSStatus err;
+ FSSpec spec;
+ nsAutoString filePath;
+
+ NS_ASSERTION(aFontData && aFontData->mFontFile,
+ "MakePlatformFont called with null file ptr");
+
+ if (!aFontData->mFontFile)
+ return nsnull;
+
+ aFontData->mFontFile->GetPath(filePath);
+
+ NSString *path = GetNSStringForString(filePath);
+ if (!path)
+ return nsnull;
+
+ // assumption: filename is already in the form xxx.ttf, otherwise
+ // ATS will reject
+
+ err = MakeFSSpec(&spec, path);
+ if (err != noErr)
+ return nsnull;
+
+ ATSUFontID fontID;
+ ATSFontContainerRef containerRef;
+
+ err = ATSFontActivateFromFileSpecification(&spec,
+ kPrivateATSFontContextPrivate,
+ kATSFontFormatUnspecified,
+ NULL,
+ kATSOptionFlagsDoNotNotify,
+ &containerRef);
+ if (err != noErr)
+ return nsnull;
+
+ mATSGeneration = ATSGeneration();
+
+ // ignoring containers with multiple fonts, use the first face only for now
+ err = ATSFontFindFromContainer(containerRef, kATSOptionFlagsDefault, 1,
+ (ATSFontRef*)&fontID, NULL);
+ if (err != noErr)
+ return nsnull;
+
+ // font entry will own this
+ MacOSUserFontData *userFontData = new MacOSUserFontData(containerRef,
+ aFontData->mFontFile,
+ aFontData->mDownloader);
+ if (!userFontData)
+ return nsnull;
+
+ PRUint16 w = aProxyEntry->mWeight;
+ NS_ASSERTION(w >= 100 && w <= 900, "bogus font weight value!");
+
+ MacOSFontEntry *newFontEntry =
+ new MacOSFontEntry(fontID, w, aProxyEntry->mStretch,
+ (PRUint32(aProxyEntry->mItalic) ?
+ FONT_STYLE_ITALIC :
+ FONT_STYLE_NORMAL),
+ userFontData);
+
+ // if something is funky about this font, delete immediately
+ if (newFontEntry && !newFontEntry->mIsValid) {
+#if DEBUG
+ char warnBuf[1024];
+ const gfxProxyFontEntry *proxyEntry =
+ static_cast<const gfxProxyFontEntry*> (aProxyEntry);
+ sprintf(warnBuf, "downloaded font not loaded properly, removed (%s) for (%s)",
+ [path UTF8String],
+ NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get());
+ NS_WARNING(warnBuf);
+#endif
+ delete newFontEntry;
+ return nsnull;
+ }
+
+ return newFontEntry;
+}
+
+
void
gfxQuartzFontCache::InitLoader()
{
GetFontFamilyList(mFontFamiliesToLoad);
mStartIndex = 0;
mNumFamilies = mFontFamiliesToLoad.Length();
}
--- a/gfx/thebes/src/gfxTextRunWordCache.cpp
+++ b/gfx/thebes/src/gfxTextRunWordCache.cpp
@@ -108,27 +108,29 @@ public:
protected:
struct CacheHashKey {
void *mFontOrGroup;
const void *mString;
PRUint32 mLength;
PRUint32 mAppUnitsPerDevUnit;
PRUint32 mStringHash;
+ PRUint64 mUserFontSetGeneration;
PRPackedBool mIsDoubleByteText;
PRPackedBool mIsRTL;
PRPackedBool mEnabledOptionalLigatures;
PRPackedBool mOptimizeSpeed;
CacheHashKey(gfxTextRun *aBaseTextRun, void *aFontOrGroup,
PRUint32 aStart, PRUint32 aLength, PRUint32 aHash)
: mFontOrGroup(aFontOrGroup), mString(aBaseTextRun->GetTextAt(aStart)),
mLength(aLength),
mAppUnitsPerDevUnit(aBaseTextRun->GetAppUnitsPerDevUnit()),
mStringHash(aHash),
+ mUserFontSetGeneration(aBaseTextRun->GetUserFontSetGeneration()),
mIsDoubleByteText((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) == 0),
mIsRTL(aBaseTextRun->IsRightToLeft()),
mEnabledOptionalLigatures((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0),
mOptimizeSpeed((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0)
{
}
};
@@ -192,24 +194,27 @@ static PRLogModuleInfo *gWordCacheLog =
static inline PRUint32
HashMix(PRUint32 aHash, PRUnichar aCh)
{
return (aHash >> 28) ^ (aHash << 4) ^ aCh;
}
// If the substring of the textrun is rendered entirely in the first font
// of the textrun's fontgroup, then return that font. Otherwise return the
-// fontgroup.
+// fontgroup. When a user font set is in use, always return the font group.
static void *GetWordFontOrGroup(gfxTextRun *aTextRun, PRUint32 aOffset,
PRUint32 aLength)
{
+ gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
+ if (fontGroup->GetUserFontSet() != nsnull)
+ return fontGroup;
+
PRUint32 glyphRunCount;
const gfxTextRun::GlyphRun *glyphRuns = aTextRun->GetGlyphRuns(&glyphRunCount);
PRUint32 glyphRunIndex = aTextRun->FindFirstGlyphRunContaining(aOffset);
- gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
gfxFont *firstFont = fontGroup->GetFontAt(0);
if (glyphRuns[glyphRunIndex].mFont != firstFont)
return fontGroup;
PRUint32 glyphRunEnd = glyphRunIndex == glyphRunCount - 1
? aTextRun->GetLength() : glyphRuns[glyphRunIndex + 1].mCharacterOffset;
if (aOffset + aLength <= glyphRunEnd)
return firstFont;
@@ -255,26 +260,32 @@ IsWordBoundary(PRUnichar aChar)
*/
PRBool
TextRunWordCache::LookupWord(gfxTextRun *aTextRun, gfxFont *aFirstFont,
PRUint32 aStart, PRUint32 aEnd, PRUint32 aHash,
nsTArray<DeferredWord>* aDeferredWords)
{
if (aEnd <= aStart)
return PR_TRUE;
+
+ gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
- CacheHashKey key(aTextRun, aFirstFont, aStart, aEnd - aStart, aHash);
+ PRBool useFontGroup = (fontGroup->GetUserFontSet() != nsnull);
+ CacheHashKey key(aTextRun, (useFontGroup ? (void*)fontGroup : (void*)aFirstFont), aStart, aEnd - aStart, aHash);
CacheHashEntry *fontEntry = mCache.PutEntry(key);
if (!fontEntry)
return PR_FALSE;
CacheHashEntry *existingEntry = nsnull;
if (fontEntry->mTextRun) {
existingEntry = fontEntry;
+ } else if (useFontGroup) {
+ PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): added using font group", aTextRun, aStart, aEnd - aStart, aHash));
} else {
+ // test to see if this can be found using the font group instead
PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): added using font", aTextRun, aStart, aEnd - aStart, aHash));
key.mFontOrGroup = aTextRun->GetFontGroup();
CacheHashEntry *groupEntry = mCache.GetEntry(key);
if (groupEntry) {
existingEntry = groupEntry;
mCache.RawRemoveEntry(fontEntry);
PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): removed using font", aTextRun, aStart, aEnd - aStart, aHash));
fontEntry = nsnull;
@@ -299,17 +310,18 @@ TextRunWordCache::LookupWord(gfxTextRun
#ifdef DEBUG
++aTextRun->mCachedWords;
#endif
// Set up the cache entry so that if later in this textrun we hit this
// entry, we'll copy within our own textrun
fontEntry->mTextRun = aTextRun;
fontEntry->mWordOffset = aStart;
- fontEntry->mHashedByFont = PR_TRUE;
+ if (!useFontGroup)
+ fontEntry->mHashedByFont = PR_TRUE;
return PR_FALSE;
}
/**
* Processes all deferred words. Each word is copied from the source
* textrun to the output textrun. (The source may be an earlier word in the
* output textrun.) If the word was not matched by the textrun's fontgroup's
* first font, then we remove the entry we optimistically added to the cache
@@ -326,16 +338,21 @@ TextRunWordCache::FinishTextRun(gfxTextR
const nsTArray<DeferredWord>& aDeferredWords,
PRBool aSuccessful)
{
aTextRun->SetFlagBits(gfxTextRunWordCache::TEXT_IN_CACHE);
PRUint32 i;
gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
gfxFont *font = fontGroup->GetFontAt(0);
+
+ // need to use the font group when user font set is around, since
+ // the first font may change as the result of a font download
+ PRBool useFontGroup = (fontGroup->GetUserFontSet() != nsnull);
+
// copy deferred words from various sources into destination textrun
for (i = 0; i < aDeferredWords.Length(); ++i) {
const DeferredWord *word = &aDeferredWords[i];
gfxTextRun *source = word->mSourceTextRun;
if (!source) {
source = aNewRun;
}
// If the word starts inside a cluster we don't want this word
@@ -345,21 +362,21 @@ TextRunWordCache::FinishTextRun(gfxTextR
PRBool wordStartsInsideLigature =
!source->IsLigatureGroupStart(word->mSourceOffset);
if (source == aNewRun) {
// We created a cache entry for this word based on the assumption
// that the word matches GetFontAt(0). If this assumption is false,
// we need to remove that cache entry and replace it with an entry
// keyed off the fontgroup.
PRBool rekeyWithFontGroup =
- GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font;
+ GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font && !useFontGroup;
if (!aSuccessful || rekeyWithFontGroup ||
wordStartsInsideCluster || wordStartsInsideLigature) {
// We need to remove the current placeholder cache entry
- CacheHashKey key(aTextRun, font, word->mDestOffset, word->mLength,
+ CacheHashKey key(aTextRun, (useFontGroup ? (void*)fontGroup : (void*)font), word->mDestOffset, word->mLength,
word->mHash);
NS_ASSERTION(mCache.GetEntry(key),
"This entry should have been added previously!");
mCache.RemoveEntry(key);
#ifdef DEBUG
--aTextRun->mCachedWords;
#endif
PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): removed using font", aTextRun, word->mDestOffset, word->mLength, word->mHash));
@@ -454,16 +471,19 @@ MakeBlankTextRun(const void* aText, PRUi
}
gfxTextRun *
TextRunWordCache::MakeTextRun(const PRUnichar *aText, PRUint32 aLength,
gfxFontGroup *aFontGroup,
const gfxFontGroup::Parameters *aParams,
PRUint32 aFlags)
{
+ // update font list when using user fonts (assures generation is current)
+ aFontGroup->UpdateFontList();
+
if (aFontGroup->GetStyle()->size == 0) {
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
// them, and always create at least size 1 fonts, i.e. they still
// render something for size 0 fonts.
return MakeBlankTextRun(aText, aLength, aFontGroup, aParams, aFlags);
}
nsAutoPtr<gfxTextRun> textRun;
@@ -525,27 +545,30 @@ TextRunWordCache::MakeTextRun(const PRUn
}
// create textrun for unknown words
gfxTextRunFactory::Parameters params =
{ aParams->mContext, nsnull, nsnull, nsnull, 0, aParams->mAppUnitsPerDevUnit };
nsAutoPtr<gfxTextRun> newRun;
newRun = aFontGroup->MakeTextRun(tempString.Elements(), tempString.Length(),
¶ms, aFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT);
-
+
FinishTextRun(textRun, newRun, aParams, deferredWords, newRun != nsnull);
return textRun.forget();
}
gfxTextRun *
TextRunWordCache::MakeTextRun(const PRUint8 *aText, PRUint32 aLength,
gfxFontGroup *aFontGroup,
const gfxFontGroup::Parameters *aParams,
PRUint32 aFlags)
{
+ // update font list when using user fonts (assures generation is current)
+ aFontGroup->UpdateFontList();
+
if (aFontGroup->GetStyle()->size == 0) {
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
// them, and always create at least size 1 fonts, i.e. they still
// render something for size 0 fonts.
return MakeBlankTextRun(aText, aLength, aFontGroup, aParams, aFlags);
}
aFlags |= gfxTextRunFactory::TEXT_IS_8BIT;
@@ -623,16 +646,17 @@ TextRunWordCache::RemoveWord(gfxTextRun
PRUint32 aEnd, PRUint32 aHash)
{
if (aEnd <= aStart)
return;
PRUint32 length = aEnd - aStart;
CacheHashKey key(aTextRun, GetWordFontOrGroup(aTextRun, aStart, length),
aStart, length, aHash);
+
CacheHashEntry *entry = mCache.GetEntry(key);
if (entry && entry->mTextRun == aTextRun) {
// XXX would like to use RawRemoveEntry here plus some extra method
// that conditionally shrinks the hashtable
mCache.RemoveEntry(key);
#ifdef DEBUG
--aTextRun->mCachedWords;
#endif
@@ -705,17 +729,18 @@ TextRunWordCache::CacheHashEntry::KeyEqu
PRUint32 length = aKey->mLength;
gfxFontGroup *fontGroup = mTextRun->GetFontGroup();
if (!IsWordEnd(mTextRun, mWordOffset + length) ||
GetFontOrGroup(fontGroup, mHashedByFont) != aKey->mFontOrGroup ||
aKey->mAppUnitsPerDevUnit != mTextRun->GetAppUnitsPerDevUnit() ||
aKey->mIsRTL != mTextRun->IsRightToLeft() ||
aKey->mEnabledOptionalLigatures != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0) ||
- aKey->mOptimizeSpeed != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0))
+ aKey->mOptimizeSpeed != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0) ||
+ aKey->mUserFontSetGeneration != (mTextRun->GetUserFontSetGeneration()))
return PR_FALSE;
if (mTextRun->GetFlags() & gfxFontGroup::TEXT_IS_8BIT) {
const PRUint8 *text = mTextRun->GetText8Bit() + mWordOffset;
if (!aKey->mIsDoubleByteText)
return memcmp(text, aKey->mString, length) == 0;
return CompareDifferentWidthStrings(text,
static_cast<const PRUnichar *>(aKey->mString), length);
@@ -726,17 +751,22 @@ TextRunWordCache::CacheHashEntry::KeyEqu
return CompareDifferentWidthStrings(static_cast<const PRUint8 *>(aKey->mString),
text, length);
}
}
PLDHashNumber
TextRunWordCache::CacheHashEntry::HashKey(const KeyTypePointer aKey)
{
- return aKey->mStringHash + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
+ // only use lower 32 bits of generation counter in hash key,
+ // since these vary the most
+ PRUint32 fontSetGen;
+ LL_L2UI(fontSetGen, aKey->mUserFontSetGeneration);
+
+ return aKey->mStringHash + fontSetGen + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
aKey->mIsDoubleByteText + aKey->mIsRTL*2 + aKey->mEnabledOptionalLigatures*4 +
aKey->mOptimizeSpeed*8;
}
#ifdef DEBUG
PLDHashOperator PR_CALLBACK
TextRunWordCache::CacheDumpEntry(CacheHashEntry* aEntry, void* userArg)
{
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxUserFontSet.cpp
@@ -0,0 +1,404 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** 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 thebes gfx code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Daggett <jdaggett@mozilla.com>
+ *
+ * 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 ***** */
+
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG /* Allow logging in the release build */
+#endif /* MOZ_LOGGING */
+#include "prlog.h"
+
+#include "gfxUserFontSet.h"
+#include "gfxPlatform.h"
+#include "nsReadableUtils.h"
+#include "nsUnicharUtils.h"
+#include "nsVoidArray.h"
+#include "prlong.h"
+
+#ifdef PR_LOGGING
+static PRLogModuleInfo *gUserFontsLog = PR_NewLogModule("userfonts");
+#endif /* PR_LOGGING */
+
+#define LOG(args) PR_LOG(gUserFontsLog, PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(gUserFontsLog, PR_LOG_DEBUG)
+
+static PRUint64 sFontSetGeneration = LL_INIT(0, 0);
+
+// TODO: support for unicode ranges not yet implemented
+
+gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
+ PRUint32 aWeight,
+ PRUint32 aStretch,
+ PRUint32 aItalicStyle,
+ gfxSparseBitSet *aUnicodeRanges)
+ : gfxFontEntry(NS_LITERAL_STRING("Proxy")), mIsLoading(PR_FALSE)
+{
+ mIsProxy = PR_TRUE;
+ mSrcList = aFontFaceSrcList;
+ mSrcIndex = 0;
+ mWeight = aWeight;
+ mStretch = aStretch;
+ mItalic = (aItalicStyle & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+}
+
+gfxProxyFontEntry::~gfxProxyFontEntry()
+{
+
+}
+
+
+PRBool
+gfxMixedFontFamily::FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
+ const gfxFontStyle& aFontStyle)
+{
+ PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+ PRBool matchesSomething;
+
+ for (PRUint32 j = 0; j < 2; j++) {
+ matchesSomething = PR_FALSE;
+ PRUint32 numFonts = mAvailableFonts.Length();
+ // build up an array of weights that match the italicness we're looking for
+ for (PRUint32 i = 0; i < numFonts; i++) {
+ gfxFontEntry *fe = mAvailableFonts[i];
+ PRUint32 weight = fe->mWeight/100;
+ if (fe->mItalic == italic) {
+ aFontsForWeights[weight] = fe;
+ matchesSomething = PR_TRUE;
+ }
+ }
+ if (matchesSomething)
+ break;
+ italic = !italic;
+ }
+
+ return matchesSomething;
+}
+
+
+gfxUserFontSet::gfxUserFontSet(LoaderContext *aContext)
+ : mLoaderContext(aContext)
+{
+ NS_ASSERTION(mLoaderContext, "font set loader context not initialized");
+ mFontFamilies.Init(5);
+ mLoaderContext->mUserFontSet = this;
+
+ IncrementGeneration();
+}
+
+gfxUserFontSet::~gfxUserFontSet()
+{
+
+}
+
+void
+gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
+ const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
+ PRUint32 aWeight,
+ PRUint32 aStretch,
+ PRUint32 aItalicStyle,
+ gfxSparseBitSet *aUnicodeRanges)
+{
+ nsAutoString key(aFamilyName);
+ ToLowerCase(key);
+
+ PRBool found;
+
+ if (aWeight == 0)
+ aWeight = FONT_WEIGHT_NORMAL;
+
+ // stretch, italic/oblique ==> zero implies normal
+
+ gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
+ if (!family) {
+ family = new gfxMixedFontFamily(aFamilyName);
+ mFontFamilies.Put(key, family);
+ }
+
+ // construct a new face and add it into the family
+ if (family) {
+ gfxProxyFontEntry *proxyEntry =
+ new gfxProxyFontEntry(aFontFaceSrcList, aWeight, aStretch,
+ aItalicStyle, aUnicodeRanges);
+ family->AddFontEntry(proxyEntry);
+ proxyEntry->mFamily = family;
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ LOG(("userfonts (%p) added (%s) with style: %s weight: %d stretch: %d",
+ this, NS_ConvertUTF16toUTF8(aFamilyName).get(),
+ (aItalicStyle & FONT_STYLE_ITALIC ? "italic" :
+ (aItalicStyle & FONT_STYLE_OBLIQUE ? "oblique" : "normal")),
+ aWeight, aStretch));
+ }
+#endif
+ }
+}
+
+gfxFontEntry*
+gfxUserFontSet::FindFontEntry(const nsAString& aName,
+ const gfxFontStyle& aFontStyle,
+ PRBool& aNeedsBold)
+{
+ nsAutoString key(aName);
+ ToLowerCase(key);
+
+ PRBool found;
+
+ gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
+
+ // no user font defined for this name
+ if (!family)
+ return nsnull;
+
+ gfxFontEntry* fe = family->FindFontForStyle(aFontStyle, aNeedsBold);
+
+ // if not a proxy, font has already been loaded
+ if (!fe->mIsProxy)
+ return fe;
+
+ gfxProxyFontEntry *proxyEntry = static_cast<gfxProxyFontEntry*> (fe);
+
+ // if currently loading, return null for now
+ if (proxyEntry->mIsLoading)
+ return nsnull;
+
+ // hasn't been loaded yet, start the load process
+ LoadStatus status;
+
+ status = LoadNext(proxyEntry);
+
+ // if the load succeeded immediately, the font entry was replaced so
+ // search again
+ if (status == STATUS_LOADED)
+ return family->FindFontForStyle(aFontStyle, aNeedsBold);
+
+ // if either loading or an error occurred, return null
+ return nsnull;
+}
+
+
+PRBool
+gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
+ const gfxDownloadedFontData& aFontData,
+ nsresult aDownloadStatus)
+{
+ NS_ASSERTION(aFontToLoad->mIsProxy, "trying to load font data for wrong font entry type");
+
+ if (!aFontToLoad->mIsProxy)
+ return PR_FALSE;
+
+ gfxProxyFontEntry *pe = static_cast<gfxProxyFontEntry*> (aFontToLoad);
+
+ // download successful, make platform font using font data
+ if (NS_SUCCEEDED(aDownloadStatus)) {
+ gfxFontEntry *fe = gfxPlatform::GetPlatform()->MakePlatformFont(pe, &aFontData);
+ if (fe) {
+ pe->mFamily->ReplaceFontEntry(pe, fe);
+ IncrementGeneration();
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ pe->mSrcList[pe->mSrcIndex].mURI->GetSpec(fontURI);
+
+ nsAutoString filePath;
+ aFontData.mFontFile->GetPath(filePath);
+
+ LOG(("userfonts (%p) [src %d] loaded uri: (%s) file: (%s) for (%s) gen: %8.8x\n",
+ this, pe->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(filePath).get(),
+ NS_ConvertUTF16toUTF8(pe->mFamily->Name()).get(), PRUint32(mGeneration)));
+ }
+#endif
+ return PR_TRUE;
+ } else {
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ pe->mSrcList[pe->mSrcIndex].mURI->GetSpec(fontURI);
+ LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) error making platform font\n",
+ this, pe->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(pe->mFamily->Name()).get()));
+ }
+#endif
+ }
+ } else {
+ // download failed
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ pe->mSrcList[pe->mSrcIndex].mURI->GetSpec(fontURI);
+ LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) error %8.8x downloading font data\n",
+ this, pe->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(pe->mFamily->Name()).get(),
+ aDownloadStatus));
+ }
+#endif
+ }
+
+ // error occurred, load next src
+ LoadStatus status;
+
+ status = LoadNext(pe);
+ if (status == STATUS_LOADED)
+ return PR_TRUE;
+
+ return PR_FALSE;
+}
+
+
+gfxUserFontSet::LoadStatus
+gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
+{
+ PRUint32 numSrc = aProxyEntry->mSrcList.Length();
+
+ NS_ASSERTION(aProxyEntry->mSrcIndex < numSrc, "already at the end of the src list for user font");
+
+ NS_ASSERTION(mLoaderContext, "user font loader context not initialized");
+ if (!mLoaderContext)
+ return STATUS_ERROR;
+
+ if (aProxyEntry->mIsLoading) {
+ aProxyEntry->mSrcIndex++;
+ } else {
+ aProxyEntry->mIsLoading = PR_TRUE;
+ }
+
+ // load each src entry in turn, until a local face is found or a download begins successfully
+ while (aProxyEntry->mSrcIndex < numSrc) {
+ const gfxFontFaceSrc& currSrc = aProxyEntry->mSrcList[aProxyEntry->mSrcIndex];
+
+ // src local ==> lookup and load
+
+ if (currSrc.mIsLocal) {
+ gfxFontEntry *fe = gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName);
+ if (fe) {
+ aProxyEntry->mFamily->ReplaceFontEntry(aProxyEntry, fe);
+ IncrementGeneration();
+ LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
+ this, aProxyEntry->mSrcIndex,
+ NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
+ NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(),
+ PRUint32(mGeneration)));
+ return STATUS_LOADED;
+ } else {
+ LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",
+ this, aProxyEntry->mSrcIndex,
+ NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
+ NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+ }
+ }
+
+ // src url ==> start the load process
+ else {
+ if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
+ currSrc.mFormatFlags)) {
+ PRBool loadOK = mLoaderContext->mLoaderProc(aProxyEntry,
+ currSrc.mURI,
+ mLoaderContext);
+ if (loadOK) {
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ currSrc.mURI->GetSpec(fontURI);
+ LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
+ this, aProxyEntry->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+ }
+#endif
+ return STATUS_LOADING;
+ } else {
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ currSrc.mURI->GetSpec(fontURI);
+ LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) download failed\n",
+ this, aProxyEntry->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+ }
+#endif
+ }
+ } else {
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ currSrc.mURI->GetSpec(fontURI);
+ LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) format not supported\n",
+ this, aProxyEntry->mSrcIndex, fontURI.get(),
+ NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+ }
+#endif
+ }
+ }
+
+ aProxyEntry->mSrcIndex++;
+ }
+
+ // all src's failed, remove this face
+ LOG(("userfonts (%p) failed all src for (%s)\n",
+ this, NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+
+ gfxMixedFontFamily *family = aProxyEntry->mFamily;
+
+ aProxyEntry->mFamily->RemoveFontEntry(aProxyEntry);
+
+ // no more faces? remove the entire family
+ if (family->mAvailableFonts.Length() == 0) {
+ LOG(("userfonts (%p) failed all faces, remove family (%s)\n",
+ this, NS_ConvertUTF16toUTF8(family->Name()).get()));
+ RemoveFamily(family->Name());
+ }
+
+ return STATUS_END_OF_LIST;
+}
+
+
+void
+gfxUserFontSet::IncrementGeneration()
+{
+ // add one, increment again if zero
+ LL_ADD(sFontSetGeneration, sFontSetGeneration, 1);
+ if (LL_IS_ZERO(sFontSetGeneration))
+ LL_ADD(sFontSetGeneration, sFontSetGeneration, 1);
+ mGeneration = sFontSetGeneration;
+}
+
+
+void
+gfxUserFontSet::RemoveFamily(const nsAString& aFamilyName)
+{
+ nsAutoString key(aFamilyName);
+ ToLowerCase(key);
+
+ mFontFamilies.Remove(key);
+}
--- a/gfx/thebes/src/gfxWindowsFonts.cpp
+++ b/gfx/thebes/src/gfxWindowsFonts.cpp
@@ -187,31 +187,18 @@ FontFamily::FamilyAddStylesProc(const EN
FamilyAddStyleProcData *faspd = reinterpret_cast<FamilyAddStyleProcData*>(data);
FontFamily *ff = faspd->ff;
HDC hdc = faspd->dc;
// Some fonts claim to support things > 900, but we don't so clamp the sizes
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
- gfxWindowsFontType feType;
- if (metrics.ntmFlags & NTM_TYPE1)
- feType = GFX_FONT_TYPE_TYPE1;
- else if (metrics.ntmFlags & (NTM_PS_OPENTYPE))
- feType = GFX_FONT_TYPE_PS_OPENTYPE;
- else if (metrics.ntmFlags & (NTM_TT_OPENTYPE))
- feType = GFX_FONT_TYPE_TT_OPENTYPE;
- else if (fontType == TRUETYPE_FONTTYPE)
- feType = GFX_FONT_TYPE_TRUETYPE;
- else if (fontType == RASTER_FONTTYPE)
- feType = GFX_FONT_TYPE_RASTER;
- else if (fontType == DEVICE_FONTTYPE)
- feType = GFX_FONT_TYPE_DEVICE;
- else
- feType = GFX_FONT_TYPE_UNKNOWN;
+
+ gfxWindowsFontType feType = FontEntry::DetermineFontType(metrics, fontType);
FontEntry *fe = nsnull;
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
fe = ff->mVariations[i];
if (feType > fe->mFontType) {
// if the new type is better than the old one, remove the old entries
ff->mVariations.RemoveElementAt(i);
--i;
@@ -227,25 +214,24 @@ FontFamily::FamilyAddStylesProc(const EN
if (fe->mWeight == logFont.lfWeight &&
fe->mItalic == (logFont.lfItalic == 0xFF)) {
// update the charset bit here since this could be different
fe->mCharset[metrics.tmCharSet] = 1;
return 1;
}
}
- fe = new FontEntry(ff->mName);
- ff->mVariations.AppendElement(fe);
- fe->mFontType = feType;
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ logFont.lfOutPrecision = FontTypeToOutPrecision(feType);
+ fe = FontEntry::CreateFontEntry(ff->mName, feType, (logFont.lfItalic == 0xFF), (PRUint16) (logFont.lfWeight), nsnull, hdc, &logFont);
- fe->mItalic = (logFont.lfItalic == 0xFF);
- fe->mWeight = logFont.lfWeight;
+ if (!fe)
+ return 1;
- if (fe->IsType1())
- fe->mForceGDI = PR_TRUE;
+ ff->mVariations.AppendElement(fe);
// mark the charset bit
fe->mCharset[metrics.tmCharSet] = 1;
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
@@ -258,49 +244,17 @@ FontFamily::FamilyAddStylesProc(const EN
for (PRUint32 i = 0; i < 4; ++i) {
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
for (PRUint32 k = 0; k < 32; ++k) {
fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
}
}
}
- fe->mIsBadUnderlineFont = ff->mIsBadUnderlineFont;
-
- // read in the character map
- logFont.lfCharSet = DEFAULT_CHARSET;
- logFont.lfOutPrecision = FontTypeToOutPrecision(fe->mFontType);
-
- HFONT font = CreateFontIndirectW(&logFont);
-
- NS_ASSERTION(font, "This font creation should never ever ever fail");
- if (font) {
- HFONT oldFont = (HFONT)SelectObject(hdc, font);
-
- // ReadCMAP may change the values of mUnicodeFont and mSymbolFont
- if (NS_FAILED(ReadCMAP(hdc, fe))) {
- // Type1 fonts aren't necessarily Unicode but
- // this is the best guess we can make here
- if (fe->IsType1())
- fe->mUnicodeFont = PR_TRUE;
- else
- fe->mUnicodeFont = PR_FALSE;
-
- // For fonts where we failed to read the character map,
- // we can take a slow path to look up glyphs character by character
- fe->mUnknownCMAP = PR_TRUE;
-
- //printf("(fontinit-cmap) %s failed to get cmap, type1:%d \n", NS_ConvertUTF16toUTF8(fe->mFaceName).get(), (PRUint32)(fe->mIsType1));
- } else {
- //printf("(fontinit-cmap) %s cmap loaded, italic:%d, weight:%d\n", NS_ConvertUTF16toUTF8(fe->mFaceName).get(), (PRUint32)(fe->mItalic), (PRUint32)(fe->mWeight));
- }
-
- SelectObject(hdc, oldFont);
- DeleteObject(font);
- }
+ fe->mIsBadUnderlineFont = ff->mIsBadUnderlineFontFamily;
return 1;
}
// general cmap reading routines moved to gfxFontUtils.cpp
void
FontFamily::FindStyleVariations()
{
@@ -388,16 +342,112 @@ FontFamily::FindWeightsForStyle(gfxFontE
if (matchesSomething)
break;
italic = !italic;
}
return matchesSomething;
}
+FontEntry*
+FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc, LOGFONTW *aLogFont)
+{
+ LOGFONTW logFont;
+ PRBool needRelease = PR_FALSE;
+
+ // jtdfix - need to set charset, unicode ranges, pitch/family
+
+ FontEntry *fe;
+
+ fe = new FontEntry(aName);
+ fe->mFontType = aFontType;
+ fe->mUserFontData = aUserFontData;
+
+ fe->mItalic = aItalic;
+ fe->mWeight = aWeight;
+
+ if (fe->IsType1())
+ fe->mForceGDI = PR_TRUE;
+
+ if (!aLogFont) {
+ aLogFont = &logFont;
+ FontEntry::FillLogFont(aLogFont, fe, 0, aItalic);
+ }
+
+ if (!hdc) {
+ hdc = GetDC(nsnull);
+ SetGraphicsMode(hdc, GM_ADVANCED);
+ needRelease = PR_TRUE;
+ }
+
+ HFONT font = CreateFontIndirectW(aLogFont);
+
+ if (font) {
+ HFONT oldFont = (HFONT)SelectObject(hdc, font);
+
+ // ReadCMAP may change the values of mUnicodeFont and mSymbolFont
+ if (NS_FAILED(::ReadCMAP(hdc, fe))) {
+ // Type1 fonts aren't necessarily Unicode but
+ // this is the best guess we can make here
+ if (fe->IsType1())
+ fe->mUnicodeFont = PR_TRUE;
+ else
+ fe->mUnicodeFont = PR_FALSE;
+
+ // For fonts where we failed to read the character map,
+ // we can take a slow path to look up glyphs character by character
+ fe->mUnknownCMAP = PR_TRUE;
+
+ }
+
+ SelectObject(hdc, oldFont);
+ DeleteObject(font);
+ }
+
+ if (needRelease)
+ ReleaseDC(nsnull, hdc);
+
+ return fe;
+}
+
+
+void
+FontEntry::FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic)
+{
+#define CLIP_TURNOFF_FONTASSOCIATION 0x40
+
+ aLogFont->lfHeight = (LONG)-ROUND(aSize);
+
+ if (aLogFont->lfHeight == 0)
+ aLogFont->lfHeight = -1;
+
+ // Fill in logFont structure
+ aLogFont->lfWidth = 0;
+ aLogFont->lfEscapement = 0;
+ aLogFont->lfOrientation = 0;
+ aLogFont->lfUnderline = FALSE;
+ aLogFont->lfStrikeOut = FALSE;
+ aLogFont->lfCharSet = DEFAULT_CHARSET;
+ aLogFont->lfOutPrecision = FontTypeToOutPrecision(aFontEntry->mFontType);
+ aLogFont->lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
+ aLogFont->lfQuality = DEFAULT_QUALITY;
+ aLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ // always force lfItalic if we want it. Font selection code will
+ // do its best to give us an italic font entry, but if no face exists
+ // it may give us a regular one based on weight. Windows should
+ // do fake italic for us in that case.
+ aLogFont->lfItalic = aItalic;
+ aLogFont->lfWeight = aFontEntry->mWeight;
+
+ int len = PR_MIN(aFontEntry->Name().Length(), LF_FACESIZE - 1);
+ memcpy(aLogFont->lfFaceName, nsPromiseFlatString(aFontEntry->Name()).get(), len * 2);
+ aLogFont->lfFaceName[len] = '\0';
+}
+
+
PRBool
FontEntry::TestCharacterMap(PRUint32 aCh)
{
if (mUnknownCMAP) {
if (aCh > 0xFFFF)
return PR_FALSE;
// previous code was using the group style
@@ -659,50 +709,23 @@ gfxWindowsFont::ComputeMetrics()
mSpaceGlyph = glyph;
}
}
SelectObject(dc, oldFont);
ReleaseDC((HWND)nsnull, dc);
- SanitizeMetrics(mMetrics, GetFontEntry()->IsBadUnderlineFont());
+ SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
}
void
gfxWindowsFont::FillLogFont(gfxFloat aSize)
{
-#define CLIP_TURNOFF_FONTASSOCIATION 0x40
-
- mLogFont.lfHeight = (LONG)-ROUND(aSize);
-
- if (mLogFont.lfHeight == 0)
- mLogFont.lfHeight = -1;
-
- // Fill in logFont structure
- mLogFont.lfWidth = 0;
- mLogFont.lfEscapement = 0;
- mLogFont.lfOrientation = 0;
- mLogFont.lfUnderline = FALSE;
- mLogFont.lfStrikeOut = FALSE;
- mLogFont.lfCharSet = DEFAULT_CHARSET;
- mLogFont.lfOutPrecision = FontTypeToOutPrecision(GetFontEntry()->mFontType);
- mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
- mLogFont.lfQuality = DEFAULT_QUALITY;
- mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- // always force lfItalic if we want it. Font selection code will
- // do its best to give us an italic font entry, but if no face exists
- // it may give us a regular one based on weight. Windows should
- // do fake italic for us in that case.
- mLogFont.lfItalic = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
- mLogFont.lfWeight = GetFontEntry()->mWeight;
-
- int len = PR_MIN(GetName().Length(), LF_FACESIZE - 1);
- memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mFontEntry->Name()).get(), len * 2);
- mLogFont.lfFaceName[len] = '\0';
+ FontEntry::FillLogFont(&mLogFont, GetFontEntry(), aSize, (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
}
nsString
gfxWindowsFont::GetUniqueName()
{
nsString uniqueName;
@@ -801,26 +824,44 @@ AddFontNameToArray(const nsAString& aNam
if (list->IndexOf(aName) == list->NoIndex)
list->AppendElement(aName);
}
return PR_TRUE;
}
+
void
gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list)
{
nsAutoTArray<nsString, 15> fonts;
ForEachFont(AddFontNameToArray, &fonts);
PRUint32 len = fonts.Length();
for (PRUint32 i = 0; i < len; ++i) {
- nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
- list->AppendElement(fe);
+ nsRefPtr<FontEntry> fe;
+
+ // first, look up in the user font set
+ gfxFontEntry *gfe;
+ PRBool needsBold;
+ if (mUserFontSet && (gfe = mUserFontSet->FindFontEntry(fonts[i], mStyle, needsBold))) {
+ // assume for now platform font if not SVG
+ fe = static_cast<FontEntry*> (gfe);
+ }
+
+ // nothing in the user font set ==> check system fonts
+ if (!fe) {
+ fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
+ }
+
+ // if found, add to the list
+ if (fe) {
+ list->AppendElement(fe);
+ }
}
}
void
gfxWindowsFontGroup::FamilyListToArrayList(const nsString& aFamilies,
const nsCString& aLangGroup,
nsTArray<nsRefPtr<FontEntry> > *list)
{
@@ -830,18 +871,60 @@ gfxWindowsFontGroup::FamilyListToArrayLi
PRUint32 len = fonts.Length();
for (PRUint32 i = 0; i < len; ++i) {
const nsString& str = fonts[i];
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, mStyle);
list->AppendElement(fe);
}
}
-gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
- : gfxFontGroup(aFamilies, aStyle)
+gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet)
+ : gfxFontGroup(aFamilies, aStyle, aUserFontSet)
+{
+ InitFontList();
+}
+
+gfxWindowsFontGroup::~gfxWindowsFontGroup()
+{
+}
+
+gfxWindowsFont *
+gfxWindowsFontGroup::GetFontAt(PRInt32 i)
+{
+ if (!mFonts[i]) {
+ nsRefPtr<gfxWindowsFont> font =
+ gfxWindowsFont::GetOrMakeFont(mFontEntries[i], &mStyle);
+ mFonts[i] = font;
+ }
+
+ return static_cast<gfxWindowsFont*>(mFonts[i].get());
+}
+
+gfxFontGroup *
+gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
+{
+ return new gfxWindowsFontGroup(mFamilies, aStyle, mUserFontSet);
+}
+
+void
+gfxWindowsFontGroup::UpdateFontList()
+{
+ // if user font set is set, check to see if font list needs updating
+ if (mUserFontSet && mCurrGeneration != GetGeneration()) {
+ // xxx - can probably improve this to detect when all fonts were found, so no need to update list
+ mFonts.Clear();
+ mFontEntries.Clear();
+ InitFontList();
+ mCurrGeneration = GetGeneration();
+ }
+
+}
+
+void
+gfxWindowsFontGroup::InitFontList()
{
GroupFamilyListToArrayList(&mFontEntries);
mFonts.AppendElements(mFontEntries.Length());
// Ensure that the first font is usable. Precompute its metrics since
// we'll surely need them anyway.
while (mFontEntries.Length() > 0) {
@@ -887,46 +970,25 @@ gfxWindowsFontGroup::gfxWindowsFontGroup
// its mUnknownCMAP will be set to true, and HasCharacter will
// just report false for all characters, so the fact that the font
// is bogus should not cause problems.
mFonts.AppendElements(mFontEntries.Length());
}
if (!mStyle.systemFont) {
for (PRUint32 i = 0; i < mFontEntries.Length(); ++i) {
- if (mFontEntries[i]->IsBadUnderlineFont()) {
+ if (mFontEntries[i]->mIsBadUnderlineFont) {
gfxFloat first = GetFontAt(0)->GetMetrics().underlineOffset;
gfxFloat bad = GetFontAt(i)->GetMetrics().underlineOffset;
mUnderlineOffset = PR_MIN(first, bad);
break;
}
}
}
-}
-gfxWindowsFontGroup::~gfxWindowsFontGroup()
-{
-}
-
-gfxWindowsFont *
-gfxWindowsFontGroup::GetFontAt(PRInt32 i)
-{
- if (!mFonts[i]) {
- nsRefPtr<gfxWindowsFont> font =
- gfxWindowsFont::GetOrMakeFont(mFontEntries[i], &mStyle);
- mFonts[i] = font;
- }
-
- return static_cast<gfxWindowsFont*>(mFonts[i].get());
-}
-
-gfxFontGroup *
-gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
-{
- return new gfxWindowsFontGroup(mFamilies, aStyle);
}
static PRBool
CanTakeFastPath(PRUint32 aFlags)
{
// Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't
// We need to always use Uniscribe for RTL text, in case glyph mirroring is required
return (aFlags &
--- a/gfx/thebes/src/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/src/gfxWindowsPlatform.cpp
@@ -44,24 +44,28 @@
#include "gfxWindowsSurface.h"
#include "nsUnicharUtils.h"
#include "nsIPref.h"
#include "nsServiceManagerUtils.h"
#include "nsIWindowsRegKey.h"
+#include "nsILocalFile.h"
+#include "plbase64.h"
#include "gfxWindowsFonts.h"
+#include "gfxUserFontSet.h"
#include <string>
+#include <time.h>
#include "lcms.h"
-//#define DEBUG_CMAP_SIZE 1
+static void InitializeFontEmbeddingProcs();
// font info loader constants
static const PRUint32 kDelayBeforeLoadingCmaps = 8 * 1000; // 8secs
static const PRUint32 kIntervalBetweenLoadingCmaps = 150; // 150ms
static const PRUint32 kNumFontsPerSlice = 10; // read in info 10 fonts at a time
static __inline void
BuildKeyNameFromFontName(nsAString &aName)
@@ -91,16 +95,18 @@ gfxWindowsPlatform::gfxWindowsPlatform()
UpdateFontList();
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
pref->RegisterCallback("font.", PrefChangedCallback, this);
pref->RegisterCallback("font.name-list.", PrefChangedCallback, this);
pref->RegisterCallback("intl.accept_languages", PrefChangedCallback, this);
// don't bother unregistering. We'll get shutdown after the pref service
+
+ InitializeFontEmbeddingProcs();
}
gfxWindowsPlatform::~gfxWindowsPlatform()
{
}
already_AddRefed<gfxASurface>
gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size,
@@ -314,17 +320,17 @@ gfxWindowsPlatform::InitBadUnderlineList
PRBool aborted;
nsAutoString resolved;
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
if (resolved.IsEmpty())
continue;
FontFamily *ff = FindFontFamily(resolved);
if (!ff)
continue;
- ff->mIsBadUnderlineFont = 1;
+ ff->mIsBadUnderlineFontFamily = 1;
}
}
nsresult
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
aFamilyName.Truncate();
PRBool aborted;
@@ -512,19 +518,374 @@ gfxWindowsPlatform::FindFontForChar(PRUi
// no match? add to set of non-matching codepoints
mCodepointsWithNoFonts.set(aCh);
return nsnull;
}
gfxFontGroup *
gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
- const gfxFontStyle *aStyle)
+ const gfxFontStyle *aStyle,
+ gfxUserFontSet *aUserFontSet)
+{
+ return new gfxWindowsFontGroup(aFamilies, aStyle, aUserFontSet);
+}
+
+
+struct FullFontNameSearch {
+ FullFontNameSearch(const nsAString& aFullName)
+ : mFound(PR_FALSE), mFullName(aFullName), mDC(nsnull), mFontEntry(nsnull)
+ { }
+
+ PRPackedBool mFound;
+ nsString mFullName;
+ nsString mFamilyName;
+ HDC mDC;
+ gfxFontEntry *mFontEntry;
+};
+
+// callback called for each face within a single family
+// match against elfFullName
+
+static int CALLBACK
+FindFullNameForFace(const ENUMLOGFONTEXW *lpelfe,
+ const NEWTEXTMETRICEXW *nmetrics,
+ DWORD fontType, LPARAM userArg)
+{
+ FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
+
+ // does the full name match?
+ if (!data->mFullName.Equals(nsDependentString(lpelfe->elfFullName)))
+ return 1; // continue
+
+ // found match, create a new font entry
+ data->mFound = PR_TRUE;
+
+ const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
+ LOGFONTW logFont = lpelfe->elfLogFont;
+
+ // Some fonts claim to support things > 900, but we don't so clamp the sizes
+ logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
+
+ gfxWindowsFontType feType = FontEntry::DetermineFontType(metrics, fontType);
+
+ data->mFontEntry = FontEntry::CreateFontEntry(data->mFamilyName, feType, (logFont.lfItalic == 0xFF), (PRUint16) (logFont.lfWeight), nsnull, data->mDC, &logFont);
+
+ return 0; // stop iteration
+}
+
+
+// callback called for each family name, based on the assumption that the
+// first part of the full name is the family name
+
+static PLDHashOperator PR_CALLBACK
+FindFullName(nsStringHashKey::KeyType aKey,
+ nsRefPtr<FontFamily>& aFontFamily,
+ void* userArg)
+{
+ FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
+
+ // does the family name match up to the length of the family name?
+ const nsString& family = aFontFamily->Name();
+
+ nsString fullNameFamily;
+ data->mFullName.Left(fullNameFamily, family.Length());
+
+ // if so, iterate over faces in this family to see if there is a match
+ if (family.Equals(fullNameFamily)) {
+ HDC hdc;
+
+ if (!data->mDC) {
+ data->mDC= GetDC(nsnull);
+ SetGraphicsMode(data->mDC, GM_ADVANCED);
+ }
+ hdc = data->mDC;
+
+ LOGFONTW logFont;
+ memset(&logFont, 0, sizeof(LOGFONTW));
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ logFont.lfPitchAndFamily = 0;
+ PRUint32 l = PR_MIN(family.Length(), LF_FACESIZE - 1);
+ memcpy(logFont.lfFaceName,
+ nsPromiseFlatString(family).get(),
+ l * sizeof(PRUnichar));
+ logFont.lfFaceName[l] = 0;
+ data->mFamilyName.Assign(family);
+
+ EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)FindFullNameForFace, (LPARAM)data, 0);
+ }
+
+ if (data->mFound)
+ return PL_DHASH_STOP;
+
+ return PL_DHASH_NEXT;
+}
+
+gfxFontEntry*
+gfxWindowsPlatform::LookupLocalFont(const nsAString& aFontName)
+{
+ // walk over list of names
+ FullFontNameSearch data(aFontName);
+
+ // find fonts that support the character
+ mFonts.Enumerate(FindFullName, &data);
+
+ if (data.mDC)
+ ReleaseDC(nsnull, data.mDC);
+
+ return data.mFontEntry;
+}
+
+// make a unique font name, limited on Windows to 31 two-byte characters
+static void MakeUniqueFontName(PRUnichar aName[LF_FACESIZE])
+{
+ static PRUint32 fontCount = 0;
+ ++fontCount;
+ PRUint32 time = (PRUint32) _time32(nsnull);
+
+ char buf[LF_FACESIZE];
+
+ sprintf(buf, "mozfont%8.8x%8.8x", time, fontCount); // slightly retarded, figure something better later...
+
+ nsCAutoString fontName(buf);
+
+ PRUint32 nameLen = PR_MIN(fontName.Length(), LF_FACESIZE - 1);
+ memcpy(aName, nsPromiseFlatString(NS_ConvertUTF8toUTF16(fontName)).get(), nameLen * 2);
+ aName[nameLen] = 0;
+}
+
+// from t2embapi.h, included in Platform SDK 6.1 but not 6.0
+
+#ifndef __t2embapi__
+
+#define TTLOAD_PRIVATE 0x00000001
+#define LICENSE_PREVIEWPRINT 0x0004
+#define E_NONE 0x0000L
+
+typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
+
+typedef struct
+{
+ unsigned short usStructSize; // size in bytes of structure client should set to sizeof(TTLOADINFO)
+ unsigned short usRefStrSize; // size in wide characters of pusRefStr including NULL terminator
+ unsigned short *pusRefStr; // reference or actual string.
+}TTLOADINFO;
+
+LONG WINAPI TTLoadEmbeddedFont
+(
+ __out HANDLE* phFontReference, // on completion, contains handle to identify embedded font installed
+ // on system
+ __in ULONG ulFlags, // flags specifying the request
+ __out ULONG* pulPrivStatus, // on completion, contains the embedding status
+ __in ULONG ulPrivs, // allows for the reduction of licensing privileges
+ __out ULONG* pulStatus, // on completion, may contain status flags for request
+ __in READEMBEDPROC lpfnReadFromStream, // callback function for doc/disk reads
+ __in LPVOID lpvReadStream, // the input stream tokin
+ __in_opt LPWSTR szWinFamilyName, // the new 16 bit windows family name can be NULL
+ __in_opt LPSTR szMacFamilyName, // the new 8 bit mac family name can be NULL
+ __in_opt TTLOADINFO* pTTLoadInfo // optional security
+);
+
+#endif // __t2embapi__
+
+typedef LONG( WINAPI *TTLoadEmbeddedFontProc ) (HANDLE* phFontReference, ULONG ulFlags, ULONG* pulPrivStatus, ULONG ulPrivs, ULONG* pulStatus,
+ READEMBEDPROC lpfnReadFromStream, LPVOID lpvReadStream, LPWSTR szWinFamilyName,
+ LPSTR szMacFamilyName, TTLOADINFO* pTTLoadInfo);
+
+typedef LONG( WINAPI *TTDeleteEmbeddedFontProc ) (HANDLE hFontReference, ULONG ulFlags, ULONG* pulStatus);
+
+
+static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nsnull;
+static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nsnull;
+
+static void InitializeFontEmbeddingProcs()
{
- return new gfxWindowsFontGroup(aFamilies, aStyle);
+ HMODULE fontlib = LoadLibrary("t2embed.dll");
+ if (!fontlib)
+ return;
+ TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc) GetProcAddress(fontlib, "TTLoadEmbeddedFont");
+ TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc) GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
+}
+
+class WinUserFontData : public gfxUserFontData {
+public:
+ WinUserFontData(HANDLE aFontRef)
+ : mFontRef(aFontRef)
+ { }
+
+ virtual ~WinUserFontData()
+ {
+ ULONG pulStatus;
+ TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
+ }
+
+ HANDLE mFontRef;
+};
+
+// used to control stream read by Windows TTLoadEmbeddedFont API
+
+class EOTFontStreamReader {
+public:
+ EOTFontStreamReader(nsILocalFile *aFontFile, PRUint8 *aEOTHeader,
+ PRUint32 aEOTHeaderLen)
+ : mFontFile(aFontFile), mFd(nsnull), mOpenError(PR_FALSE),
+ mInHeader(PR_TRUE), mHeaderOffset(0), mEOTHeader(aEOTHeader),
+ mEOTHeaderLen(aEOTHeaderLen)
+ {
+
+ }
+
+ ~EOTFontStreamReader()
+ {
+ if (mFd) {
+ PR_Close(mFd);
+ }
+
+ mFontFile->Remove(PR_FALSE);
+ }
+
+ nsCOMPtr<nsILocalFile> mFontFile;
+ PRFileDesc *mFd;
+ PRPackedBool mOpenError;
+ PRPackedBool mInHeader;
+ PRUint32 mHeaderOffset;
+ PRUint8 *mEOTHeader;
+ PRUint32 mEOTHeaderLen;
+
+ PRBool OpenFontFile()
+ {
+ nsresult rv;
+
+ rv = mFontFile->OpenNSPRFileDesc(PR_RDONLY, 0, &mFd);
+ if (NS_FAILED(rv) || !mFd)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+ unsigned long Read(void *outBuffer, const unsigned long aBytesToRead)
+ {
+ PRUint32 bytesLeft = aBytesToRead;
+ PRUint8 *out = static_cast<PRUint8*> (outBuffer);
+
+ if (mOpenError)
+ return 0;
+
+ if (!mFd) {
+ if (!OpenFontFile()) {
+ mOpenError = PR_TRUE;
+ return 0;
+ }
+ }
+
+ // read from EOT header
+ if (mInHeader) {
+ PRUint32 toCopy = PR_MIN(aBytesToRead, mEOTHeaderLen - mHeaderOffset);
+ memcpy(out, mEOTHeader + mHeaderOffset, toCopy);
+ bytesLeft -= toCopy;
+ mHeaderOffset += toCopy;
+ out += toCopy;
+ if (mHeaderOffset == mEOTHeaderLen)
+ mInHeader = PR_FALSE;
+ }
+
+ if (bytesLeft) {
+ PRInt32 bytesRead = PR_Read(mFd, out, bytesLeft);
+ if (bytesRead > 0)
+ bytesLeft -= bytesRead;
+ }
+
+ return aBytesToRead - bytesLeft;
+ }
+
+ static unsigned long ReadEOTStream(void *aReadStream, void *outBuffer,
+ const unsigned long aBytesToRead)
+ {
+ EOTFontStreamReader *eotReader =
+ static_cast<EOTFontStreamReader*> (aReadStream);
+ return eotReader->Read(outBuffer, aBytesToRead);
+ }
+
+};
+
+gfxFontEntry*
+gfxWindowsPlatform::MakePlatformFont(const gfxFontEntry *aProxyEntry,
+ const gfxDownloadedFontData* aFontData)
+{
+ // if calls aren't available, bail
+ if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
+ return nsnull;
+
+ // create an eot header
+ nsAutoTArray<PRUint8,2048> eotHeader;
+ PRUint8 *buffer;
+ PRUint32 eotlen;
+ PRUnichar fontName[LF_FACESIZE];
+ PRBool isCFF;
+
+ nsresult rv;
+ HANDLE fontRef;
+ PRInt32 ret;
+
+ {
+ nsCOMPtr<nsILocalFile> fontFile(do_QueryInterface(aFontData->mFontFile, &rv));
+ if (NS_FAILED(rv))
+ return nsnull;
+
+ rv = gfxFontUtils::MakeEOTHeader(fontFile, &eotHeader, &isCFF);
+ if (NS_FAILED(rv))
+ return nsnull;
+
+ // load in embedded font data
+ eotlen = eotHeader.Length();
+ buffer = reinterpret_cast<PRUint8*> (eotHeader.Elements());
+
+ ULONG privStatus, pulStatus;
+ MakeUniqueFontName(fontName);
+ EOTFontStreamReader eotReader(fontFile, buffer, eotlen);
+
+ ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
+ LICENSE_PREVIEWPRINT, &pulStatus,
+ EOTFontStreamReader::ReadEOTStream,
+ &eotReader, fontName, 0, 0);
+ }
+
+ if (ret != E_NONE)
+ return nsnull;
+
+ // make a new font entry using the unique name
+ WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
+ PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
+
+ return FontEntry::CreateFontEntry(nsDependentString(fontName),
+ gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
+ PRUint32(aProxyEntry->mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
+ w, winUserFontData);
+}
+
+PRBool
+gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
+{
+ // reject based on format flags
+ if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
+ return PR_FALSE;
+ }
+
+ // exclude AAT fonts on platforms other than Mac OS X, this allows
+ // fonts for complex scripts which require AAT tables to be omitted
+ // on other platforms
+ if ((aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)
+ && !(aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE))) {
+ return PR_FALSE;
+ }
+
+ // reject based on filetype in URI
+
+ // otherwise, return true
+ return PR_TRUE;
}
FontFamily *
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
{
nsAutoString name(aName);
BuildKeyNameFromFontName(name);
--- a/gfx/thebes/test/Makefile.in
+++ b/gfx/thebes/test/Makefile.in
@@ -47,17 +47,19 @@ include $(DEPTH)/config/autoconf.mk
REQUIRES = \
xpcom \
string \
thebes \
cairo \
pref \
lcms \
+ necko \
unicharutil \
+ nspr \
$(NULL)
# All platforms
CPPSRCS = \
gfxSurfaceRefCountTest.cpp \
gfxFontSelectionTest.cpp \
gfxTextRunPerfTest.cpp \
gfxWordCacheTest.cpp \
--- a/gfx/thebes/test/gfxFontSelectionTest.cpp
+++ b/gfx/thebes/test/gfxFontSelectionTest.cpp
@@ -283,17 +283,17 @@ DumpTestExpect (TestEntry *test) {
printf ("\n");
}
}
PRBool
RunTest (TestEntry *test, gfxContext *ctx) {
nsRefPtr<gfxFontGroup> fontGroup;
- fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle);
+ fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle, nsnull);
nsAutoPtr<gfxTextRun> textRun;
gfxTextRunFactory::Parameters params = {
ctx, nsnull, nsnull, nsnull, 0, 60
};
PRUint32 flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
if (test->isRTL) {
flags |= gfxTextRunFactory::TEXT_IS_RTL;
--- a/gfx/thebes/test/gfxTextRunPerfTest.cpp
+++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp
@@ -91,17 +91,17 @@ RunTest (TestEntry *test, gfxContext *ct
if (!lastFamilies || strcmp(lastFamilies, test->mFamilies)) {
gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
400,
16.0,
nsDependentCString("x-western"),
0.0,
PR_FALSE, PR_FALSE);
- fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16);
+ fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nsnull);
}
nsAutoPtr<gfxTextRun> textRun;
PRUint32 i;
PRBool isASCII = PR_TRUE;
for (i = 0; test->mString[i]; ++i) {
if (test->mString[i] & 0x80) {
isASCII = PR_FALSE;
--- a/gfx/thebes/test/gfxWordCacheTest.cpp
+++ b/gfx/thebes/test/gfxWordCacheTest.cpp
@@ -158,17 +158,17 @@ main (int argc, char **argv) {
gfxFontStyle style (FONT_STYLE_NORMAL,
139,
10.0,
nsDependentCString("x-western"),
0.0,
PR_FALSE, PR_FALSE);
nsRefPtr<gfxFontGroup> fontGroup =
- gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style);
+ gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style, nsnull);
gfxTextRunFactory::Parameters params = {
ctx, nsnull, nsnull, nsnull, 0, 60
};
PRUint32 flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
// First load an Arabic word into the cache
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -73,16 +73,17 @@
#include "nsThemeConstants.h"
#include "nsPIDOMWindow.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIWidget.h"
#include "gfxMatrix.h"
#include "gfxTypes.h"
+#include "gfxUserFontSet.h"
#ifdef MOZ_SVG
#include "nsSVGUtils.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGForeignObjectFrame.h"
#include "nsSVGOuterSVGFrame.h"
#endif
@@ -1488,20 +1489,23 @@ nsLayoutUtils::GetFontMetricsForFrame(ns
return nsLayoutUtils::GetFontMetricsForStyleContext(aFrame->GetStyleContext(),
aFontMetrics);
}
nsresult
nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
nsIFontMetrics** aFontMetrics)
{
- return aStyleContext->PresContext()->DeviceContext()->
- GetMetricsFor(aStyleContext->GetStyleFont()->mFont,
+ // pass the user font set object into the device context to pass along to CreateFontGroup
+ gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet();
+
+ return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor(
+ aStyleContext->GetStyleFont()->mFont,
aStyleContext->GetStyleVisibility()->mLangGroup,
- *aFontMetrics);
+ *aFontMetrics, fs);
}
nsIFrame*
nsLayoutUtils::FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame)
{
nsIFrame* result = aDescendantFrame;
while (result) {
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -78,16 +78,17 @@
#include "nsFrameManager.h"
#include "nsLayoutUtils.h"
#include "nsIViewManager.h"
#include "nsCSSFrameConstructor.h"
#include "nsCSSRuleProcessor.h"
#include "nsStyleChangeList.h"
#include "nsRuleNode.h"
#include "nsEventDispatcher.h"
+#include "gfxUserFontSet.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
#endif // IBMBIDI
#include "nsContentUtils.h"
// Needed for Start/Stop of Image Animation
@@ -221,16 +222,17 @@ nsPresContext::nsPresContext(nsIDocument
if (!IsDynamic()) {
mImageAnimationMode = imgIContainer::kDontAnimMode;
mNeverAnimate = PR_TRUE;
} else {
mImageAnimationMode = imgIContainer::kNormalAnimMode;
mNeverAnimate = PR_FALSE;
}
NS_ASSERTION(mDocument, "Null document");
+ mUserFontSet = nsnull;
}
nsPresContext::~nsPresContext()
{
mImageLoaders.Enumerate(destroy_loads, nsnull);
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
SetShell(nsnull);
@@ -278,16 +280,18 @@ nsPresContext::~nsPresContext()
#endif // IBMBIDI
nsContentUtils::UnregisterPrefCallback("layout.css.dpi",
nsPresContext::PrefChangedCallback,
this);
NS_IF_RELEASE(mDeviceContext);
NS_IF_RELEASE(mLookAndFeel);
NS_IF_RELEASE(mLangGroup);
+
+ SetUserFontSet(nsnull);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END
@@ -1571,16 +1575,29 @@ nsPresContext::IsChrome() const
/* virtual */ PRBool
nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const
{
return nsRuleNode::
HasAuthorSpecifiedRules(aFrame->GetStyleContext(), ruleTypeMask);
}
+gfxUserFontSet*
+nsPresContext::GetUserFontSet() {
+ return mUserFontSet;
+}
+
+void
+nsPresContext::SetUserFontSet(gfxUserFontSet *aUserFontSet)
+{
+ NS_IF_RELEASE(mUserFontSet);
+ mUserFontSet = aUserFontSet;
+ NS_IF_ADDREF(mUserFontSet);
+}
+
void
nsPresContext::FireDOMPaintEvent()
{
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
if (!docShell)
return;
nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(docShell);
nsISupports* eventTarget = ourWindow;
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -61,16 +61,17 @@
#include "nsGkAtoms.h"
#include "nsIDocument.h"
#include "nsInterfaceHashtable.h"
#include "nsCycleCollectionParticipant.h"
#include "nsChangeHint.h"
// This also pulls in gfxTypes.h, which we cannot include directly.
#include "gfxRect.h"
#include "nsRegion.h"
+
class nsImageLoader;
#ifdef IBMBIDI
class nsBidiPresUtils;
#endif // IBMBIDI
struct nsRect;
class imgIRequest;
@@ -86,16 +87,17 @@ class nsIAtom;
class nsIEventStateManager;
class nsIURI;
class nsILookAndFeel;
class nsICSSPseudoComparator;
class nsIAtom;
struct nsStyleBackground;
template <class T> class nsRunnableMethod;
class nsIRunnable;
+class gfxUserFontSet;
#ifdef MOZ_REFLOW_PERF
class nsIRenderingContext;
#endif
enum nsWidgetType {
eWidgetType_Button = 1,
eWidgetType_Checkbox = 2,
@@ -773,16 +775,19 @@ public:
virtual PRBool HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const;
// Is it OK to let the page specify colors and backgrounds?
PRBool UseDocumentColors() const {
return GetCachedBoolPref(kPresContext_UseDocumentColors) || IsChrome();
}
PRBool SupressingResizeReflow() const { return mSupressResizeReflow; }
+
+ gfxUserFontSet* GetUserFontSet();
+ void SetUserFontSet(gfxUserFontSet *aUserFontSet);
void NotifyInvalidation(const nsRect& aRect, PRBool aIsCrossDoc);
void FireDOMPaintEvent();
protected:
friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal();
NS_HIDDEN_(void) SysColorChangedInternal();
@@ -840,16 +845,19 @@ protected:
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsITimer> mPrefChangedTimer;
nsPropertyTable mPropertyTable;
nsRegion mSameDocDirtyRegion;
nsRegion mCrossDocDirtyRegion;
+ // container for per-context fonts (downloadable, SVG, etc.)
+ gfxUserFontSet* mUserFontSet;
+
nsLanguageSpecificTransformType mLanguageSpecificTransformType;
PRInt32 mFontScaler;
nscoord mMinimumFontSize;
nsRect mVisibleArea;
nsSize mPageSize;
float mPageScale;
float mPPScale;
--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -220,17 +220,9 @@
// {14632191-AC21-4BDF-83E7-2363AD17E838}
#define NS_XULPOPUPMANAGER_CID \
{ 0x14632191, 0xac21, 0x4bdf, { 0x83, 0xe7, 0x23, 0x63, 0xad, 0x17, 0xe8, 0x38 } }
// {93ad72a6-02cd-4716-9626-d47d5ec275ec}
#define NS_DOMJSON_CID \
{ 0x93ad72a6, 0x02cd, 0x4716, { 0x96, 0x26, 0xd4, 0x7d, 0x5e, 0xc2, 0x75, 0xec } }
-
-#ifdef MOZ_MEDIA
-#define NS_HTMLAUDIOELEMENT_CID \
-{ /* 1d40026b-4c44-4f6f-b158-26bb5e9c65e9 */ \
- 0x1d40026b, 0x4c44, 0x4f6f, \
- {0xb1, 0x58, 0x26, 0xbb, 0x5e, 0x9c, 0x65, 0xe9}}
-#endif
-
#endif /* nsLayoutCID_h__ */
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -218,21 +218,16 @@ class nsIDocumentLoaderFactory;
#define PRODUCT_NAME "Gecko"
#define NS_HTMLIMGELEMENT_CONTRACTID \
"@mozilla.org/content/element/html;1?name=img"
#define NS_HTMLOPTIONELEMENT_CONTRACTID \
"@mozilla.org/content/element/html;1?name=option"
-#ifdef MOZ_MEDIA
-#define NS_HTMLAUDIOELEMENT_CONTRACTID \
- "@mozilla.org/content/element/html;1?name=audio"
-#endif
-
/* 0ddf4df8-4dbb-4133-8b79-9afb966514f5 */
#define NS_PLUGINDOCLOADERFACTORY_CID \
{ 0x0ddf4df8, 0x4dbb, 0x4133, { 0x8b, 0x79, 0x9a, 0xfb, 0x96, 0x65, 0x14, 0xf5 } }
#define NS_WINDOWCOMMANDTABLE_CID \
{ /* 0DE2FBFA-6B7F-11D7-BBBA-0003938A9D96 */ \
0x0DE2FBFA, 0x6B7F, 0x11D7, {0xBB, 0xBA, 0x00, 0x03, 0x93, 0x8A, 0x9D, 0x96} }
@@ -492,17 +487,16 @@ MAKE_CTOR(CreateDOMSelection,
MAKE_CTOR(CreateSelection, nsFrameSelection, NS_NewSelection)
MAKE_CTOR(CreateRange, nsIDOMRange, NS_NewRange)
MAKE_CTOR(CreateRangeUtils, nsIRangeUtils, NS_NewRangeUtils)
MAKE_CTOR(CreateContentIterator, nsIContentIterator, NS_NewContentIterator)
MAKE_CTOR(CreatePreContentIterator, nsIContentIterator, NS_NewPreContentIterator)
MAKE_CTOR(CreateSubtreeIterator, nsIContentIterator, NS_NewContentSubtreeIterator)
// CreateHTMLImgElement, see below
// CreateHTMLOptionElement, see below
-// CreateHTMLAudioElement, see below
MAKE_CTOR(CreateTextEncoder, nsIDocumentEncoder, NS_NewTextEncoder)
MAKE_CTOR(CreateHTMLCopyTextEncoder, nsIDocumentEncoder, NS_NewHTMLCopyTextEncoder)
MAKE_CTOR(CreateXMLContentSerializer, nsIContentSerializer, NS_NewXMLContentSerializer)
MAKE_CTOR(CreateHTMLContentSerializer, nsIContentSerializer, NS_NewHTMLContentSerializer)
MAKE_CTOR(CreatePlainTextSerializer, nsIContentSerializer, NS_NewPlainTextSerializer)
MAKE_CTOR(CreateHTMLFragmentSink, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink)
MAKE_CTOR(CreateHTMLFragmentSink2, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink2)
MAKE_CTOR(CreateHTMLParanoidFragmentSink, nsIFragmentContentSink, NS_NewHTMLParanoidFragmentSink)
@@ -669,63 +663,16 @@ UnregisterHTMLOptionElement(nsIComponent
nsIFile* aPath,
const char* aRegistryLocation,
const nsModuleComponentInfo* aInfo)
{
// XXX remove category entry
return NS_OK;
}
-#ifdef MOZ_MEDIA
-static NS_IMETHODIMP
-CreateHTMLAudioElement(nsISupports* aOuter, REFNSIID aIID, void** aResult)
-{
- *aResult = nsnull;
- if (aOuter)
- return NS_ERROR_NO_AGGREGATION;
- // Note! NS_NewHTMLAudioElement is special cased to handle a null nodeinfo
- nsCOMPtr<nsIContent> inst(NS_NewHTMLAudioElement(nsnull));
- return inst ? inst->QueryInterface(aIID, aResult) : NS_ERROR_OUT_OF_MEMORY;
-}
-
-static NS_IMETHODIMP
-RegisterHTMLAudioElement(nsIComponentManager *aCompMgr,
- nsIFile* aPath,
- const char* aRegistryLocation,
- const char* aComponentType,
- const nsModuleComponentInfo* aInfo)
-{
- nsCOMPtr<nsICategoryManager> catman =
- do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
-
- if (!catman)
- return NS_ERROR_FAILURE;
-
- nsXPIDLCString previous;
- nsresult rv = catman->AddCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY,
- "Audio", NS_HTMLAUDIOELEMENT_CONTRACTID,
- PR_TRUE, PR_TRUE, getter_Copies(previous));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return catman->AddCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
- "Audio", "HTMLAudioElement",
- PR_TRUE, PR_TRUE, getter_Copies(previous));
-}
-
-static NS_IMETHODIMP
-UnregisterHTMLAudioElement(nsIComponentManager* aCompMgr,
- nsIFile* aPath,
- const char* aRegistryLocation,
- const nsModuleComponentInfo* aInfo)
-{
- // XXX remove category entry
- return NS_OK;
-}
-#endif
-
static NS_METHOD
RegisterDataDocumentContentPolicy(nsIComponentManager *aCompMgr,
nsIFile* aPath,
const char* aRegistryLocation,
const char* aComponentType,
const nsModuleComponentInfo* aInfo)
{
nsresult rv;
@@ -1048,40 +995,31 @@ static const nsModuleComponentInfo gComp
nsnull,
nsCSSOMFactoryConstructor },
{ "Inspector CSS Utils",
NS_INSPECTORCSSUTILS_CID,
nsnull,
nsInspectorCSSUtilsConstructor },
- // Needed to support "new Option;", "new Image;" and "new Audio;" in JavaScript
+ // Needed to support "new Option;" and "new Image;" in JavaScript
{ "HTML img element",
NS_HTMLIMAGEELEMENT_CID,
NS_HTMLIMGELEMENT_CONTRACTID,
CreateHTMLImgElement,
RegisterHTMLImgElement,
UnregisterHTMLImgElement },
{ "HTML option element",
NS_HTMLOPTIONELEMENT_CID,
NS_HTMLOPTIONELEMENT_CONTRACTID,
CreateHTMLOptionElement,
RegisterHTMLOptionElement,
UnregisterHTMLOptionElement },
-#ifdef MOZ_MEDIA
- { "HTML audio element",
- NS_HTMLAUDIOELEMENT_CID,
- NS_HTMLAUDIOELEMENT_CONTRACTID,
- CreateHTMLAudioElement,
- RegisterHTMLAudioElement,
- UnregisterHTMLAudioElement },
-#endif
-
#ifdef MOZ_ENABLE_CANVAS
{ "Canvas 2D Rendering Context",
NS_CANVASRENDERINGCONTEXT2D_CID,
"@mozilla.org/content/canvas-rendering-context;1?id=2d",
CreateCanvasRenderingContext2D },
#endif
{ "XML document encoder",
--- a/layout/style/Makefile.in
+++ b/layout/style/Makefile.in
@@ -146,16 +146,17 @@ CPPSRCS = \
nsCSSStyleSheet.cpp \
nsCSSValue.cpp \
nsComputedDOMStyle.cpp \
nsDOMCSSAttrDeclaration.cpp \
nsDOMCSSDeclaration.cpp \
nsDOMCSSRGBColor.cpp \
nsDOMCSSRect.cpp \
nsDOMCSSValueList.cpp \
+ nsFontFaceLoader.cpp \
nsHTMLCSSStyleSheet.cpp \
nsHTMLStyleSheet.cpp \
nsInspectorCSSUtils.cpp \
nsLayoutStylesheetCache.cpp \
nsMediaFeatures.cpp \
nsROCSSPrimitiveValue.cpp \
nsRuleNode.cpp \
nsStyleContext.cpp \
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -77,16 +77,20 @@
#include "nsAttrValue.h"
#include "nsAttrName.h"
#include "nsILookAndFeel.h"
#include "nsWidgetsCID.h"
#include "nsServiceManagerUtils.h"
#include "nsTArray.h"
#include "nsContentUtils.h"
#include "nsIMediaList.h"
+#include "gfxPlatform.h"
+#include "gfxUserFontSet.h"
+#include "nsCSSRules.h"
+#include "nsFontFaceLoader.h"
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
static nsTArray< nsCOMPtr<nsIAtom> >* sSystemMetrics = 0;
struct RuleValue {
/**
* |RuleValue|s are constructed before they become part of the
* |RuleHash|, to act as rule/selector pairs. |Add| is called when
@@ -2287,16 +2291,139 @@ struct CascadeEnumData {
nsPresContext* mPresContext;
nsMediaQueryResultCacheKey& mCacheKey;
// Hooray, a manual PLDHashTable since nsClassHashtable doesn't
// provide a getter that gives me a *reference* to the value.
PLDHashTable mRulesByWeight; // of RuleValue* linked lists (?)
PLArenaPool& mArena;
};
+static void
+InsertFontFaceRule(nsICSSRule* aRule, gfxUserFontSet* fs)
+{
+ nsCSSFontFaceRule *fontFace = static_cast<nsCSSFontFaceRule*> (aRule);
+ PRInt32 type;
+ NS_ASSERTION(NS_SUCCEEDED(aRule->GetType(type))
+ && type == nsICSSRule::FONT_FACE_RULE,
+ "InsertFontFaceRule passed a non-fontface CSS rule");
+
+ // fontFace->List();
+
+ nsAutoString fontfamily, valueString;
+ nsCSSValue val;
+
+ PRUint32 unit;
+ PRUint32 weight = NS_STYLE_FONT_WEIGHT_NORMAL;
+ PRUint32 stretch = NS_STYLE_FONT_STRETCH_NORMAL;
+ PRUint32 italicStyle = FONT_STYLE_NORMAL;
+
+ // set up family name
+ fontFace->GetDesc(eCSSFontDesc_Family, val);
+ unit = val.GetUnit();
+ if (unit == eCSSUnit_String) {
+ val.GetStringValue(fontfamily);
+ fontfamily.Trim("\"");
+ } else {
+ NS_ASSERTION(unit == eCSSUnit_String,
+ "@font-face family name has non-string unit type");
+ return;
+ }
+
+ // set up weight
+ fontFace->GetDesc(eCSSFontDesc_Weight, val);
+ unit = val.GetUnit();
+ if (unit != eCSSUnit_Null) {
+ if (unit == eCSSUnit_Normal) {
+ weight = NS_STYLE_FONT_WEIGHT_NORMAL;
+ } else {
+ weight = val.GetIntValue();
+ }
+ }
+
+ // set up stretch
+ fontFace->GetDesc(eCSSFontDesc_Stretch, val);
+ unit = val.GetUnit();
+ if (unit != eCSSUnit_Null) {
+ if (unit == eCSSUnit_Normal) {
+ stretch = NS_STYLE_FONT_STRETCH_NORMAL;
+ } else {
+ stretch = val.GetIntValue();
+ }
+ }
+
+ // set up font style
+ fontFace->GetDesc(eCSSFontDesc_Style, val);
+ if (val.GetUnit() != eCSSUnit_Null) {
+ if (val.GetUnit() == eCSSUnit_Normal) {
+ italicStyle = FONT_STYLE_NORMAL;
+ } else {
+ italicStyle = val.GetIntValue();
+ }
+ }
+
+ // set up src array
+ nsTArray<gfxFontFaceSrc> srcArray;
+
+ fontFace->GetDesc(eCSSFontDesc_Src, val);
+ unit = val.GetUnit();
+ if (unit == eCSSUnit_Array) {
+ nsCSSValue::Array *srcArr = val.GetArrayValue();
+ PRUint32 i, numSrc = srcArr->Count(), faceIndex = 0;
+
+ for (i = 0; i < numSrc; i++) {
+ val = srcArr->Item(i);
+ unit = val.GetUnit();
+ gfxFontFaceSrc *face = srcArray.AppendElements(1);
+ if (!face)
+ return;
+
+ switch (unit) {
+
+ case eCSSUnit_Local_Font:
+ val.GetStringValue(face->mLocalName);
+ face->mIsLocal = PR_TRUE;
+ face->mURI = nsnull;
+ face->mFormatFlags = 0;
+ break;
+ case eCSSUnit_URL:
+ face->mIsLocal = PR_FALSE;
+ face->mURI = val.GetURLValue();
+ face->mLocalName.Truncate();
+ face->mFormatFlags = 0;
+ while (i + 1 < numSrc && (val = srcArr->Item(i+1),
+ val.GetUnit() == eCSSUnit_Font_Format)) {
+ nsDependentString valueString(val.GetStringBufferValue());
+ if (valueString.LowerCaseEqualsASCII("opentype")) {
+ face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
+ } else if (valueString.LowerCaseEqualsASCII("truetype")) {
+ face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
+ } else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
+ face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
+ } else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
+ face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
+ } else if (valueString.LowerCaseEqualsASCII("svg")) {
+ face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
+ }
+ i++;
+ }
+ break;
+ default:
+ NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
+ "strange unit type in font-face src array");
+ break;
+ }
+ }
+ }
+
+ if (!fontfamily.IsEmpty() && srcArray.Length() > 0) {
+ fs->AddFontFace(fontfamily, srcArray, weight, stretch, italicStyle);
+ }
+
+}
+
static PRBool
InsertRuleByWeight(nsICSSRule* aRule, void* aData)
{
CascadeEnumData* data = (CascadeEnumData*)aData;
PRInt32 type = nsICSSRule::UNKNOWN_RULE;
aRule->GetType(type);
if (nsICSSRule::STYLE_RULE == type) {
@@ -2320,20 +2447,38 @@ InsertRuleByWeight(nsICSSRule* aRule, vo
}
else if (nsICSSRule::MEDIA_RULE == type ||
nsICSSRule::DOCUMENT_RULE == type) {
nsICSSGroupRule* groupRule = (nsICSSGroupRule*)aRule;
if (groupRule->UseForPresentation(data->mPresContext, data->mCacheKey))
if (!groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData))
return PR_FALSE;
}
+ else if (nsICSSRule::FONT_FACE_RULE == type
+ && gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
+ nsPresContext *presContext = data->mPresContext;
+ gfxUserFontSet *fs = presContext->GetUserFontSet();
+ if (!fs) {
+ nsFontFaceLoaderContext *loaderCtx = new nsFontFaceLoaderContext(presContext);
+ if (!loaderCtx)
+ return PR_FALSE;
+ fs = new gfxUserFontSet(loaderCtx); // user font set owns loader context
+ if (!fs) {
+ delete loaderCtx;
+ return PR_FALSE;
+ }
+ presContext->SetUserFontSet(fs);
+ }
+
+ InsertFontFaceRule(aRule, fs);
+ }
+
return PR_TRUE;
}
-
static PRBool
CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData)
{
nsCSSStyleSheet* sheet = static_cast<nsCSSStyleSheet*>(aSheet);
CascadeEnumData* data = static_cast<CascadeEnumData*>(aData);
PRBool bSheetApplicable = PR_TRUE;
sheet->GetApplicable(bSheetApplicable);
new file mode 100644
--- /dev/null
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:ts=2:et:sw=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 Foundation code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Daggett <jdaggett@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+/* code for loading in @font-face defined font data */
+
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG /* Allow logging in the release build */
+#endif /* MOZ_LOGGING */
+#include "prlog.h"
+
+#include "nsFontFaceLoader.h"
+
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+#include "nsIStreamListener.h"
+#include "nsNetUtil.h"
+#include "nsIChannelEventSink.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsContentUtils.h"
+
+#include "nsPresContext.h"
+#include "nsIPresShell.h"
+#include "nsIDocument.h"
+#include "nsIFrame.h"
+#include "nsIPrincipal.h"
+#include "nsIScriptSecurityManager.h"
+
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+
+
+#ifdef PR_LOGGING
+static PRLogModuleInfo *gFontDownloaderLog = PR_NewLogModule("fontdownloader");
+#endif /* PR_LOGGING */
+
+#define LOG(args) PR_LOG(gFontDownloaderLog, PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(gFontDownloaderLog, PR_LOG_DEBUG)
+
+
+#define ENFORCE_SAME_SITE_ORIGIN "gfx.downloadable_fonts.enforce_same_site_origin"
+static PRBool gEnforceSameSiteOrigin = PR_TRUE;
+
+static PRBool
+CheckMayLoad(nsIDocument* aDoc, nsIURI* aURI)
+{
+ // allow this to be disabled via a pref
+ static PRBool init = PR_FALSE;
+
+ if (!init) {
+ init = PR_TRUE;
+ nsContentUtils::AddBoolPrefVarCache(ENFORCE_SAME_SITE_ORIGIN, &gEnforceSameSiteOrigin);
+ }
+
+ if (!gEnforceSameSiteOrigin)
+ return PR_TRUE;
+
+ if (!aDoc)
+ return PR_FALSE;
+
+ nsresult rv = aDoc->NodePrincipal()->CheckMayLoad(aURI, PR_TRUE);
+ return NS_SUCCEEDED(rv);
+}
+
+
+nsFontFaceLoader::nsFontFaceLoader(gfxFontEntry *aFontToLoad, nsIURI *aFontURI,
+ gfxUserFontSet::LoaderContext *aContext)
+ : mFontEntry(aFontToLoad), mFontURI(aFontURI), mLoaderContext(aContext)
+{
+
+}
+
+nsFontFaceLoader::~nsFontFaceLoader()
+{
+
+}
+
+NS_IMPL_ISUPPORTS1(nsFontFaceLoader, nsIDownloadObserver)
+
+static nsresult
+MakeTempFileName(nsIFile** tempFile)
+{
+ nsresult rv;
+
+ rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, tempFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // xxx - need something a little less lame here...
+ static PRUint16 count = 0;
+ PRTime now = PR_Now();
+ PRUint32 current = (PRUint32) now;
+
+ ++count;
+ char buf[256];
+ sprintf(buf, "mozfont_%8.8x%4.4x.ttf", current, count);
+
+ rv = (*tempFile)->AppendNative(nsDependentCString(buf));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return (*tempFile)->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+}
+
+// initiate the load
+nsresult
+nsFontFaceLoader::Init()
+{
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ mFontURI->GetSpec(fontURI);
+ LOG(("fontdownloader (%p) download start - font uri: (%s)\n",
+ this, fontURI.get()));
+ }
+#endif
+
+ nsresult rv;
+
+ nsCOMPtr<nsIFile> tempFile;
+ rv = MakeTempFileName(getter_AddRefs(tempFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_NewDownloader(getter_AddRefs(mDownloader), this, tempFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInterfaceRequestor> sameOriginChecker
+ = nsContentUtils::GetSameOriginChecker();
+
+ rv = NS_OpenURI(mDownloader, nsnull, mFontURI, nsnull, nsnull,
+ sameOriginChecker);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFontFaceLoader::OnDownloadComplete(nsIDownloader *aDownloader,
+ nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsresult aStatus,
+ nsIFile *aFile)
+{
+
+#ifdef PR_LOGGING
+ if (LOG_ENABLED()) {
+ nsCAutoString fontURI;
+ mFontURI->GetSpec(fontURI);
+ if (NS_SUCCEEDED(aStatus)) {
+ LOG(("fontdownloader (%p) download completed - font uri: (%s)\n",
+ this, fontURI.get()));
+ } else {
+ LOG(("fontdownloader (%p) download failed - font uri: (%s) error: %8.8x\n",
+ this, fontURI.get(), aStatus));
+ }
+ }
+#endif
+
+ PRBool fontUpdate;
+
+ if (NS_SUCCEEDED(aStatus) && aFile) {
+ // font data download succeeded, try to load the font
+ mFaceData.mFormatFlags = 0;
+ mFaceData.mFontFile = aFile;
+ mFaceData.mDownloader = aDownloader;
+ }
+
+ // whether an error occurred or not, notify the user font set of the completion
+ fontUpdate = mLoaderContext->mUserFontSet->OnLoadComplete(mFontEntry,
+ mFaceData,
+ aStatus);
+
+ // when new font loaded, need to reflow
+ if (fontUpdate) {
+ nsFontFaceLoaderContext *loaderCtx
+ = static_cast<nsFontFaceLoaderContext*> (mLoaderContext);
+
+ nsIPresShell *ps = loaderCtx->mPresContext->PresShell();
+ if (ps) {
+ // reflow async so that reflows coalesce
+ ps->StyleChangeReflow();
+ LOG(("fontdownloader (%p) reflow\n", this));
+ }
+ }
+
+ return NS_OK;
+}
+
+PRBool
+nsFontFaceLoader::CreateHandler(gfxFontEntry *aFontToLoad, nsIURI *aFontURI,
+ gfxUserFontSet::LoaderContext *aContext)
+{
+ // check same-site origin
+ nsFontFaceLoaderContext *loaderCtx
+ = static_cast<nsFontFaceLoaderContext*> (aContext);
+
+ nsIPresShell *ps = loaderCtx->mPresContext->PresShell();
+ if (!ps)
+ return PR_FALSE;
+
+ if (!CheckMayLoad(ps->GetDocument(), aFontURI))
+ return PR_FALSE;
+
+ nsRefPtr<nsFontFaceLoader> loader = new nsFontFaceLoader(aFontToLoad,
+ aFontURI,
+ aContext);
+ if (!loader)
+ return PR_FALSE;
+
+ nsresult rv = loader->Init();
+ return NS_SUCCEEDED(rv);
+}
new file mode 100644
--- /dev/null
+++ b/layout/style/nsFontFaceLoader.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:ts=2:et:sw=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 Foundation code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Daggett <jdaggett@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+/* code for loading in @font-face defined font data */
+
+#ifndef nsFontFaceLoader_h_
+#define nsFontFaceLoader_h_
+
+#include "nsIDownloader.h"
+#include "nsIURI.h"
+#include "gfxUserFontSet.h"
+
+class nsIRequest;
+class nsISupports;
+class nsPresContext;
+
+class nsFontFaceLoader : public nsIDownloadObserver
+{
+public:
+
+ nsFontFaceLoader(gfxFontEntry *aFontToLoad, nsIURI *aFontURI,
+ gfxUserFontSet::LoaderContext *aContext);
+ virtual ~nsFontFaceLoader();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDOWNLOADOBSERVER
+
+ // initiate the load
+ nsresult Init();
+
+ // returns whether create succeeded or not
+ static PRBool CreateHandler(gfxFontEntry *aFontToLoad, nsIURI *aFontURI,
+ gfxUserFontSet::LoaderContext *aContext);
+
+private:
+ nsRefPtr<gfxFontEntry> mFontEntry;
+ nsCOMPtr<nsIURI> mFontURI;
+ gfxUserFontSet::LoaderContext* mLoaderContext;
+ gfxDownloadedFontData mFaceData;
+ nsCOMPtr<nsIStreamListener> mDownloader;
+};
+
+class nsFontFaceLoaderContext : public gfxUserFontSet::LoaderContext {
+public:
+ nsFontFaceLoaderContext(nsPresContext* aContext)
+ : gfxUserFontSet::LoaderContext(nsFontFaceLoader::CreateHandler),
+ mPresContext(aContext)
+ {
+
+ }
+
+ nsPresContext* mPresContext;
+};
+
+
+#endif /* !defined(nsFontFaceLoader_h_) */
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -1248,17 +1248,17 @@ nsSVGGlyphFrame::EnsureTextRun(float *aD
}
const nsFont& font = fontData->mFont;
gfxFontStyle fontStyle(font.style, font.weight, textRunSize, langGroup,
font.sizeAdjust, font.systemFont,
font.familyNameQuirks);
nsRefPtr<gfxFontGroup> fontGroup =
- gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle);
+ gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle, presContext->GetUserFontSet());
PRUint32 flags = gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX |
nsLayoutUtils::GetTextRunFlagsForStyle(GetStyleContext(), GetStyleText(), GetStyleFont());
// XXX We should use a better surface here! But then we'd have to
// change things so we can ensure we always have the "right" sort of
// surface available, by creating the textrun only at the right times
nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx();
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -129,16 +129,19 @@ pref("browser.chrome.image_icons.max_siz
pref("browser.triple_click_selects_paragraph", true);
// 0 = Off, 1 = Full, 2 = Tagged Images Only.
// See eCMSMode in gfx/thebes/public/gfxPlatform.h
pref("gfx.color_management.mode", 2);
pref("gfx.color_management.display_profile", "");
pref("gfx.color_management.rendering_intent", 0);
+pref("gfx.downloadable_fonts.enabled", true);
+pref("gfx.downloadable_fonts.enforce_same_site_origin", true);
+
pref("accessibility.browsewithcaret", false);
pref("accessibility.warn_on_browsewithcaret", true);
#ifndef XP_MACOSX
// Tab focus model bit field:
// 1 focuses text controls, 2 focuses other form elements, 4 adds links.
// Most users will want 1, 3, or 7.
// On OS X, we use Full Keyboard Access system preference,