/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */
for (uint32_t b = 0; b < numBlocks; b++) { if (mBlockIndex[b] == NO_BLOCK) { continue;
} const Block* block = &mBlocks[mBlockIndex[b]]; constint BUFSIZE = 256; char outStr[BUFSIZE]; int index = 0;
index += snprintf(&outStr[index], BUFSIZE - index, "%s u+%6.6x [", aPrefix,
(b * BLOCK_SIZE_BITS)); for (int i = 0; i < 32; i += 4) { for (int j = i; j < i + 4; j++) {
uint8_t bits = block->mBits[j];
uint8_t flip1 = ((bits & 0xaa) >> 1) | ((bits & 0x55) << 1);
uint8_t flip2 = ((flip1 & 0xcc) >> 2) | ((flip1 & 0x33) << 2);
uint8_t flipped = ((flip2 & 0xf0) >> 4) | ((flip2 & 0x0f) << 4);
index += snprintf(&outStr[index], BUFSIZE - index, "%2.2x", flipped);
} if (i + 4 != 32) index += snprintf(&outStr[index], BUFSIZE - index, " ");
}
Unused << snprintf(&outStr[index], BUFSIZE - index, "]");
LOG(aWhichLog, ("%s", outStr));
}
}
nsresult gfxFontUtils::ReadCMAPTableFormat10(const uint8_t* aBuf,
uint32_t aLength,
gfxSparseBitSet& aCharacterMap) { // Ensure table is large enough that we can safely read the header
NS_ENSURE_TRUE(aLength >= sizeof(Format10CmapHeader),
NS_ERROR_GFX_CMAP_MALFORMED);
for (uint32_t i = 0; i < numChars; ++i) { if (uint16_t(*glyphs) != 0) {
aCharacterMap.set(charCode);
}
++charCode;
++glyphs;
}
aCharacterMap.Compact();
return NS_OK;
}
nsresult gfxFontUtils::ReadCMAPTableFormat12or13( const uint8_t* aBuf, uint32_t aLength, gfxSparseBitSet& aCharacterMap) { // Format 13 has the same structure as format 12, the only difference is // the interpretation of the glyphID field. So we can share the code here // that reads the table and just records character coverage.
// Ensure table is large enough that we can safely read the header
NS_ENSURE_TRUE(aLength >= sizeof(Format12CmapHeader),
NS_ERROR_GFX_CMAP_MALFORMED);
// Check that the table is large enough for the group array const uint32_t numGroups = cmap12->numGroups;
NS_ENSURE_TRUE(
(tablelen - sizeof(Format12CmapHeader)) / sizeof(Format12Group) >=
numGroups,
NS_ERROR_GFX_CMAP_MALFORMED);
// The array of groups immediately follows the subtable header. const Format12Group* group = reinterpret_cast<const Format12Group*>(aBuf + sizeof(Format12CmapHeader));
// Check that groups are in correct order and do not overlap, // and record character coverage in aCharacterMap.
uint32_t prevEndCharCode = 0; for (uint32_t i = 0; i < numGroups; i++, group++) {
uint32_t startCharCode = group->startCharCode; const uint32_t endCharCode = group->endCharCode;
NS_ENSURE_TRUE((prevEndCharCode < startCharCode || i == 0) &&
startCharCode <= endCharCode &&
endCharCode <= CMAP_MAX_CODEPOINT,
NS_ERROR_GFX_CMAP_MALFORMED); // don't include a character that maps to glyph ID 0 (.notdef) if (group->startGlyphId == 0) {
startCharCode++;
} if (startCharCode <= endCharCode) {
aCharacterMap.SetRange(startCharCode, endCharCode);
}
prevEndCharCode = endCharCode;
}
// This field should normally (except for Mac platform subtables) be zero // according to the OT spec, but some buggy fonts have lang = 1 (which would // be English for MacOS). E.g. Arial Narrow Bold, v. 1.1 (Tiger), Arial // Unicode MS (see bug 530614). So accept either zero or one here; the error // should be harmless.
NS_ENSURE_TRUE((ReadShortAt(aBuf, OffsetLanguage) & 0xfffe) == 0,
NS_ERROR_GFX_CMAP_MALFORMED);
// sanity-check range // This permits ranges to overlap by 1 character, which is strictly // incorrect but occurs in Baskerville on OS X 10.7 (see bug 689087), // and appears to be harmless in practice
NS_ENSURE_TRUE(startCount >= prevEndCount && startCount <= endCount,
NS_ERROR_GFX_CMAP_MALFORMED);
prevEndCount = endCount;
if (idRangeOffset == 0) { // figure out if there's a code in the range that would map to // glyph ID 0 (.notdef); if so, we need to skip setting that // character code in the map const uint16_t skipCode = 65536 - ReadShortAt16(idDeltas, i); if (startCount < skipCode) {
aCharacterMap.SetRange(startCount,
std::min<uint16_t>(skipCode - 1, endCount));
} if (skipCode < endCount) {
aCharacterMap.SetRange(std::max<uint16_t>(startCount, skipCode + 1),
endCount);
}
} else { // Unused: self-documenting. // const uint16_t idDelta = ReadShortAt16(idDeltas, i); for (uint32_t c = startCount; c <= endCount; ++c) { if (c == 0xFFFF) break;
// make sure we have a glyph if (*gdata != 0) { // The glyph index at this point is:
uint16_t glyph = ReadShortAt16(idDeltas, i) + *gdata; if (glyph) {
aCharacterMap.set(c);
}
}
}
}
}
if (aIsSymbolFont) { // For fonts with "MS Symbol" encoding, we duplicate character mappings in // the U+F0xx range down to U+00xx codepoints, so as to support fonts such // as Wingdings. // Note that if the font actually has cmap coverage for the U+00xx range // (either duplicating the PUA codepoints or mapping to separate glyphs), // this will not affect it. for (uint32_t c = 0x0020; c <= 0x00ff; ++c) { if (aCharacterMap.test(0xf000 + c)) {
aCharacterMap.set(c);
}
}
}
uint8_t* table = new uint8_t[tablelen];
memcpy(table, aBuf, tablelen);
aTable = static_cast<const uint8_t*>(table);
return NS_OK;
}
// For fonts with two format-4 tables, the first one (Unicode platform) is // preferred on the Mac; on other platforms we allow the Microsoft-platform // subtable to replace it.
// Sanity-check that the fixed-size arrays don't exceed the buffer. const uint8_t* const limit = aBuf + aLength; if ((const uint8_t*)(&idRangeOffset[segCount]) > limit) { return 0; // broken font, just bail out safely
}
// For most efficient binary search, we want to work on a range of segment // indexes that is a power of 2 so that we can always halve it by shifting. // So we find the largest power of 2 that is <= segCount. // We will offset this range by segOffset so as to reach the end // of the table, provided that doesn't put us beyond the target // value from the outset.
uint32_t powerOf2 = mozilla::FindHighestBit(segCount);
uint32_t segOffset = segCount - powerOf2;
uint32_t idx = 0;
if (uint16_t(startCodes[segOffset]) <= aCh) {
idx = segOffset;
}
// Repeatedly halve the size of the range until we find the target group while (powerOf2 > 1) {
powerOf2 >>= 1; if (uint16_t(startCodes[idx + powerOf2]) <= aCh) {
idx += powerOf2;
}
}
if (aCh >= uint16_t(startCodes[idx]) && aCh <= uint16_t(endCodes[idx])) {
uint16_t result; if (uint16_t(idRangeOffset[idx]) == 0) {
result = aCh;
} else {
uint16_t offset = aCh - uint16_t(startCodes[idx]); const AutoSwap_PRUint16* glyphIndexTable =
(const AutoSwap_PRUint16*)((constchar*)&idRangeOffset[idx] +
uint16_t(idRangeOffset[idx])); if ((const uint8_t*)(glyphIndexTable + offset + 1) > limit) { return 0; // broken font, just bail out safely
}
result = glyphIndexTable[offset];
}
// Note that this is unsigned 16-bit arithmetic, and may wrap around // (which is required behavior per spec)
result += uint16_t(idDelta[idx]); return result;
}
uint32_t gfxFontUtils::MapCharToGlyphFormat12or13(const uint8_t* aBuf,
uint32_t aCh) { // The only difference between formats 12 and 13 is the interpretation of // the glyphId field. So the code here uses the same "Format12" structures, // etc., to handle both subtable formats.
// We know that numGroups is within range for the subtable size // because it was checked by ReadCMAPTableFormat12or13.
uint32_t numGroups = cmap12->numGroups;
// The array of groups immediately follows the subtable header. const Format12Group* groups = reinterpret_cast<const Format12Group*>(aBuf + sizeof(Format12CmapHeader));
// For most efficient binary search, we want to work on a range that // is a power of 2 so that we can always halve it by shifting. // So we find the largest power of 2 that is <= numGroups. // We will offset this range by rangeOffset so as to reach the end // of the table, provided that doesn't put us beyond the target // value from the outset.
uint32_t powerOf2 = mozilla::FindHighestBit(numGroups);
uint32_t rangeOffset = numGroups - powerOf2;
uint32_t range = 0;
uint32_t startCharCode;
if (groups[rangeOffset].startCharCode <= aCh) {
range = rangeOffset;
}
// Repeatedly halve the size of the range until we find the target group while (powerOf2 > 1) {
powerOf2 >>= 1; if (groups[range + powerOf2].startCharCode <= aCh) {
range += powerOf2;
}
}
// Check if the character is actually present in the range and return // the corresponding glyph ID. Here is where formats 12 and 13 interpret // the startGlyphId (12) or glyphId (13) field differently
startCharCode = groups[range].startCharCode; if (startCharCode <= aCh && groups[range].endCharCode >= aCh) { return uint16_t(cmap12->format) == 12
? uint16_t(groups[range].startGlyphId) + aCh - startCharCode
: uint16_t(groups[range].startGlyphId);
}
// Else it's not present, so return the .notdef glyph return 0;
}
// produce a unique font name that is (1) a valid Postscript name and (2) less // than 31 characters in length. Using AddFontMemResourceEx on Windows fails // for names longer than 30 characters in length.
if (!PL_Base64Encode(reinterpret_cast<char*>(&guid), sizeof(guid), guidB64)) return NS_ERROR_FAILURE;
// all b64 characters except for '/' are allowed in Postscript names, so // convert / ==> - char* p; for (p = guidB64; *p; p++) { if (*p == '/') *p = '-';
}
// 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 {
uint32_t offset;
uint32_t length;
};
#pragmapack()
staticbool IsValidSFNTVersion(uint32_t version) { // normally 0x00010000, CFF-style OT fonts == 'OTTO' and Apple TT fonts = // 'true' 'typ1' is also possible for old Type 1 fonts in a SFNT container but // not supported return version == 0x10000 || version == TRUETYPE_TAG('O', 'T', 'T', 'O') ||
version == TRUETYPE_TAG('t', 'r', 'u', 'e');
}
gfxUserFontType gfxFontUtils::DetermineFontDataType(const uint8_t* aFontData,
uint32_t aFontDataLength) { // test for OpenType font data // problem: EOT-Lite with 0x10000 length will look like TrueType! if (aFontDataLength >= sizeof(SFNTHeader)) { const SFNTHeader* sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData);
uint32_t sfntVersion = sfntHeader->sfntVersion; if (IsValidSFNTVersion(sfntVersion)) { return GFX_USERFONT_OPENTYPE;
}
}
// test for WOFF or WOFF2 if (aFontDataLength >= sizeof(AutoSwap_PRUint32)) { const AutoSwap_PRUint32* version = reinterpret_cast<const AutoSwap_PRUint32*>(aFontData); if (uint32_t(*version) == TRUETYPE_TAG('w', 'O', 'F', 'F')) { return GFX_USERFONT_WOFF;
} if (uint32_t(*version) == TRUETYPE_TAG('w', 'O', 'F', '2')) { return GFX_USERFONT_WOFF2;
}
}
nsresult gfxFontUtils::RenameFont(const nsAString& aName, const uint8_t* aFontData,
uint32_t aFontDataLength,
FallibleTArray<uint8_t>* aNewFont) {
NS_ASSERTION(aNewFont, "null font data array");
uint64_t dataLength(aFontDataLength);
// new name table staticconst uint32_t neededNameIDs[] = {NAME_ID_FAMILY, NAME_ID_STYLE,
NAME_ID_UNIQUE, NAME_ID_FULL,
NAME_ID_POSTSCRIPT};
// calculate new name table size
uint16_t nameCount = std::size(neededNameIDs);
// leave room for null-terminator
uint32_t nameStrLength = (aName.Length() + 1) * sizeof(char16_t); if (nameStrLength > 65535) { // The name length _in bytes_ must fit in an unsigned short field; // therefore, a name longer than this cannot be used. return NS_ERROR_FAILURE;
}
// round name table size up to 4-byte multiple
uint32_t nameTableSize =
(sizeof(NameHeader) + sizeof(NameRecord) * nameCount + nameStrLength +
3) &
~3;
if (dataLength + nameTableSize > UINT32_MAX) return NS_ERROR_FAILURE;
// bug 505386 - need to handle unpadded font length
uint32_t paddedFontDataSize = (aFontDataLength + 3) & ~3;
uint32_t adjFontDataSize = paddedFontDataSize + nameTableSize;
// create new buffer: old font data plus new name table if (!aNewFont->AppendElements(adjFontDataSize, fallible)) return NS_ERROR_OUT_OF_MEMORY;
// copy the old font data
uint8_t* newFontData = reinterpret_cast<uint8_t*>(aNewFont->Elements());
// null the last four bytes in case the font length is not a multiple of 4
memset(newFontData + aFontDataLength, 0,
paddedFontDataSize - aFontDataLength);
// copy font data
memcpy(newFontData, aFontData, aFontDataLength);
// null out the last 4 bytes for checksum calculations
memset(newFontData + adjFontDataSize - 4, 0, 4);
// adjust name table header to point to the new name table
SFNTHeader* sfntHeader = reinterpret_cast<SFNTHeader*>(newFontData);
// table directory entries begin immediately following SFNT header
TableDirEntry* dirEntry =
FindTableDirEntry(newFontData, TRUETYPE_TAG('n', 'a', 'm', 'e')); // function only called if font validates, so this should always be true
MOZ_ASSERT(dirEntry, "attempt to rename font with no name table");
uint32_t numTables = sfntHeader->numTables;
// note: dirEntry now points to 'name' table record
while (nameData < nameDataEnd) checkSum = checkSum + *nameData++;
// adjust name table entry to point to new name table
dirEntry->offset = paddedFontDataSize;
dirEntry->length = nameTableSize;
dirEntry->checkSum = checkSum;
// fix up checksums
uint32_t checksum = 0;
// checksum for font = (checksum of header) + (checksum of tables)
uint32_t headerLen = sizeof(SFNTHeader) + sizeof(TableDirEntry) * numTables; const AutoSwap_PRUint32* headerData = reinterpret_cast<const AutoSwap_PRUint32*>(newFontData);
// header length is in bytes, checksum calculated in longwords for (i = 0; i < (headerLen >> 2); i++, headerData++) {
checksum += *headerData;
}
// This is only called after the basic validity of the downloaded sfnt // data has been checked, so it should never fail to find the name table // (though it might fail to read it, if memory isn't available); // other checks here are just for extra paranoia.
nsresult gfxFontUtils::GetFullNameFromSFNT(const uint8_t* aFontData,
uint32_t aLength,
nsACString& aFullName) {
aFullName = "(MISSING NAME)"; // should always get replaced
// first, look for the English name (this will succeed 99% of the time)
rv = ReadNames(aNameData, aDataLen, aNameID, CANONICAL_LANG_ID, PLATFORM_ID,
names);
NS_ENSURE_SUCCESS(rv, rv);
// otherwise, grab names for all languages if (names.Length() == 0) {
rv = ReadNames(aNameData, aDataLen, aNameID, LANG_ALL, PLATFORM_ID, names);
NS_ENSURE_SUCCESS(rv, rv);
}
#ifdefined(XP_MACOSX) // may be dealing with font that only has Microsoft name entries if (names.Length() == 0) {
rv = ReadNames(aNameData, aDataLen, aNameID, LANG_ID_MICROSOFT_EN_US,
PLATFORM_ID_MICROSOFT, names);
NS_ENSURE_SUCCESS(rv, rv);
// return the first name (99.9% of the time names will // contain a single English name) if (names.Length()) {
aName.Assign(names[0]); return NS_OK;
}
return NS_ERROR_FAILURE;
}
// Charsets to use for decoding Mac platform font names. // This table is sorted by {encoding, language}, with the wildcard "ANY" being // greater than any defined values for each field; we use a binary search on // both fields, and fall back to matching only encoding if necessary
// Some "redundant" entries for specific combinations are included such as // encoding=roman, lang=english, in order that common entries will be found // on the first search.
// Return the Encoding object we should use to decode a font name // given the name table attributes. // Special return values: // X_USER_DEFINED_ENCODING One of Mac legacy encodings that is not a part // of Encoding Standard // nullptr unknown charset, do not attempt conversion const Encoding* gfxFontUtils::GetCharsetForFontName(uint16_t aPlatform,
uint16_t aScript,
uint16_t aLanguage) { switch (aPlatform) { case PLATFORM_ID_UNICODE: return UTF_16BE_ENCODING;
case PLATFORM_ID_MAC: {
MacFontNameCharsetMapping searchValue = {aScript, aLanguage, nullptr}; for (uint32_t i = 0; i < 2; ++i) {
size_t idx; if (BinarySearchIf(gMacFontNameCharsets, 0,
std::size(gMacFontNameCharsets),
MacCharsetMappingComparator(searchValue), &idx)) { return gMacFontNameCharsets[idx].mEncoding;
}
// no match, so try again finding one in any language
searchValue.mLanguage = ANY;
}
} break;
case PLATFORM_ID_ISO: if (aScript < std::size(gISOFontNameCharsets)) { return gISOFontNameCharsets[aScript];
} break;
case PLATFORM_ID_MICROSOFT: if (aScript < std::size(gMSFontNameCharsets)) { return gMSFontNameCharsets[aScript];
} break;
}
// convert a raw name from the name table to an nsString, if possible; // return value indicates whether conversion succeeded bool gfxFontUtils::DecodeFontName(constchar* aNameData, int32_t aByteLen,
uint32_t aPlatformCode, uint32_t aScriptCode,
uint32_t aLangCode, nsACString& aName) { if (aByteLen <= 0) {
NS_WARNING("empty font name");
aName.SetLength(0); returntrue;
}
auto encoding = GetCharsetForFontName(aPlatformCode, aScriptCode, aLangCode);
if (!encoding) { // nullptr -> unknown charset #ifdef DEBUG char warnBuf[128]; if (aByteLen > 64) aByteLen = 64;
SprintfLiteral(warnBuf, "skipping font name, unknown charset %d:%d:%d for <%.*s>",
aPlatformCode, aScriptCode, aLangCode, aByteLen, aNameData);
NS_WARNING(warnBuf); #endif returnfalse;
}
if (encoding == X_USER_DEFINED_ENCODING) { #ifdef XP_DARWIN // Special case for macOS only: support legacy Mac encodings // that aren't part of the Encoding Standard. if (aPlatformCode == PLATFORM_ID_MAC) {
CFStringRef str =
CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)aNameData,
aByteLen, aScriptCode, false); if (str) {
CFIndex length = CFStringGetLength(str);
nsAutoString name16;
name16.SetLength(length);
CFStringGetCharacters(str, CFRangeMake(0, length),
(UniChar*)name16.BeginWriting());
CFRelease(str);
CopyUTF16toUTF8(name16, aName); returntrue;
}
} #endif
NS_WARNING("failed to get the decoder for a font name string"); returnfalse;
}
auto rv = encoding->DecodeWithoutBOMHandling(
nsDependentCSubstring(aNameData, aByteLen), aName); return NS_SUCCEEDED(rv);
}
// -- name table data const NameHeader* nameHeader = reinterpret_cast<const NameHeader*>(aNameData);
uint32_t nameCount = nameHeader->count;
// -- sanity check the number of name records if (uint64_t(nameCount) * sizeof(NameRecord) > aDataLen) {
NS_WARNING("invalid font (name table data)"); return NS_ERROR_FAILURE;
}
// -- iterate through name records const NameRecord* nameRecord = reinterpret_cast<const NameRecord*>(aNameData + sizeof(NameHeader));
uint64_t nameStringsBase = uint64_t(nameHeader->stringOffset);
uint32_t i; for (i = 0; i < nameCount; i++, nameRecord++) {
uint32_t platformID;
// skip over unwanted nameID's if (uint32_t(nameRecord->nameID) != aNameID) { continue;
}
// skip over unwanted platform data
platformID = nameRecord->platformID; if (aPlatformID != PLATFORM_ALL && platformID != uint32_t(aPlatformID)) { continue;
}
// skip over unwanted languages if (aLangID != LANG_ALL &&
uint32_t(nameRecord->languageID) != uint32_t(aLangID)) { continue;
}
// add name to names array
// -- calculate string location
uint32_t namelen = nameRecord->length;
uint32_t nameoff =
nameRecord->offset; // offset from base of string storage
if (nameStringsBase + uint64_t(nameoff) + uint64_t(namelen) > aDataLen) {
NS_WARNING("invalid font (name table strings)"); return NS_ERROR_FAILURE;
}
// -- decode if necessary and make nsString
nsAutoCString name;
// https://www.microsoft.com/typography/otspec/fvar.htm#instanceRecord struct InstanceRecord {
AutoSwap_PRUint16 subfamilyNameID;
AutoSwap_PRUint16 flags;
AutoSwap_PRInt32 coordinates[1]; // variable-size array [axisCount] // The variable-length 'coordinates' array may be followed by an // optional extra field 'postScriptNameID'. We can't directly // represent this in the struct, because its offset varies depending // on the number of axes present. // (Not currently used by our code here anyhow.) // AutoSwap_PRUint16 postScriptNameID;
};
// Load the two font tables we need as harfbuzz blobs; if either is absent, // just bail out.
AutoHBBlob fvarTable(
aFontEntry->GetFontTable(TRUETYPE_TAG('f', 'v', 'a', 'r')));
AutoHBBlob nameTable(
aFontEntry->GetFontTable(TRUETYPE_TAG('n', 'a', 'm', 'e'))); if (!fvarTable || !nameTable) { return;
} unsignedint len; constchar* data = hb_blob_get_data(fvarTable, &len); if (len < sizeof(FvarHeader)) { return;
} // Read the fields of the table header; bail out if it looks broken. auto fvar = reinterpret_cast<const FvarHeader*>(data); if (uint16_t(fvar->majorVersion) != 1 || uint16_t(fvar->minorVersion) != 0 ||
uint16_t(fvar->reserved) != 2) { return;
}
uint16_t axisCount = fvar->axisCount;
uint16_t axisSize = fvar->axisSize;
uint16_t instanceCount = fvar->instanceCount;
uint16_t instanceSize = fvar->instanceSize; if (axisCount ==
0 || // no axes? // https://www.microsoft.com/typography/otspec/fvar.htm#axisSize
axisSize != 20 || // required value for current table version // https://www.microsoft.com/typography/otspec/fvar.htm#instanceSize
(instanceSize != axisCount * sizeof(int32_t) + 4 &&
instanceSize != axisCount * sizeof(int32_t) + 6)) { return;
} // Check that axis array will not exceed table size
uint16_t axesOffset = fvar->axesArrayOffset; if (axesOffset + uint32_t(axisCount) * axisSize > len) { return;
} // Get pointer to the array of axis records auto axes = reinterpret_cast<const AxisRecord*>(data + axesOffset); // Get address of instance array, and check it doesn't overflow table size. // https://www.microsoft.com/typography/otspec/fvar.htm#axisAndInstanceArrays auto instData = data + axesOffset + axisCount * axisSize; if (instData + uint32_t(instanceCount) * instanceSize > data + len) { return;
} if (aInstances) {
aInstances->SetCapacity(instanceCount); for (unsigned i = 0; i < instanceCount; ++i, instData += instanceSize) { // Typed pointer to the current instance record, to read its fields. auto inst = reinterpret_cast<const InstanceRecord*>(instData); // Pointer to the coordinates array within the instance record. // This array has axisCount elements, and is included in instanceSize // (which depends on axisCount, and was validated above) so we know // access to coords[j] below will not be outside the table bounds. auto coords = &inst->coordinates[0];
gfxFontVariationInstance instance;
uint16_t nameID = inst->subfamilyNameID;
nsresult rv = ReadCanonicalName(nameTable, nameID, instance.mName); if (NS_FAILED(rv)) { // If no name was available for the instance, ignore it. continue;
}
instance.mValues.SetCapacity(axisCount); for (unsigned j = 0; j < axisCount; ++j) {
gfxFontVariationValue value = {axes[j].axisTag,
int32_t(coords[j]) / 65536.0f};
instance.mValues.AppendElement(value);
}
aInstances->AppendElement(std::move(instance));
}
} if (aAxes) {
aAxes->SetCapacity(axisCount); for (unsigned i = 0; i < axisCount; ++i) { if (uint16_t(axes[i].flags) & HIDDEN_AXIS) { continue;
}
gfxFontVariationAxis axis;
axis.mTag = axes[i].axisTag;
uint16_t nameID = axes[i].axisNameID;
nsresult rv = ReadCanonicalName(nameTable, nameID, axis.mName); if (NS_FAILED(rv)) {
axis.mName.Truncate(0);
} // Convert values from 16.16 fixed-point to float
axis.mMinValue = int32_t(axes[i].minValue) / 65536.0f;
axis.mDefaultValue = int32_t(axes[i].defaultValue) / 65536.0f;
axis.mMaxValue = int32_t(axes[i].maxValue) / 65536.0f;
aAxes->AppendElement(axis);
}
}
}
for (uint32_t i = 0; i < nameCount; i++, nameRecord++) {
uint32_t nameLen = nameRecord->length;
uint32_t nameOff =
nameRecord->offset; // offset from base of string storage
if (stringsBase + nameOff + nameLen > aDataLength) {
NS_WARNING("invalid font (name table strings)"); return;
}
uint16_t nameID = nameRecord->nameID; if ((useFullName && nameID == NAME_ID_FULL) ||
(!useFullName &&
(nameID == NAME_ID_FAMILY || nameID == NAME_ID_PREFERRED_FAMILY))) {
nsAutoCString otherFamilyName; bool ok = DecodeFontName(
aNameData + stringsBase + nameOff, nameLen,
uint32_t(nameRecord->platformID), uint32_t(nameRecord->encodingID),
uint32_t(nameRecord->languageID), otherFamilyName); // add if not same as canonical family name if (ok && otherFamilyName != aFamilyName &&
!aOtherFamilyNames.Contains(otherFamilyName)) {
aOtherFamilyNames.AppendElement(otherFamilyName);
}
}
}
}
#ifdef XP_WIN
/* static */ bool gfxFontUtils::IsCffFont(const uint8_t* aFontData) { // this is only called after aFontData has passed basic validation, // so we know there is enough data present to allow us to read the version! const SFNTHeader* sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData); return (sfntHeader->sfntVersion == TRUETYPE_TAG('O', 'T', 'T', 'O'));
}
if (dom::GetCurrentThreadWorkerPrivate()) { returnfalse;
}
// The only permissible threads are the main thread, the worker thread, the // servo threads. If the latter, we must be traversing. bool traversing = ServoStyleSet::IsInServoTraversal();
MOZ_ASSERT(traversing); return traversing;
}
/* static */ ServoStyleSet* gfxFontUtils::CurrentServoStyleSet() { // If we are on a worker thread, we must not check for the current set since // the main/servo threads may be busy in parallel. if (dom::GetCurrentThreadWorkerPrivate()) { return nullptr;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.50Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.