summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxFontFamilyList.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/gfxFontFamilyList.h')
-rw-r--r--gfx/thebes/gfxFontFamilyList.h364
1 files changed, 364 insertions, 0 deletions
diff --git a/gfx/thebes/gfxFontFamilyList.h b/gfx/thebes/gfxFontFamilyList.h
new file mode 100644
index 000000000..e240102e0
--- /dev/null
+++ b/gfx/thebes/gfxFontFamilyList.h
@@ -0,0 +1,364 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_FONT_FAMILY_LIST_H
+#define GFX_FONT_FAMILY_LIST_H
+
+#include "nsDebug.h"
+#include "nsISupportsImpl.h"
+#include "nsString.h"
+#include "nsUnicharUtils.h"
+#include "nsTArray.h"
+#include "mozilla/MemoryReporting.h"
+
+namespace mozilla {
+
+/**
+ * type of font family name, either a name (e.g. Helvetica) or a
+ * generic (e.g. serif, sans-serif), with the ability to distinguish
+ * between unquoted and quoted names for serializaiton
+ */
+
+enum FontFamilyType : uint32_t {
+ eFamily_none = 0, // used when finding generics
+
+ // explicitly named font family (e.g. Helvetica)
+ eFamily_named,
+ eFamily_named_quoted,
+
+ // generics
+ eFamily_serif, // pref font code relies on this ordering!!!
+ eFamily_sans_serif,
+ eFamily_monospace,
+ eFamily_cursive,
+ eFamily_fantasy,
+
+ // special
+ eFamily_moz_variable,
+ eFamily_moz_fixed,
+
+ eFamily_generic_first = eFamily_serif,
+ eFamily_generic_last = eFamily_fantasy,
+ eFamily_generic_count = (eFamily_fantasy - eFamily_serif + 1)
+};
+
+enum QuotedName { eQuotedName, eUnquotedName };
+
+/**
+ * font family name, a string for the name if not a generic and
+ * a font type indicated named family or which generic family
+ */
+
+struct FontFamilyName final {
+ FontFamilyName()
+ : mType(eFamily_named)
+ {}
+
+ // named font family - e.g. Helvetica
+ explicit FontFamilyName(const nsAString& aFamilyName,
+ QuotedName aQuoted = eUnquotedName) {
+ mType = (aQuoted == eQuotedName) ? eFamily_named_quoted : eFamily_named;
+ mName = aFamilyName;
+ }
+
+ // generic font family - e.g. sans-serif
+ explicit FontFamilyName(FontFamilyType aType) {
+ NS_ASSERTION(aType != eFamily_named &&
+ aType != eFamily_named_quoted &&
+ aType != eFamily_none,
+ "expected a generic font type");
+ mName.Truncate();
+ mType = aType;
+ }
+
+ FontFamilyName(const FontFamilyName& aCopy) {
+ mType = aCopy.mType;
+ mName = aCopy.mName;
+ }
+
+ bool IsNamed() const {
+ return mType == eFamily_named || mType == eFamily_named_quoted;
+ }
+
+ bool IsGeneric() const {
+ return !IsNamed();
+ }
+
+ void AppendToString(nsAString& aFamilyList, bool aQuotes = true) const {
+ switch (mType) {
+ case eFamily_named:
+ aFamilyList.Append(mName);
+ break;
+ case eFamily_named_quoted:
+ if (aQuotes) {
+ aFamilyList.Append('"');
+ }
+ aFamilyList.Append(mName);
+ if (aQuotes) {
+ aFamilyList.Append('"');
+ }
+ break;
+ case eFamily_serif:
+ aFamilyList.AppendLiteral("serif");
+ break;
+ case eFamily_sans_serif:
+ aFamilyList.AppendLiteral("sans-serif");
+ break;
+ case eFamily_monospace:
+ aFamilyList.AppendLiteral("monospace");
+ break;
+ case eFamily_cursive:
+ aFamilyList.AppendLiteral("cursive");
+ break;
+ case eFamily_fantasy:
+ aFamilyList.AppendLiteral("fantasy");
+ break;
+ case eFamily_moz_fixed:
+ aFamilyList.AppendLiteral("-moz-fixed");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // helper method that converts generic names to the right enum value
+ static FontFamilyName
+ Convert(const nsAString& aFamilyOrGenericName) {
+ // should only be passed a single font - not entirely correct, a family
+ // *could* have a comma in it but in practice never does so
+ // for debug purposes this is fine
+ NS_ASSERTION(aFamilyOrGenericName.FindChar(',') == -1,
+ "Convert method should only be passed a single family name");
+
+ FontFamilyType genericType = eFamily_none;
+ if (aFamilyOrGenericName.LowerCaseEqualsLiteral("serif")) {
+ genericType = eFamily_serif;
+ } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("sans-serif")) {
+ genericType = eFamily_sans_serif;
+ } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("monospace")) {
+ genericType = eFamily_monospace;
+ } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("cursive")) {
+ genericType = eFamily_cursive;
+ } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("fantasy")) {
+ genericType = eFamily_fantasy;
+ } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("-moz-fixed")) {
+ genericType = eFamily_moz_fixed;
+ } else {
+ return FontFamilyName(aFamilyOrGenericName, eUnquotedName);
+ }
+
+ return FontFamilyName(genericType);
+ }
+
+ // memory reporting
+ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+ return mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+ }
+
+ FontFamilyType mType;
+ nsString mName; // empty if mType != eFamily_named
+};
+
+inline bool
+operator==(const FontFamilyName& a, const FontFamilyName& b) {
+ return a.mType == b.mType && a.mName == b.mName;
+}
+
+/**
+ * font family list, array of font families and a default font type.
+ * font family names are either named strings or generics. the default
+ * font type is used to preserve the variable font fallback behavior
+ */
+
+class FontFamilyList {
+public:
+ FontFamilyList()
+ : mDefaultFontType(eFamily_none)
+ {
+ }
+
+ explicit FontFamilyList(FontFamilyType aGenericType)
+ : mDefaultFontType(eFamily_none)
+ {
+ Append(FontFamilyName(aGenericType));
+ }
+
+ FontFamilyList(const nsAString& aFamilyName,
+ QuotedName aQuoted)
+ : mDefaultFontType(eFamily_none)
+ {
+ Append(FontFamilyName(aFamilyName, aQuoted));
+ }
+
+ FontFamilyList(const FontFamilyList& aOther)
+ : mFontlist(aOther.mFontlist)
+ , mDefaultFontType(aOther.mDefaultFontType)
+ {
+ }
+
+ void Append(const FontFamilyName& aFamilyName) {
+ mFontlist.AppendElement(aFamilyName);
+ }
+
+ void Append(const nsTArray<nsString>& aFamilyNameList) {
+ uint32_t len = aFamilyNameList.Length();
+ for (uint32_t i = 0; i < len; i++) {
+ mFontlist.AppendElement(FontFamilyName(aFamilyNameList[i],
+ eUnquotedName));
+ }
+ }
+
+ void Clear() {
+ mFontlist.Clear();
+ }
+
+ uint32_t Length() const {
+ return mFontlist.Length();
+ }
+
+ bool IsEmpty() const {
+ return mFontlist.IsEmpty();
+ }
+
+ const nsTArray<FontFamilyName>& GetFontlist() const {
+ return mFontlist;
+ }
+
+ bool Equals(const FontFamilyList& aFontlist) const {
+ return mFontlist == aFontlist.mFontlist &&
+ mDefaultFontType == aFontlist.mDefaultFontType;
+ }
+
+ FontFamilyType FirstGeneric() const {
+ uint32_t len = mFontlist.Length();
+ for (uint32_t i = 0; i < len; i++) {
+ const FontFamilyName& name = mFontlist[i];
+ if (name.IsGeneric()) {
+ return name.mType;
+ }
+ }
+ return eFamily_none;
+ }
+
+ bool HasGeneric() const {
+ return FirstGeneric() != eFamily_none;
+ }
+
+ bool HasDefaultGeneric() const {
+ uint32_t len = mFontlist.Length();
+ for (uint32_t i = 0; i < len; i++) {
+ const FontFamilyName& name = mFontlist[i];
+ if (name.mType == mDefaultFontType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Find the first generic (but ignoring cursive and fantasy, as they are
+ // rarely configured in any useful way) in the list.
+ // If found, move it to the start and return true; else return false.
+ bool PrioritizeFirstGeneric() {
+ uint32_t len = mFontlist.Length();
+ for (uint32_t i = 0; i < len; i++) {
+ const FontFamilyName name = mFontlist[i];
+ if (name.IsGeneric()) {
+ if (name.mType == eFamily_cursive ||
+ name.mType == eFamily_fantasy) {
+ continue;
+ }
+ if (i > 0) {
+ mFontlist.RemoveElementAt(i);
+ mFontlist.InsertElementAt(0, name);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void PrependGeneric(FontFamilyType aType) {
+ mFontlist.InsertElementAt(0, FontFamilyName(aType));
+ }
+
+ void ToString(nsAString& aFamilyList,
+ bool aQuotes = true,
+ bool aIncludeDefault = false) const {
+ aFamilyList.Truncate();
+ uint32_t len = mFontlist.Length();
+ for (uint32_t i = 0; i < len; i++) {
+ if (i != 0) {
+ aFamilyList.Append(',');
+ }
+ const FontFamilyName& name = mFontlist[i];
+ name.AppendToString(aFamilyList, aQuotes);
+ }
+ if (aIncludeDefault && mDefaultFontType != eFamily_none) {
+ if (!aFamilyList.IsEmpty()) {
+ aFamilyList.Append(',');
+ }
+ if (mDefaultFontType == eFamily_serif) {
+ aFamilyList.AppendLiteral("serif");
+ } else {
+ aFamilyList.AppendLiteral("sans-serif");
+ }
+ }
+ }
+
+ // searches for a specific non-generic name, lowercase comparison
+ bool Contains(const nsAString& aFamilyName) const {
+ uint32_t len = mFontlist.Length();
+ nsAutoString fam(aFamilyName);
+ ToLowerCase(fam);
+ for (uint32_t i = 0; i < len; i++) {
+ const FontFamilyName& name = mFontlist[i];
+ if (name.mType != eFamily_named &&
+ name.mType != eFamily_named_quoted) {
+ continue;
+ }
+ nsAutoString listname(name.mName);
+ ToLowerCase(listname);
+ if (listname.Equals(fam)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ FontFamilyType GetDefaultFontType() const { return mDefaultFontType; }
+ void SetDefaultFontType(FontFamilyType aType) {
+ NS_ASSERTION(aType == eFamily_none || aType == eFamily_serif ||
+ aType == eFamily_sans_serif,
+ "default font type must be either serif or sans-serif");
+ mDefaultFontType = aType;
+ }
+
+ // memory reporting
+ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+ size_t n = 0;
+ n += mFontlist.ShallowSizeOfExcludingThis(aMallocSizeOf);
+ for (size_t i = 0; i < mFontlist.Length(); i++) {
+ n += mFontlist[i].SizeOfExcludingThis(aMallocSizeOf);
+ }
+ return n;
+ }
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+ return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+ }
+
+private:
+ nsTArray<FontFamilyName> mFontlist;
+ FontFamilyType mDefaultFontType; // none, serif or sans-serif
+};
+
+inline bool
+operator==(const FontFamilyList& a, const FontFamilyList& b) {
+ return a.Equals(b);
+}
+
+} // namespace mozilla
+
+#endif /* GFX_FONT_FAMILY_LIST_H */