DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (e7e658ec1e98)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
/* 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 SharedFontList_h
#define SharedFontList_h

#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
#include "mozilla/FontPropertyTypes.h"
#include <atomic>

class gfxSparseBitSet;
struct gfxFontStyle;
class gfxFontEntry;
struct GlobalFontMatch;

namespace mozilla {
namespace fontlist {

class FontList;  // See the separate SharedFontList-impl.h header

/**
 * A Pointer in the shared font list contains a packed index/offset pair,
 * with a 12-bit index into the array of shared-memory blocks, and a 20-bit
 * offset into the block.
 * The maximum size of each block is therefore 2^20 bytes (1048576).
 */
struct Pointer {
 private:
  friend class FontList;
  static const uint32_t kIndexBits = 12u;
  static const uint32_t kBlockShift = 20u;
  static_assert(kIndexBits + kBlockShift == 32u, "bad Pointer bit count");

  static const uint32_t kNullValue = 0xffffffffu;
  static const uint32_t kOffsetMask = (1u << kBlockShift) - 1;

 public:
  static Pointer Null() { return Pointer(); }

  Pointer() : mBlockAndOffset(kNullValue) {}

  Pointer(uint32_t aBlock, uint32_t aOffset)
      : mBlockAndOffset((aBlock << kBlockShift) | aOffset) {
    MOZ_ASSERT(aBlock < (1u << kIndexBits) && aOffset < (1u << kBlockShift));
  }

  Pointer(const Pointer& aOther) {
    mBlockAndOffset.store(aOther.mBlockAndOffset);
  }

  bool IsNull() const { return mBlockAndOffset == kNullValue; }

  uint32_t Block() const { return mBlockAndOffset >> kBlockShift; }

  uint32_t Offset() const { return mBlockAndOffset & kOffsetMask; }

  /**
   * Convert a fontlist::Pointer to a standard C++ pointer. This requires the
   * FontList, which will know where the shared memory block is mapped in
   * the current process's address space.
   */
  void* ToPtr(FontList* aFontList) const;

  Pointer& operator=(const Pointer& aOther) {
    mBlockAndOffset.store(aOther.mBlockAndOffset);
    return *this;
  }

  // We store the block index and the offset within the block as a single
  // atomic 32-bit value so we can safely modify a Pointer without other
  // processes seeing a broken (partially-updated) value.
  std::atomic<uint32_t> mBlockAndOffset;
};

/**
 * Family and face names are stored as String records, which hold a length
 * (in utf-8 code units) and a Pointer to the string's UTF-8 characters.
 */
struct String {
  String() : mPointer(Pointer::Null()), mLength(0) {}

  String(FontList* aList, const nsACString& aString)
      : mPointer(Pointer::Null()) {
    Assign(aString, aList);
  }

  const nsCString AsString(FontList* aList) const {
    MOZ_ASSERT(!mPointer.IsNull());
    nsCString res;
    res.AssignLiteral(static_cast<const char*>(mPointer.ToPtr(aList)), mLength);
    return res;
  }

  void Assign(const nsACString& aString, FontList* aList);

  const char* BeginReading(FontList* aList) const {
    MOZ_ASSERT(!mPointer.IsNull());
    return static_cast<const char*>(mPointer.ToPtr(aList));
  }

  uint32_t Length() const { return mLength; }

  bool IsNull() const { return mPointer.IsNull(); }

 private:
  Pointer mPointer;
  uint32_t mLength;
};

/**
 * A Face record represents an individual font resource; it has the style
 * properties needed for font matching, as well as a pointer to a character
 * map that records the supported character set. This may be Null if we have
 * not yet loaded the data.
 * The mDescriptor and mIndex fields provide the information needed to
 * instantiate a (platform-specific) font reference that can be used with
 * platform font APIs; their content depends on the requirements of the
 * platform APIs (e.g. font PostScript name, file pathname, serialized
 * fontconfig pattern, etc).
 */
struct Face {
  // Data required to initialize a Face
  struct InitData {
    nsCString mDescriptor;  // descriptor that can be used to instantiate a
                            // platform font reference
    uint16_t mIndex;        // an index used with descriptor (on some platforms)
    bool mFixedPitch;       // is the face fixed-pitch (monospaced)?
    mozilla::WeightRange mWeight;     // CSS font-weight value
    mozilla::StretchRange mStretch;   // CSS font-stretch value
    mozilla::SlantStyleRange mStyle;  // CSS font-style value
  };

  Face(FontList* aList, const InitData& aData)
      : mDescriptor(aList, aData.mDescriptor),
        mIndex(aData.mIndex),
        mFixedPitch(aData.mFixedPitch),
        mWeight(aData.mWeight),
        mStretch(aData.mStretch),
        mStyle(aData.mStyle),
        mCharacterMap(Pointer::Null()) {}

  bool HasValidDescriptor() const {
    return !mDescriptor.IsNull() && mIndex != uint16_t(-1);
  }

  void SetCharacterMap(FontList* aList, const gfxSparseBitSet* aCharMap);

  String mDescriptor;
  uint16_t mIndex;
  bool mFixedPitch;
  mozilla::WeightRange mWeight;
  mozilla::StretchRange mStretch;
  mozilla::SlantStyleRange mStyle;
  Pointer mCharacterMap;
};

/**
 * A Family record represents an available (installed) font family; it has
 * a name (for display purposes) and a key (lowercased, for case-insensitive
 * lookups), as well as a pointer to an array of Faces. Depending on the
 * platform, the array of faces may be lazily initialized the first time we
 * want to use the family.
 */
struct Family {
  // Data required to initialize a Family
  struct InitData {
    InitData(const nsACString& aKey,   // lookup key (lowercased)
             const nsACString& aName,  // display name
             uint32_t aIndex = 0,   // [win] index in the system font collection
             bool aHidden = false,  // [mac] hidden font (e.g. .SFNSText)?
             bool aBundled = false,       // [win] font was bundled with the app
                                          // rather than system-installed
             bool aBadUnderline = false,  // underline-position in font is bad
             bool aForceClassic = false   // [win] use "GDI classic" rendering
             )
        : mKey(aKey),
          mName(aName),
          mIndex(aIndex),
          mHidden(aHidden),
          mBundled(aBundled),
          mBadUnderline(aBadUnderline),
          mForceClassic(aForceClassic) {}
    bool operator<(const InitData& aRHS) const { return mKey < aRHS.mKey; }
    bool operator==(const InitData& aRHS) const {
      return mKey == aRHS.mKey && mName == aRHS.mName &&
             mHidden == aRHS.mHidden && mBundled == aRHS.mBundled &&
             mBadUnderline == aRHS.mBadUnderline;
    }
    const nsCString mKey;
    const nsCString mName;
    uint32_t mIndex;
    bool mHidden;
    bool mBundled;
    bool mBadUnderline;
    bool mForceClassic;
  };

  /**
   * Font families are considered "simple" if they contain only 4 faces with
   * style attributes corresponding to Regular, Bold, Italic, and BoldItalic
   * respectively, or a subset of these (e.g. only Regular and Bold). In this
   * case, the faces are stored at predefined positions in the mFaces array,
   * and a simplified (faster) style-matching algorithm can be used.
   */
  enum {
    // Indexes into mFaces for families where mIsSimple is true
    kRegularFaceIndex = 0,
    kBoldFaceIndex = 1,
    kItalicFaceIndex = 2,
    kBoldItalicFaceIndex = 3,
    // mask values for selecting face with bold and/or italic attributes
    kBoldMask = 0x01,
    kItalicMask = 0x02
  };

  Family(FontList* aList, const InitData& aData);

  void AddFaces(FontList* aList, const nsTArray<Face::InitData>& aFaces);

  void SetFacePtrs(FontList* aList, nsTArray<Pointer>& aFaces);

  const String& Key() const { return mKey; }

  const String& DisplayName() const { return mName; }

  uint32_t Index() const { return mIndex & 0x7fffffffu; }
  bool IsBundled() const { return mIndex & 0x80000000u; }

  uint32_t NumFaces() const {
    MOZ_ASSERT(IsInitialized());
    return mFaceCount;
  }

  Pointer* Faces(FontList* aList) const {
    MOZ_ASSERT(IsInitialized());
    return static_cast<Pointer*>(mFaces.ToPtr(aList));
  }

  bool IsHidden() const { return mIsHidden; }

  bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
  bool IsForceClassic() const { return mIsForceClassic; }

  bool IsInitialized() const { return !mFaces.IsNull(); }

  void FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
                            nsTArray<Face*>& aFaceList,
                            bool aIgnoreSizeTolerance = false) const;

  Face* FindFaceForStyle(FontList* aList, const gfxFontStyle& aStyle,
                         bool aIgnoreSizeTolerance = false) const;

  void SearchAllFontsForChar(FontList* aList, GlobalFontMatch* aMatchData);

  void SetupFamilyCharMap(FontList* aList);

 private:
  std::atomic<uint32_t> mFaceCount;
  String mKey;
  String mName;
  Pointer mCharacterMap;  // If non-null, union of character coverage of all
                          // faces in the family
  Pointer mFaces;         // Pointer to array of |mFaceCount| face pointers
  uint32_t mIndex;        // [win] Top bit set indicates app-bundled font family
  bool mIsHidden;
  bool mIsBadUnderlineFamily;
  bool mIsForceClassic;
  bool mIsSimple;  // family allows simplified style matching: mFaces contains
                   // exactly 4 entries [Regular, Bold, Italic, BoldItalic].
};

/**
 * For platforms where we build an index of local font face names (PS-name
 * and fullname of the font) to support @font-face{src:local(...)}, we map
 * each face name to an index into the family list, and an index into the
 * family's list of faces.
 */
struct LocalFaceRec {
  /**
   * The InitData struct needs to record the family name rather than index,
   * as we may be collecting these records at the same time as building the
   * family list, so we don't yet know the final family index.
   * When actually recorded in the FontList's mLocalFaces array, the family
   * will be stored as a simple index into the mFamilies array.
   */
  struct InitData {
    nsCString mFamilyName;
    uint32_t mFaceIndex;
    InitData(const nsACString& aFamily, uint32_t aFace)
        : mFamilyName(aFamily), mFaceIndex(aFace) {}
    InitData() = default;
  };
  String mKey;
  uint32_t mFamilyIndex;  // Index into the font list's Families array
  uint32_t mFaceIndex;    // Index into the family's Faces array
};

}  // namespace fontlist
}  // namespace mozilla

#include "ipc/IPCMessageUtils.h"

namespace IPC {

template <>
struct ParamTraits<mozilla::fontlist::Pointer> {
  typedef mozilla::fontlist::Pointer paramType;
  static void Write(Message* aMsg, const paramType& aParam) {
    uint32_t v = aParam.mBlockAndOffset;
    WriteParam(aMsg, v);
  }
  static bool Read(const Message* aMsg, PickleIterator* aIter,
                   paramType* aResult) {
    uint32_t v;
    if (ReadParam(aMsg, aIter, &v)) {
      aResult->mBlockAndOffset.store(v);
      return true;
    }
    return false;
  }
};

}  // namespace IPC

#undef ERROR  // This is defined via Windows.h, but conflicts with some bindings
              // code when this gets included in the same compilation unit.

#endif /* SharedFontList_h */