Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/gfx/skia/skia/src/sfnt/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  SkOTUtils.cpp   Sprache: C

 
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include <array>

#include "src/sfnt/SkOTUtils.h"

#include "include/core/SkData.h"
#include "include/core/SkStream.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkEndian.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/sfnt/SkOTTableTypes.h"
#include "src/sfnt/SkOTTable_head.h"
#include "src/sfnt/SkOTTable_name.h"
#include "src/sfnt/SkSFNTHeader.h"

uint32_t SkOTUtils::CalcTableChecksum(SK_OT_ULONG *data, size_t length) {
    uint32_t sum = 0;
    SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG);
    for (; data < dataEnd; ++data) {
        sum += SkEndian_SwapBE32(*data);
    }
    return sum;
}

SkData* SkOTUtils::RenameFont(SkStreamAsset* fontData, const char* fontName, int fontNameLen) {

    // Get the sfnt header.
    SkSFNTHeader sfntHeader;
    if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) {
        return nullptr;
    }

    // Find the existing 'name' table.
    int tableIndex;
    SkSFNTHeader::TableDirectoryEntry tableEntry;
    int numTables = SkEndian_SwapBE16(sfntHeader.numTables);
    for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
        if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) {
            return nullptr;
        }
        if (SkOTTableName::TAG == tableEntry.tag) {
            break;
        }
    }
    if (tableIndex == numTables) {
        return nullptr;
    }

    if (!fontData->rewind()) {
        return nullptr;
    }

    // The required 'name' record types: Family, Style, Unique, Full and PostScript.
    static constexpr std::array<SkOTTableName::Record::NameID::Predefined::Value, 5> names{{
        SkOTTableName::Record::NameID::Predefined::FontFamilyName,
        SkOTTableName::Record::NameID::Predefined::FontSubfamilyName,
        SkOTTableName::Record::NameID::Predefined::UniqueFontIdentifier,
        SkOTTableName::Record::NameID::Predefined::FullFontName,
        SkOTTableName::Record::NameID::Predefined::PostscriptName,
    }};

    // GDI will not use a Symbol cmap table if there is no Symbol encoded name.
    static constexpr std::array<SkOTTableName::Record::EncodingID::Windows::Value, 2> encodings{{
        SkOTTableName::Record::EncodingID::Windows::Symbol,
        SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2,
    }};

    // Copy the data, leaving out the old name table.
    // In theory, we could also remove the DSIG table if it exists.
    size_t nameTableLogicalSize = sizeof(SkOTTableName)
                                + (encodings.size() * names.size() * sizeof(SkOTTableName::Record))
                                + (fontNameLen * sizeof(SK_OT_USHORT));
    size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4.

    size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) &&nbsp;~3; // Rounded up to a multiple of 4.
    size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset);

    //originalDataSize is the size of the original data without the name table.
    size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize;
    size_t newDataSize = originalDataSize + nameTablePhysicalSize;

    auto rewrittenFontData = SkData::MakeUninitialized(newDataSize);
    SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(rewrittenFontData->writable_data());

    if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) {
        return nullptr;
    }
    if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) {
        return nullptr;
    }
    if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) {
        return nullptr;
    }

    //Fix up the offsets of the directory entries after the old 'name' table entry.
    SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader));
    SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables;
    SkSFNTHeader::TableDirectoryEntry* headTableEntry = nullptr;
    for (; currentEntry < endEntry; ++currentEntry) {
        uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
        if (oldOffset > oldNameTableOffset) {
            currentEntry->offset = SkEndian_SwapBE32(SkToU32(oldOffset - oldNameTablePhysicalSize));
        }

        if (SkOTTableHead::TAG == currentEntry->tag) {
            headTableEntry = currentEntry;
        }
    }

    // Make the table directory entry point to the new 'name' table.
    SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
    nameTableEntry->logicalLength = SkEndian_SwapBE32(SkToU32(nameTableLogicalSize));
    nameTableEntry->offset = SkEndian_SwapBE32(SkToU32(originalDataSize));

    // Write the new 'name' table after the original font data.
    SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
    unsigned short stringOffset = sizeof(SkOTTableName) + (encodings.size() * names.size() * sizeof(SkOTTableName::Record));
    nameTable->format = SkOTTableName::format_0;
    nameTable->count = SkEndian_SwapBE16(encodings.size() * names.size());
    nameTable->stringOffset = SkEndian_SwapBE16(stringOffset);

    SkOTTableName::Record* nameRecord = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName));
    for (const auto& encoding : encodings) {
        for (const auto& name : names) {
            nameRecord->platformID.value = SkOTTableName::Record::PlatformID::Windows;
            nameRecord->encodingID.windows.value = encoding;
            nameRecord->languageID.windows.value = SkOTTableName::Record::LanguageID::Windows::English_UnitedStates;
            nameRecord->nameID.predefined.value = name;
            nameRecord->offset = SkEndian_SwapBE16(0);
            nameRecord->length = SkEndian_SwapBE16(SkToU16(fontNameLen * sizeof(SK_OT_USHORT)));
            ++nameRecord;
        }
    }

    SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset);
    for (int i = 0; i < fontNameLen; ++i) {
        nameString[i] = SkEndian_SwapBE16(fontName[i]);
    }

    unsigned char* logical = data + originalDataSize + nameTableLogicalSize;
    unsigned char* physical = data + originalDataSize + nameTablePhysicalSize;
    for (; logical < physical; ++logical) {
        *logical = 0;
    }

    // Update the table checksum in the directory entry.
    nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize));

    // Update the checksum adjustment in the head table.
    if (headTableEntry) {
        size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset);
        if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) {
            SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset);
            headTable->checksumAdjustment = SkEndian_SwapBE32(0);
            uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize);
            headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum);
        }
    }

    return rewrittenFontData.release();
}

sk_sp<SkOTUtils::LocalizedStrings_NameTable>
SkOTUtils::LocalizedStrings_NameTable::Make(const SkTypeface& typeface,
                                            SK_OT_USHORT types[],
                                            int typesCount)
{
    static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
    size_t nameTableSize = typeface.getTableSize(nameTag);
    if (0 == nameTableSize) {
        return nullptr;
    }
    std::unique_ptr<uint8_t[]> nameTableData(new uint8_t[nameTableSize]);
    size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get());
    if (copied != nameTableSize) {
        return nullptr;
    }

    return sk_sp<SkOTUtils::LocalizedStrings_NameTable>(
        new SkOTUtils::LocalizedStrings_NameTable(std::move(nameTableData), nameTableSize,
                                                  types, typesCount));
}

sk_sp<SkOTUtils::LocalizedStrings_NameTable>
SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(const SkTypeface& typeface) {
    return Make(typeface,
                SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
                std::size(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
}

bool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) {
    do {
        SkOTTableName::Iterator::Record record;
        if (fFamilyNameIter.next(record)) {
            localizedString->fString = record.name;
            localizedString->fLanguage = record.language;
            return true;
        }
        if (fTypesCount == fTypesIndex + 1) {
            return false;
        }
        ++fTypesIndex;
        fFamilyNameIter.reset(fTypes[fTypesIndex]);
    } while (true);
}

SK_OT_USHORT SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
    SkOTTableName::Record::NameID::Predefined::FontFamilyName,
    SkOTTableName::Record::NameID::Predefined::PreferredFamily,
    SkOTTableName::Record::NameID::Predefined::WWSFamilyName,
};

void SkOTUtils::SetAdvancedTypefaceFlags(SkOTTableOS2_V4::Type fsType,
                                         SkAdvancedTypefaceMetrics* info) {
    SkASSERT(info);
    // The logic should be identical to SkTypeface_FreeType::onGetAdvancedMetrics().
    if (fsType.raw.value != 0) {
        if (SkToBool(fsType.field.Restricted) || SkToBool(fsType.field.Bitmap)) {
            info->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag;
        }
        if (SkToBool(fsType.field.NoSubsetting)) {
            info->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag;
        }
    }
}

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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 und die Messung sind noch experimentell.