///////////////////////////////////////////////////////
| 452 | |
| 453 | //////////////////////////////////////////////////////////// |
| 454 | bool Font::openFromStreamImpl(InputStream& stream, std::string_view type) |
| 455 | { |
| 456 | // Cleanup the previous resources |
| 457 | cleanup(); |
| 458 | |
| 459 | auto fontHandles = std::make_shared<FontHandles>(); |
| 460 | |
| 461 | // Initialize FreeType |
| 462 | // Note: we initialize FreeType for every font instance in order to avoid having a single |
| 463 | // global manager that would create a lot of issues regarding creation and destruction order. |
| 464 | if (FT_Init_FreeType(&fontHandles->library) != 0) |
| 465 | { |
| 466 | err() << "Failed to load font from " << type << " (failed to initialize FreeType)" << std::endl; |
| 467 | return false; |
| 468 | } |
| 469 | |
| 470 | // Prepare a wrapper for our stream, that we'll pass to FreeType callbacks |
| 471 | fontHandles->streamRec.base = nullptr; |
| 472 | fontHandles->streamRec.size = static_cast<unsigned long>(stream.getSize().value()); |
| 473 | fontHandles->streamRec.pos = 0; |
| 474 | fontHandles->streamRec.descriptor.pointer = &stream; |
| 475 | fontHandles->streamRec.read = &read; |
| 476 | fontHandles->streamRec.close = &close; |
| 477 | |
| 478 | // Setup the FreeType callbacks that will read our stream |
| 479 | FT_Open_Args args; |
| 480 | args.flags = FT_OPEN_STREAM; |
| 481 | args.stream = &fontHandles->streamRec; |
| 482 | args.driver = nullptr; |
| 483 | |
| 484 | // Load the new font face from the specified stream |
| 485 | FT_Face face = nullptr; |
| 486 | if (FT_Open_Face(fontHandles->library, &args, 0, &face) != 0) |
| 487 | { |
| 488 | err() << "Failed to load font from " << type << " (failed to create the font face)" << std::endl; |
| 489 | return false; |
| 490 | } |
| 491 | fontHandles->face = face; |
| 492 | |
| 493 | // Load the stroker that will be used to outline the font |
| 494 | if (FT_Stroker_New(fontHandles->library, &fontHandles->stroker) != 0) |
| 495 | { |
| 496 | err() << "Failed to load font from " << type << " (failed to create the stroker)" << std::endl; |
| 497 | return false; |
| 498 | } |
| 499 | |
| 500 | // Select the Unicode character map |
| 501 | if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) |
| 502 | { |
| 503 | err() << "Failed to load font from " << type << " (failed to set the Unicode character set)" << std::endl; |
| 504 | return false; |
| 505 | } |
| 506 | |
| 507 | // Store the loaded font handles |
| 508 | m_fontHandles = std::move(fontHandles); |
| 509 | |
| 510 | // Store the font information |
| 511 | m_info.id = getUniqueId(); |
nothing calls this directly
no test coverage detected