mac 字體遍歷demo

文章目錄

    • 邏輯字體類
    • 頭文件
    • 實現文件
    • 使用文件主程序
    • CMakeLists文件
    • 腳本文件

邏輯字體類

#ifndef LOGICAL_FONT_H
#define LOGICAL_FONT_H#include <string>
#include <memory>
#include <CoreText/CoreText.h>
#include <CoreFoundation/CoreFoundation.h>class LogicalFont {
public:LogicalFont() = default;~LogicalFont() {if (character_set_) {CFRelease(character_set_);}}// Getters and setters for font namesconst std::string& en_family_name() const { return family_name_; }const std::string& en_face_name() const { return style_name_; }const std::string& en_postscript_name() const { return postscript_name_; }const std::string& localized_family_name() const { return localized_family_name_; }const std::string& localized_style_name() const { return localized_style_name_; }const std::string& localized_postscript_name() const { return localized_postscript_name_; }const std::string& full_name() const { return full_name_; }const std::string& font_path() const { return font_path_; }void set_family_name(const std::string& name) { family_name_ = name; }void set_style_name(const std::string& name) { style_name_ = name; }void set_postscript_name(const std::string& name) { postscript_name_ = name; }void set_localized_family_name(const std::string& name) { localized_family_name_ = name; }void set_localized_style_name(const std::string& name) { localized_style_name_ = name; }void set_localized_postscript_name(const std::string& name) { localized_postscript_name_ = name; }void set_full_name(const std::string& name) { full_name_ = name; }void set_font_path(const std::string& path) { font_path_ = path; }// Getters and setters for font metricsint32_t ascent() const { return ascent_; }int32_t descent() const { return descent_; }int32_t line_gap() const { return line_gap_; }int32_t cap_height() const { return cap_height_; }int32_t x_height() const { return x_height_; }int32_t underline_position() const { return underline_position_; }int32_t underline_thickness() const { return underline_thickness_; }int32_t strikethrough_position() const { return strikethrough_position_; }int32_t strikethrough_thickness() const { return strikethrough_thickness_; }int32_t slant_angle() const { return slant_angle_; }float weight() const { return weight_; }float width() const { return width_; }void set_ascent(int32_t value) { ascent_ = value; }void set_descent(int32_t value) { descent_ = value; }void set_line_gap(int32_t value) { line_gap_ = value; }void set_cap_height(int32_t value) { cap_height_ = value; }void set_x_height(int32_t value) { x_height_ = value; }void set_underline_position(int32_t value) { underline_position_ = value; }void set_underline_thickness(int32_t value) { underline_thickness_ = value; }void set_strikethrough_position(int32_t value) { strikethrough_position_ = value; }void set_strikethrough_thickness(int32_t value) { strikethrough_thickness_ = value; }void set_slant_angle(int32_t value) { slant_angle_ = value; }void set_weight(float value) { weight_ = value; }void set_width(float value) { width_ = value; }// Getters and setters for font style attributesbool bold() const { return bold_; }bool italic() const { return italic_; }void set_bold(bool value) { bold_ = value; }void set_italic(bool value) { italic_ = value; }// Character set handlingCFCharacterSetRef character_set() const { return character_set_; }void set_character_set(CFCharacterSetRef charset) {if (character_set_) {CFRelease(character_set_);}// 添加顯式類型轉換character_set_ = (CFCharacterSetRef)CFRetain(charset);}// CTFontRef handlingCTFontRef logical_font() const { return logical_font_; }void set_logical_font(CTFontRef font) { logical_font_ = font; }private:// Font namesstd::string family_name_;               // English family namestd::string style_name_;                // English style/face namestd::string postscript_name_;           // English PostScript namestd::string localized_family_name_;     // Localized family namestd::string localized_style_name_;      // Localized style namestd::string localized_postscript_name_; // Localized PostScript namestd::string full_name_;                 // Full font name (family + style)std::string font_path_;                 // Path to font file// Font metricsint32_t ascent_ = 0;int32_t descent_ = 0;int32_t line_gap_ = 0;int32_t cap_height_ = 0;int32_t x_height_ = 0;int32_t underline_position_ = 0;int32_t underline_thickness_ = 0;int32_t strikethrough_position_ = 0;int32_t strikethrough_thickness_ = 0;int32_t slant_angle_ = 0;float weight_ = 0.0f;float width_ = 0.0f;// Font style attributesbool bold_ = false;bool italic_ = false;// Character setCFCharacterSetRef character_set_ = nullptr;// CoreText font reference (weak reference, not owned)CTFontRef logical_font_ = nullptr;
};#endif // LOGICAL_FONT_H

頭文件


#pragma once
#include <memory>
#include <CoreText/CoreText.h>
#include <type_traits>
#include <CoreText/CoreText.h>
#include <CoreGraphics/CoreGraphics.h>
#include <iostream>#include<memory>
#include <CoreText/CoreText.h>#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include<unordered_set>
#include "LogicalFont.hpp"namespace FontUtils {// CFString轉std::stringstd::string CFStringToStdString(CFStringRef cfStr);// Unicode范圍結構體struct UnicodeRange {uint32_t start;  // 范圍起始碼點uint32_t end;    // 范圍結束碼點};// CFURL轉文件路徑std::string CFURLToPath(CFURLRef url);// 字符串規范化(去空格/符號+轉小寫)std::string NormalizeString(std::string input);} // namespace FontUtilsclass FontManagerMac
{
public:FontManagerMac() {};~FontManagerMac() {};void EnumerateSystemFonts();private:// 處理所有字體家族void ProcessFontFamilies(CFArrayRef fontFamilies);// 處理單個字體家族void ProcessSingleFontFamily(CFStringRef familyName);// 處理字體描述符數組void ProcessFontDescriptors(CFArrayRef fontDescriptors, CFStringRef familyName);// 處理單個字體void ProcessSingleFont(CTFontDescriptorRef fontDescriptor, CFStringRef familyName, CFIndex index);void StoreFontInfo(const std::shared_ptr<LogicalFont>& log_font);bool GetFontInfo(std::shared_ptr<LogicalFont>& font, CTFontRef ctFont);bool GetExtendedFontMetrics(std::shared_ptr<LogicalFont> &font, CTFontRef ctf_font);std::vector<FontUtils::UnicodeRange> GetSupportedUnicodeRanges(CTFontRef font);public: //為了便于演示這些數據,直接設置為公開的// 字體對象映射容器std::unordered_map<std::string, std::shared_ptr<LogicalFont>> postscript_to_font_;std::unordered_map<std::string, std::shared_ptr<LogicalFont>> local_postscript_to_font_;std::unordered_map<std::string, std::shared_ptr<LogicalFont>> full_to_font_;// 名稱集合容器std::unordered_set<std::string> family_set_;std::unordered_set<std::string> postscript_set_;std::unordered_set<std::string> local_family_set_;std::unordered_set<std::string> local_postscript_set_;// 名稱映射容器std::unordered_map<std::string, std::string> postscript_to_family_;std::unordered_map<std::string, std::string> en_to_local_family_;std::unordered_map<std::string, std::string> local_to_en_ps_;std::map<std::string, std::vector<FontUtils::UnicodeRange>> font_unicode_ranges_map_ ; // 打印所有字體容器數據void PrintAllFontData() const {std::cout << "\n========== Font Container Data ==========\n";PrintFontMaps();PrintNameSets();PrintNameMappings();// PrintUnicodeRanges();std::cout << "========================================\n";}
private:// 打印字體對象映射void PrintFontMaps() const {std::cout << "\n[Font Object Mappings]\n";PrintMap("PostScript to Font", postscript_to_font_);PrintMap("Localized PostScript to Font", local_postscript_to_font_);PrintMap("Full Name to Font", full_to_font_);}// 打印名稱集合void PrintNameSets() const {std::cout << "\n[Name Sets]\n";PrintSet("Family Names", family_set_);PrintSet("PostScript Names", postscript_set_);PrintSet("Localized Family Names", local_family_set_);PrintSet("Localized PostScript Names", local_postscript_set_);}// 打印名稱映射void PrintNameMappings() const {std::cout << "\n[Name Mappings]\n";PrintStringMap("PostScript to Family", postscript_to_family_);PrintStringMap("English to Local Family", en_to_local_family_);PrintStringMap("Local to English PostScript", local_to_en_ps_);}// 打印Unicode范圍void PrintUnicodeRanges() const {std::cout << "\n[Unicode Ranges by Font]\n";for (const auto& [fontName, ranges] : font_unicode_ranges_map_) {std::cout << "  " << fontName << ":\n";for (const auto& range : ranges) {std::cout << "    U+" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << range.start << "-U+" << std::setw(4) << range.end << std::dec << "\n";}}}// 輔助函數:打印unordered_map<string, shared_ptr>template<typename T>void PrintMap(const std::string& title, const std::unordered_map<std::string, std::shared_ptr<T>>& map) const {std::cout << "  " << title << " (" << map.size() << " items):\n";for (const auto& [key, value] : map) {std::cout << "    " << std::setw(40) << std::left << key << " -> " << (value ? value->en_postscript_name() : "nullptr") << "\n";}}// 輔助函數:打印unordered_set<string>void PrintSet(const std::string& title, const std::unordered_set<std::string>& set) const {std::cout << "  " << title << " (" << set.size() << " items):\n    ";size_t count = 0;for (const auto& item : set) {std::cout << item;if (++count % 5 == 0 && count != set.size()) std::cout << "\n    ";else if (count != set.size()) std::cout << ", ";}std::cout << "\n";}// 輔助函數:打印unordered_map<string, string>void PrintStringMap(const std::string& title, const std::unordered_map<std::string, std::string>& map) const {std::cout << "  " << title << " (" << map.size() << " items):\n";for (const auto& [key, value] : map) {std::cout << "    " << std::setw(40) << std::left << key << " -> " << value << "\n";}}
};

實現文件


#include "mac_font_traversal.h"
using std::shared_ptr;namespace FontUtils {std::string CFStringToStdString(CFStringRef cfStr) {if (!cfStr) return "";CFIndex length = CFStringGetLength(cfStr);CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;std::unique_ptr<char[]> buffer(new char[maxSize]);if (CFStringGetCString(cfStr, buffer.get(), maxSize, kCFStringEncodingUTF8)) {return std::string(buffer.get());}return "";}std::string CFURLToPath(CFURLRef url) {if (!url) {return {}; // 返回空字符串如果 URL 是空的}char path[PATH_MAX];if (!CFURLGetFileSystemRepresentation(url, true, (UInt8*)path, PATH_MAX)) {return {}; // 返回空字符串如果轉換失敗}return std::string(path); // 轉換成功,返回路徑字符串}std::string NormalizeString(std::string input) {std::string result;result.reserve(input.size());for (const unsigned char ch : input) {if (ch != ' ' && ch != '-' && ch != '_' && ch != ',' && !std::isspace(ch)) {result += std::tolower(ch);}}return result;}}// 函數:獲取字體支持的Unicode范圍
// 參數:字體引用(CTFontRef)
// 返回值:該字體支持的Unicode范圍集合(vector<UnicodeRange>)
std::vector<FontUtils::UnicodeRange> FontManagerMac::GetSupportedUnicodeRanges(CTFontRef font) {std::vector<FontUtils::UnicodeRange> tempRanges; // 臨時存儲范圍集合if (!font) {  // 檢查字體引用是否有效return tempRanges; // 無效則返回空集合}// 1. 獲取字體支持的字符集CFCharacterSetRef charset = CTFontCopyCharacterSet(font); // 復制字體字符集// 創建字符集的位圖表示CFDataRef bitmapData = CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault, charset);const UInt8 *bitmap = CFDataGetBytePtr(bitmapData); // 獲取位圖數據指針CFIndex length = CFDataGetLength(bitmapData);      // 獲取位圖數據長度bool inRange = false;   // 標記是否處于連續范圍內uint32_t start = 0;     // 當前范圍的起始碼點uint32_t maxChar = 0;   // 當前范圍的結束碼點// 2. 遍歷位圖,檢測并合并連續范圍for (uint32_t byteIndex = 0; byteIndex < length; byteIndex++) {UInt8 byte = bitmap[byteIndex]; // 獲取當前字節if (byte == 0) {  // 如果字節為0,表示沒有支持的字符if (inRange) { // 如果之前處于范圍內,則結束當前范圍tempRanges.push_back({start, (byteIndex << 3) - 1});inRange = false;}continue; // 跳過后續處理}// 檢查字節中的每一位(共8位)for (uint32_t bit = 0; bit < 8; bit++) {uint32_t currentChar = (byteIndex << 3) + bit; // 計算當前字符碼點bool isSupported = (byte & (1 << bit)) != 0;   // 檢查當前位是否被支持if (isSupported) {  // 如果字符被支持if (!inRange) { // 如果不在范圍內,則開始新范圍start = currentChar;inRange = true;}maxChar = currentChar; // 更新范圍結束碼點} else if (inRange) { // 如果字符不被支持但之前處于范圍內tempRanges.push_back({start, currentChar - 1}); // 結束當前范圍inRange = false;}}}// 處理最后一個范圍(如果遍歷結束時仍處于范圍內)if (inRange) {tempRanges.push_back({start, maxChar});}// 3. 壓縮范圍(合并相鄰或重疊的范圍)if (!tempRanges.empty()) {size_t compressedCount = 0; // 壓縮后的范圍計數// 遍歷所有范圍for (size_t i = 1; i < tempRanges.size(); i++) {// 如果當前范圍與前一個范圍相鄰或重疊if (tempRanges[i].start <= tempRanges[compressedCount].end + 1) {// 合并范圍(取最大的結束碼點)if (tempRanges[i].end > tempRanges[compressedCount].end) {tempRanges[compressedCount].end = tempRanges[i].end;}} else {// 不重疊則保留當前范圍compressedCount++;tempRanges[compressedCount] = tempRanges[i];}}// 調整向量大小為壓縮后的數量tempRanges.resize(compressedCount + 1);}// 釋放資源CFRelease(bitmapData);CFRelease(charset);return tempRanges; // 返回最終的范圍集合
}
void FontManagerMac::StoreFontInfo(const std::shared_ptr<LogicalFont>& font) {// 規范化名稱const auto norm_face_name = FontUtils::NormalizeString(font->en_face_name());const auto norm_family_name = FontUtils::NormalizeString(font->en_family_name());const auto norm_ps_name = FontUtils::NormalizeString(font->en_postscript_name());const auto norm_local_ps_name = FontUtils::NormalizeString(font->localized_postscript_name());const auto norm_local_family_name = FontUtils::NormalizeString(font->localized_family_name());const auto norm_full_name = FontUtils::NormalizeString(font->full_name());// 字體對象映射postscript_to_font_.emplace(norm_ps_name, font);local_postscript_to_font_.emplace(norm_local_ps_name, font);full_to_font_.emplace(norm_full_name, font);// 名稱集合family_set_.insert(norm_family_name);postscript_set_.insert(norm_ps_name);// 家族與Postscript名映射//family_to_postscript_[norm_family_name].insert(norm_ps_name);postscript_to_family_.emplace(norm_ps_name, norm_family_name);// 本地化名稱集合local_family_set_.insert(font->localized_family_name());local_postscript_set_.insert(font->localized_postscript_name());// 本地化與標準名稱映射en_to_local_family_.emplace(norm_family_name, norm_local_family_name);local_to_en_ps_.emplace(norm_local_ps_name, norm_ps_name);//處理對應的unicode 支持范圍font_unicode_ranges_map_.try_emplace(norm_family_name,GetSupportedUnicodeRanges(font->logical_font()));}// 枚舉系統字體void FontManagerMac::EnumerateSystemFonts() {// 獲取系統所有可用字體家族名稱數組CFArrayRef fontFamilies = CTFontManagerCopyAvailableFontFamilyNames();// 檢查是否成功獲取字體家族列表if (!fontFamilies) {std::cerr << "Error: Unable to get system font family list" << std::endl;return;}// 處理所有字體家族ProcessFontFamilies(fontFamilies);// 釋放字體家族數組內存CFRelease(fontFamilies);}// 處理所有字體家族void FontManagerMac::ProcessFontFamilies(CFArrayRef fontFamilies) {// 獲取字體家族數量CFIndex familyCount = CFArrayGetCount(fontFamilies);// 遍歷每個字體家族for (CFIndex i = 0; i < familyCount; ++i) {// 獲取當前索引的字體家族名稱CFStringRef familyName = (CFStringRef)CFArrayGetValueAtIndex(fontFamilies, i);// 檢查是否成功獲取家族名稱if (!familyName) {std::cerr << "Warning: Failed to get font family name at index " << i << std::endl;continue;}// 處理單個字體家族ProcessSingleFontFamily(familyName);}}// 處理單個字體家族void FontManagerMac::ProcessSingleFontFamily(CFStringRef familyName) {// 創建字體描述符(指定家族名稱和默認大小0)CTFontDescriptorRef familyDescriptor = CTFontDescriptorCreateWithNameAndSize(familyName, 0);// 檢查是否成功創建描述符if (!familyDescriptor) {std::cerr << "Warning: Failed to create descriptor for family "<< FontUtils::CFStringToStdString(familyName) << std::endl;return;}// 獲取匹配該家族的所有字體描述符CFArrayRef fontDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, NULL);// 釋放家族描述符內存CFRelease(familyDescriptor);// 檢查是否獲取到字體描述符if (!fontDescriptors) {std::cerr << "Warning: No fonts found for family "<< FontUtils::CFStringToStdString(familyName) << std::endl;return;}// 處理該家族下的所有字體描述符ProcessFontDescriptors(fontDescriptors, familyName);// 釋放字體描述符數組內存CFRelease(fontDescriptors);}// 處理字體描述符數組void FontManagerMac::ProcessFontDescriptors(CFArrayRef fontDescriptors, CFStringRef familyName) {// 獲取字體描述符數量CFIndex fontCount = CFArrayGetCount(fontDescriptors);// 遍歷每個字體描述符for (CFIndex j = 0; j < fontCount; ++j) {// 獲取當前索引的字體描述符CTFontDescriptorRef fontDescriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fontDescriptors, j);// 處理單個字體ProcessSingleFont(fontDescriptor, familyName, j);}}// 處理單個字體void FontManagerMac::ProcessSingleFont(CTFontDescriptorRef fontDescriptor, CFStringRef familyName, CFIndex index) {// 根據描述符創建字體對象CTFontRef font = CTFontCreateWithFontDescriptor(fontDescriptor, 0.0, NULL);// 檢查是否成功創建字體if (!font) {std::cerr << "Warning: Failed to create font for descriptor " << index<< " in family " << FontUtils::CFStringToStdString(familyName) << std::endl;return;}// 創建邏輯字體對象auto log_font = std::make_shared<LogicalFont>();// 設置字體屬性并存儲有效字體if (GetFontInfo(log_font, font)) {StoreFontInfo(log_font);}// 釋放字體對象內存CFRelease(font);}bool FontManagerMac::GetExtendedFontMetrics(std::shared_ptr<LogicalFont>& font, CTFontRef ctf_font) {if (!ctf_font || !font) return false;// 獲取基本度量信息font->set_ascent(static_cast<int32_t>(CTFontGetAscent(ctf_font)));font->set_descent(static_cast<int32_t>(CTFontGetDescent(ctf_font)));font->set_line_gap(static_cast<int32_t>(CTFontGetLeading(ctf_font)));font->set_cap_height(static_cast<int32_t>(CTFontGetCapHeight(ctf_font)));font->set_x_height(static_cast<int32_t>(CTFontGetXHeight(ctf_font)));// 下劃線信息font->set_underline_position(static_cast<int32_t>(CTFontGetUnderlinePosition(ctf_font)));font->set_underline_thickness(static_cast<int32_t>(CTFontGetUnderlineThickness(ctf_font)));// 刪除線信息(估算)font->set_strikethrough_position(static_cast<int32_t>(font->strikethrough_position() * 0.5f));font->set_strikethrough_thickness(font->underline_thickness());// 斜體角度if (&CTFontGetSlantAngle != NULL) {font->set_slant_angle(static_cast<int32_t>(CTFontGetSlantAngle(ctf_font)));}// 字重CGFloat fontWeight = 0.0;CFDictionaryRef fontTraits = CTFontCopyTraits(ctf_font);if (fontTraits) {CFNumberRef weightTrait = (CFNumberRef)CFDictionaryGetValue(fontTraits, kCTFontWeightTrait);if (weightTrait) {CFNumberGetValue(weightTrait, kCFNumberCGFloatType, &fontWeight);fontWeight = (fontWeight - 0.4) / 0.6; // 標準化}CFRelease(fontTraits);}font->set_weight(fontWeight);// 字體寬度CGGlyph glyph;UniChar testChar = 'x';if (CTFontGetGlyphsForCharacters(ctf_font, &testChar, &glyph, 1)) {CGSize advance;CTFontGetAdvancesForGlyphs(ctf_font, kCTFontOrientationHorizontal, &glyph, &advance, 1);font->set_width(advance.width);}return true;
}
// 獲取字體信息并填充到LogicalFont對象中
bool FontManagerMac::GetFontInfo(std::shared_ptr<LogicalFont>& font, CTFontRef ctf_font) {if (!font || !ctf_font) return false;CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(ctf_font);if (!descriptor) return false;// 一次性獲取所有基礎屬性CFStringRef family = nullptr;CFStringRef styleName = nullptr;// 獲取 family 和 styleName
if ((family = static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute)))) {font->set_family_name(FontUtils::CFStringToStdString(family));}if ((styleName = static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute)))) {font->set_style_name(FontUtils::CFStringToStdString(styleName));}// 設置全名(需要family和styleName)if (family && styleName) {font->set_full_name(FontUtils::CFStringToStdString(family) + " " +FontUtils::CFStringToStdString(styleName));}// 獲取本地化名稱if (CFStringRef localizedFamily = CTFontCopyLocalizedName(ctf_font, kCTFontFamilyNameKey, nullptr)) {font->set_localized_family_name(FontUtils::CFStringToStdString(localizedFamily));CFRelease(localizedFamily);}if (styleName) { // 本地化樣式名需要styleNameif (CFStringRef localizedStyle = CTFontCopyLocalizedName(ctf_font, kCTFontStyleNameKey, nullptr)) {font->set_localized_style_name(FontUtils::CFStringToStdString(localizedStyle));CFRelease(localizedStyle);}}// 獲取PostScript相關名稱(獨立操作)if (CFStringRef psName = CTFontCopyPostScriptName(ctf_font)) {font->set_postscript_name(FontUtils::CFStringToStdString(psName));CFRelease(psName);if (CFStringRef localizedPsName = CTFontCopyLocalizedName(ctf_font, kCTFontPostScriptNameKey, nullptr)) {font->set_localized_postscript_name(FontUtils::CFStringToStdString(localizedPsName));CFRelease(localizedPsName);}}// 獲取字符集if (CFCharacterSetRef fontChars = CTFontCopyCharacterSet(ctf_font)) {font->set_character_set(fontChars);CFRelease(fontChars);}// 獲取字體路徑if (CFURLRef fontURL = static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))) {font->set_font_path(FontUtils::CFURLToPath(fontURL));CFRelease(fontURL);}// 釋放基礎屬性if (family) CFRelease(family);if (styleName) CFRelease(styleName);// 獲取擴展屬性GetExtendedFontMetrics(font, ctf_font);font->set_logical_font(ctf_font);CFRelease(descriptor);return true;
}

使用文件主程序

#include "mac_font_traversal.h"int main()
{FontManagerMac  font_manager;font_manager.EnumerateSystemFonts();font_manager.PrintAllFontData();
}

CMakeLists文件

cmake_minimum_required(VERSION 3.15)
project(FontManagerMac)# 設置C++標準
set(CMAKE_CXX_STANDARD 17)# 查找macOS系統框架
find_library(COREFOUNDATION CoreFoundation REQUIRED)
find_library(CORETEXT CoreText REQUIRED)# 添加庫目標
add_executable(FontManagerMac${CMAKE_CURRENT_SOURCE_DIR}/LogicalFont.hpp${CMAKE_CURRENT_SOURCE_DIR}/mac_font_traversal.h${CMAKE_CURRENT_SOURCE_DIR}/mac_font_traversal.cpp${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)# 鏈接系統框架
target_link_libraries(FontManagerMac PRIVATE${COREFOUNDATION}${CORETEXT}
)
# 找到并鏈接 CoreGraphics 和 ImageIO 框架
if(APPLE)find_library(COREGRAPHICS_FRAMEWORK CoreGraphics)find_library(IMAGEIO_FRAMEWORK ImageIO)target_link_libraries(FontManagerMac  PRIVATE ${COREGRAPHICS_FRAMEWORK} ${IMAGEIO_FRAMEWORK})
endif()# 包含當前目錄
target_include_directories(FontManagerMac PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})# 針對Xcode額外設置
if(CMAKE_GENERATOR STREQUAL "Xcode")set_target_properties(FontManagerMac PROPERTIESXCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES"XCODE_ATTRIBUTE_GCC_INPUT_FILETYPE "sourcecode.cpp.utf-8")
endif()

腳本文件

#!/bin/bash# Set root directory
root_dir=$(pwd)# Function to perform the build
build() {local arch="$1"local build_type="$2"# Define directoriesbuild_dir=${root_dir}/build/mainmodule_build/MACOSX/${arch}install_dir=${root_dir}/installecho "Build dir: ${build_dir}"# Remove existing build dir to ensure a clean buildif [ -e $build_dir ]; thenrm -rf $build_dirfi# CMake command with common parameterscmake \-DBUILD_SHARED_LIBS:BOOL=TRUE \-DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE \-DCMAKE_BUILD_TYPE:STRING=${build_type} \-DCMAKE_INSTALL_PREFIX=${install_dir} \-DCMAKE_OSX_ARCHITECTURES=${arch} \-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \-DSYSTEM:STRING=Darwin \-DAFS_TARGET_PLATFORM=mac \-DAFS_BUILD_MODE:STRING=build \-G "Xcode" \-S ${root_dir} \-B ${build_dir}# Build and installcmake --build ${build_dir} \--config ${build_type} \-j 14 \--
}# Call build function for Debug configurations only
build x86_64 Debug
# build arm64 Debug# # 定義輸出路徑
# output_path="${root_dir}/install/bin"
# debug_libs_dir="${output_path}/Debug"# # 確保Debug目錄存在
# mkdir -p "${debug_libs_dir}"# # 檢查要合并的庫文件是否存在
# x86_lib="${output_path}/x86_64/Debug/PDFCore.dylib"
# arm_lib="${output_path}/arm64/Debug/PDFCore.dylib"# if [[ ! -f "${x86_lib}" || ! -f "${arm_lib}" ]]; then
#     echo "錯誤:找不到要合并的庫文件"
#     echo "x86_64 庫路徑: ${x86_lib} - $(test -f "${x86_lib}" && echo "存在" || echo "不存在")"
#     echo "arm64 庫路徑: ${arm_lib} - $(test -f "${arm_lib}" && echo "存在" || echo "不存在")"
#     exit 1
# fi# # 合并Debug版本庫
# echo "正在合并Debug庫..."
# lipo -create \
#   "${x86_lib}" \
#   "${arm_lib}" \
#   -output "${debug_libs_dir}/PDFCore.dylib"# # 驗證合并后的庫
# if [[ -f "${debug_libs_dir}/PDFCore.dylib" ]]; then
#     echo "驗證合并后的庫架構:"
#     lipo -info "${debug_libs_dir}/PDFCore.dylib"
#     echo "庫合并成功完成。"
# else
#     echo "錯誤:合并后的庫文件未生成"
#     exit 1
# fi

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94132.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94132.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94132.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025牛客多校第六場 D.漂亮矩陣 K.最大gcd C.棧 L.最小括號串 個人題解

L.最小括號串 #數組操作 #貪心 題目 思路 感謝Leratiomyces大佬賽時的提示&#xff0c;否則估計還一直簽不了到&#xff08;&#xff09; 首先&#xff0c;貪心地構造出最優情況&#xff1a;數組左半部分全是(&#xff0c;右半部分全是)&#xff0c;隨后通過判斷給定的區間…

Ubuntu搭建PX4無人機仿真環境(5) —— 仿真環境搭建(以Ubuntu 22.04,ROS2 Humble 為例)

目錄前言1. 準備下載源碼方式一&#xff1a;方式二&#xff1a;安裝依賴安裝 Gazebo2. 安裝 Micro XRCE-DDS Agent3. 編譯4. 通信5. offboard 測試參考前言 本教程基于 ROS2 &#xff0c;在搭建之前&#xff0c;需要把 ROS2、QGC 等基礎環境安裝配置完成。但是這塊的資料相比較…

自動駕駛中的傳感器技術11——Camera(2)

1、自駕Camera關鍵技術點匯總 ADAS Camera 關鍵技術點摘選&#xff08;IEEE-P2020工作組&#xff09;如下&#xff1a; Ref &#xff1a; 5. IEEE 相關標準 - 圖像質量與色彩技術知識庫 https://www.image-engineering.de/content/library/white_paper/P2020_white_paper.pd…

福彩雙色球第2025088期籃球號碼分析

蔡楚門福彩雙色球第2025088期籃球號碼分析&#xff0c;上期開出籃球號碼數字08&#xff0c;數字形式是合數偶數2路球數字&#xff0c;小號區域&#xff0c;0字頭數字。本期籃球號碼分析&#xff0c;4尾數0414遺漏9期上次遺漏11期&#xff0c;2尾數0212遺漏4期上次遺漏27期&…

【兆易創新】單片機GD32F103C8T6系列入門資料

GD32F103xx 系列器件是一款基于ARM Cortex-M3 RISC內核的32位通用微控制器&#xff0c;在處理能力、降低功耗和外設方面具有超優的性價比。Cortex-M3是下一代處理器核心&#xff0c;它與嵌套矢量中斷控制器(NVIC)&#xff0c; SysTick計時器和高級調試支持緊密耦合。 GD32F103…

高效輕量的C++ HTTP服務:cpp-httplib使用指南

文章目錄httplib介紹與安裝使用案例httplib介紹與安裝 C HTTP 庫&#xff08;cpp-httplib&#xff09;是一個輕量級的 C HTTP 客戶端/服務器庫&#xff0c;它提供了簡單的 API 來創建 HTTP 服務器和客戶端&#xff0c;支持同步和異步操作。以下是一些關于cpp-httplib 的主要特…

24 SAP CPI 調用SAP HTTP接口

SAP CPI 訪問SAP接口一般用RFC或者HTTP,個人在項目中兩種方法都用過,最后還是傾向于HTTP的方式,此方式易于維護,統一管理,接口搭建比較方便。 讀者朋友可網上自行搜索"SAP 發布HTTP接口",SAP CPI調用SAP發布的HTTP接口。 配置CPI接口前,需要將CPI的證書導入…

C/C++常用字符串函數

一、字符串函數介紹&#xff1a; 字符串作為程序中常用的數據類型&#xff0c;學會對字符串進行處理是作為一名C/C程序員的基本功&#xff0c;我們要學會使用相關函數&#xff0c;并且對重點函數要會自己手動實現&#xff08;下文對重點函數有實現代碼以及相關示例&#xff09…

YOLO的Python實現以及 OpenCV

YOLO的Python實現以及 OpenCV Darknet 實現 YOLO 從頭開始開發 YOLO模型不容易&#xff0c;所以我們要使用預訓練模型在項目里進行目 標檢測。你可以在 https://pjreddie.com里到所有可用的預訓練模型。這是 Joseph C. Redmon的主頁&#xff0c;他是 Darknet的維護者。 注意 …

譯|Netflix 數據平臺運營中基于機器學習自動修復系統

來自上傳文件中的文章《Evolving from Rule-based Classifier: Machine Learning Powered Auto Remediation in Netflix Data Platform》 本文介紹了Netflix如何將基于規則的錯誤分類器與機器學習服務集成&#xff0c;實現Spark作業失敗的自動修復。技術亮點包括結合規則和ML智…

PAES算法求解 ZDT1 雙目標優化問題

前言 提醒&#xff1a; 文章內容為方便作者自己后日復習與查閱而進行的書寫與發布&#xff0c;其中引用內容都會使用鏈接表明出處&#xff08;如有侵權問題&#xff0c;請及時聯系&#xff09;。 其中內容多為一次書寫&#xff0c;缺少檢查與訂正&#xff0c;如有問題或其他拓展…

邏輯回歸的應用

一參數邏輯回歸參數及多分類策略等完整解析LogisticRegression 初始參數聲明LogisticRegression(penaltyl2, dualFalse, tol0.0001, C1.0, fit_interceptTrue, intercept_scaling1, class_weightNone, random_stateNone, solverliblinear, max_iter100, multi_classovr, verbos…

C語言(長期更新)第7講:VS實用調試技巧

C語言&#xff08;長期更新&#xff09; 第7講 VS實用調試技巧 跟著潼心走&#xff0c;輕松拿捏C語言&#xff0c;困惑通通走&#xff0c;一去不回頭~歡迎開始今天的學習內容&#xff0c;你的支持就是博主最大的動力。 目錄 C語言&#xff08;長期更新&#xff09; 第7講 …

CONTRASTIVE-KAN:一種用于稀缺標記數據的網絡安全半監督入侵檢測框架

研究背景與挑戰? ?工業環境需求?: 第四次工業革命中,物聯網(IoT)和工業物聯網(IIoT)的普及使網絡安全成為關鍵挑戰。 入侵檢測系統需實時性高,尤其對關鍵基礎設施(如燃氣管道)的快速攻擊檢測至關重要。 ?核心問題?: ?標簽數據稀缺?:工業系統多數時間處于正常…

綜合:單臂路由+三層交換技術+telnet配置+DHCP

技術考核1 實驗拓撲&#xff1a;實驗需求 1.按照圖示配置IP地址設備名 2.在SW1和SW2之間配置鏈路聚合增加鏈路帶寬&#xff0c;提高可靠性 3.PC5和PC6屬于VLAN10&#xff0c; PC7和PC8屬于VLAN20 4.SW1和SW2屬于二層交換機&#xff0c;SW3為三層交換機&#xff08;VLAN100用于對…

工業火焰識別漏報率↓78%!陌訊多模態融合算法實戰解析

原創聲明&#xff1a;本文技術方案解析基于陌訊技術白皮書2025版 標簽&#xff1a;#陌訊視覺算法 #火焰識別優化 #工業安全監控 #邊緣計算優化一、行業痛點&#xff1a;工業火災監控的漏檢危機據《2025工業安全白皮書》統計&#xff0c;化工場景傳統火焰識別系統漏報率高達35%&…

C++引用:高效安全的別名機制詳解

目錄 一、引用的概念 二、引用的特性 1、定義時必須初始化 2、一個變量可以有多個引用 3、引用一旦綁定實體就不能更改 三、const引用&#xff08;常引用&#xff09; 1、const引用的基本特性 2、臨時對象與const引用 3、臨時對象的特性 4、const 引用作為函數形參 …

大語言模型API付費?

下面是目前主流 大語言模型 API 的付費情況總覽&#xff1a; &#x1f9e0; 一、主要大語言模型 API&#xff1a;是否付費對比 提供方模型是否免費限制 / 說明OpenAIGPT-3.5 / GPT-4 / GPT-4o? 付費為主有免費額度&#xff08;如 ChatGPT 免費版&#xff09;&#xff0c;API …

巧用Wisdom SSH:容器化運維與傳統運維的抉擇

巧用Wisdom SSH&#xff1a;容器化運維與傳統運維的抉擇 在當下的技術領域&#xff0c;容器化運維與傳統運維是運維人員面臨的兩大主要方向&#xff0c;對于從業者來說&#xff0c;如何抉擇至關重要&#xff0c;而Wisdom SSH在其中能發揮顯著作用。 傳統運維&#xff1a;基石…

API征服者:Python抓取星鏈衛星實時軌跡

API征服者&#xff1a;Python抓取星鏈衛星實時軌跡從基礎調用到工業級衛星追蹤系統實戰指南一、太空數據時代&#xff1a;星鏈衛星的全球覆蓋??星鏈衛星網絡規模??&#xff1a;已發射衛星數量&#xff1a;4,000目標衛星總數&#xff1a;42,000軌道高度&#xff1a;340km - …