Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions src/odr/internal/font/cff_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
#include <odr/internal/font/cff_standard_strings.hpp>
#include <odr/internal/pdf/pdf_encoding.hpp>
#include <odr/internal/util/byte_string.hpp>
#include <odr/internal/util/stream_util.hpp>

#include <cmath>
#include <cstdint>
#include <istream>
#include <iterator>
#include <map>
#include <memory>
#include <stdexcept>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -217,14 +214,6 @@ bool CffFont::is_cff(const std::string_view data) {
static_cast<std::uint8_t>(data[3]) <= 4;
}

CffFont::CffFont(std::unique_ptr<std::istream> stream) {
if (stream == nullptr) {
throw std::invalid_argument("cff: null input stream");
}
m_data = util::stream::read(*stream);
parse();
}

CffFont::CffFont(std::string data) : m_data{std::move(data)} { parse(); }

std::vector<CffFont::Range> CffFont::read_index(const std::uint32_t offset,
Expand Down
4 changes: 0 additions & 4 deletions src/odr/internal/font/cff_font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#include <odr/internal/abstract/font.hpp>

#include <cstdint>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
Expand All @@ -29,8 +27,6 @@ class CffFont final : public abstract::Font {
/// Cheap magic test: a CFF header (major version 1, sane `hdrSize`).
[[nodiscard]] static bool is_cff(std::string_view data);

/// Parse the facts from @p stream; the raw bytes are retained for `data()`.
explicit CffFont(std::unique_ptr<std::istream> stream);
/// Parse the facts from an in-memory CFF blob (retained for `data()`).
explicit CffFont(std::string data);

Expand Down
5 changes: 1 addition & 4 deletions src/odr/internal/font/cff_transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <algorithm>
#include <cstdint>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -189,9 +188,7 @@ std::string cff::wrap_to_otf(const CffFont &font,
static_cast<std::uint16_t>(first),
static_cast<std::uint16_t>(last)));

std::ostringstream out;
build_sfnt(out, 0x4f54544f /* 'OTTO' */, std::move(tables));
return std::move(out).str();
return build_sfnt(0x4f54544f /* 'OTTO' */, std::move(tables));
}

} // namespace odr::internal::font
6 changes: 5 additions & 1 deletion src/odr/internal/font/font_file.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <odr/internal/font/font_file.hpp>

#include <odr/internal/abstract/file.hpp>
#include <odr/internal/abstract/font.hpp>
#include <odr/internal/font/sfnt_font.hpp>
#include <odr/internal/util/stream_util.hpp>

#include <istream>
#include <utility>

namespace odr::internal::font {
Expand All @@ -12,7 +15,8 @@ FontFile::FontFile(std::shared_ptr<abstract::File> file,
: m_file{std::move(file)}, m_file_type{file_type} {
// Parse eagerly: a parse failure is how detection rejects a non-font, so the
// open-strategy try/catch can fall through.
m_font = std::make_shared<sfnt::SfntFont>(m_file->stream());
m_font =
std::make_shared<sfnt::SfntFont>(util::stream::read(*m_file->stream()));
}

std::shared_ptr<abstract::File> FontFile::file() const noexcept {
Expand Down
16 changes: 2 additions & 14 deletions src/odr/internal/font/sfnt_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@

#include <odr/internal/font/sfnt_transform.hpp>
#include <odr/internal/util/byte_string.hpp>
#include <odr/internal/util/stream_util.hpp>
#include <odr/internal/util/string_util.hpp>

#include <algorithm>
#include <cstdint>
#include <istream>
#include <memory>
#include <ostream>
#include <stdexcept>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -179,14 +175,6 @@ bool SfntFont::is_sfnt(const std::string_view data) {
tag == "true" || tag == "ttcf" || tag == "typ1";
}

SfntFont::SfntFont(std::unique_ptr<std::istream> stream) {
if (stream == nullptr) {
throw std::invalid_argument("sfnt: null input stream");
}
m_data = util::stream::read(*stream);
parse();
}

SfntFont::SfntFont(std::string data) : m_data{std::move(data)} { parse(); }

void SfntFont::parse() {
Expand Down Expand Up @@ -506,7 +494,7 @@ void SfntFont::set_cmap(std::map<char32_t, std::uint16_t> cmap) {
update_reverse();
}

void SfntFont::write(std::ostream &out) const {
std::string SfntFont::write() const {
std::vector<std::pair<std::string, std::string>> tables;
tables.reserve(m_tables.size() + 1);
for (const auto &[tag, location] : m_tables) {
Expand Down Expand Up @@ -543,7 +531,7 @@ void SfntFont::write(std::ostream &out) const {
const std::uint32_t version = m_format == FontFormat::opentype_cff
? 0x4f54544fU /* 'OTTO' */
: 0x00010000U;
build_sfnt(out, version, std::move(tables));
return build_sfnt(version, std::move(tables));
}

std::optional<SfntFont::Table>
Expand Down
14 changes: 4 additions & 10 deletions src/odr/internal/font/sfnt_font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

#include <cstdint>
#include <functional>
#include <iosfwd>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
Expand All @@ -26,9 +24,6 @@ class SfntFont final : public abstract::Font {
/// Cheap magic test: a recognised SFNT version tag at the head of @p data.
[[nodiscard]] static bool is_sfnt(std::string_view data);

/// Reads @p stream fully into an in-memory buffer and parses the facts from
/// it; the bytes are retained for pass-through (see `write()`).
explicit SfntFont(std::unique_ptr<std::istream> stream);
/// Parses the facts from an in-memory SFNT blob (retained for `write()`).
explicit SfntFont(std::string data);

Expand All @@ -55,11 +50,10 @@ class SfntFont final : public abstract::Font {
/// font (see `sfnt_transform.hpp`'s `reencode_to_pua`), then `write()`.
void set_cmap(std::map<char32_t, std::uint16_t> cmap);

/// Serialize the current state to @p out: the (possibly mutated) `cmap`
/// rebuilt from `cmap()`, every other table copied verbatim from the source
/// stream, with a freshly computed table directory and checksums. @p out need
/// only be a forward sink (see `build_sfnt`).
void write(std::ostream &out) const;
/// Serialize the current state and return the bytes: the (possibly mutated)
/// `cmap` rebuilt from `cmap()`, every other table copied verbatim from the
/// source stream, with a freshly computed table directory and checksums.
[[nodiscard]] std::string write() const;

private:
/// Parse the facts from `m_data` (called by both constructors).
Expand Down
15 changes: 9 additions & 6 deletions src/odr/internal/font/sfnt_transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <bit>
#include <cstdint>
#include <map>
#include <ostream>
#include <ranges>
#include <stdexcept>
#include <utility>
Expand Down Expand Up @@ -71,8 +70,9 @@ char32_t font::pua_code_point(const std::uint16_t glyph) noexcept {
return pua_base + glyph;
}

void font::build_sfnt(std::ostream &out, const std::uint32_t sfnt_version,
std::vector<std::pair<std::string, std::string>> tables) {
std::string
font::build_sfnt(const std::uint32_t sfnt_version,
std::vector<std::pair<std::string, std::string>> tables) {
std::ranges::sort(
tables, {}, [](const auto &e) -> const std::string & { return e.first; });

Expand Down Expand Up @@ -127,11 +127,14 @@ void font::build_sfnt(std::ostream &out, const std::uint32_t sfnt_version,
bs::write_u32_be(tables[head_index].second, 8, 0xb1b0afbaU - file_checksum);
}

out.write(header.data(), static_cast<std::streamsize>(header.size()));
out.write(directory.data(), static_cast<std::streamsize>(directory.size()));
std::string out;
out.reserve(offset); // `offset` has accumulated to the whole-file size
out.append(header);
out.append(directory);
for (const auto &data : tables | std::views::values) {
out.write(data.data(), static_cast<std::streamsize>(data.size()));
out.append(data);
}
return out;
}

std::string font::serialize_cmap(const std::map<char32_t, std::uint16_t> &map) {
Expand Down
17 changes: 9 additions & 8 deletions src/odr/internal/font/sfnt_transform.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <cstdint>
#include <iosfwd>
#include <map>
#include <string>
#include <utility>
Expand All @@ -20,16 +19,18 @@ class SfntFont;
/// per-font table needed.
[[nodiscard]] char32_t pua_code_point(std::uint16_t glyph) noexcept;

/// Serialize an SFNT from its tables to @p out, computing the table directory,
/// per-table checksums and `head.checkSumAdjustment`. @p tables need not be
/// sorted; a `head` table is patched in place with the final adjustment.
/// Serialize an SFNT from its tables, computing the table directory, per-table
/// checksums and `head.checkSumAdjustment`, and return the assembled bytes.
/// @p tables need not be sorted; a `head` table is patched in place with the
/// final adjustment.
///
/// The whole-file checksum is additive over the 4-byte-aligned table layout, so
/// it equals `checksum(header+directory) + Σ checksum(table)` — computed
/// analytically and the adjustment patched into `head` before the single
/// forward write, so @p out need only be a forward sink (no seek, no tee).
void build_sfnt(std::ostream &out, std::uint32_t sfnt_version,
std::vector<std::pair<std::string, std::string>> tables);
/// analytically and the adjustment patched into `head` before the bytes are
/// concatenated.
[[nodiscard]] std::string
build_sfnt(std::uint32_t sfnt_version,
std::vector<std::pair<std::string, std::string>> tables);

/// Serialize a code point -> glyph map into a `cmap` table.
///
Expand Down
10 changes: 5 additions & 5 deletions src/odr/internal/html/font_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
#include <odr/internal/html/common.hpp>
#include <odr/internal/html/html_service.hpp>
#include <odr/internal/html/html_writer.hpp>
#include <odr/internal/util/stream_util.hpp>

#include <algorithm>
#include <istream>
#include <memory>
#include <sstream>
#include <string>

namespace odr::internal::html {
Expand Down Expand Up @@ -95,11 +96,10 @@ class HtmlServiceImpl final : public HtmlService {
// Re-encode a fresh parse: reencode_to_pua mutates the cmap in place, and
// the grid below still reads each glyph's original Unicode from
// `font`.
font::sfnt::SfntFont embed(m_font_file.impl()->file()->stream());
font::sfnt::SfntFont embed(
util::stream::read(*m_font_file.impl()->file()->stream()));
font::reencode_to_pua(embed);
std::ostringstream sfnt_out;
embed.write(sfnt_out);
reencoded = sfnt_out.str();
reencoded = embed.write();
} catch (...) {
out.out() << "<p>font has too many glyphs to display</p>";
out.write_body_end();
Expand Down
7 changes: 2 additions & 5 deletions src/odr/internal/html/pdf_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,7 @@ class HtmlServiceImpl final : public HtmlService {
std::map<char32_t, std::uint16_t> original_cmap = sfnt->cmap();
try {
font::reencode_to_pua(*sfnt);
std::ostringstream sfnt_out;
sfnt->write(sfnt_out);
(void)sfnt->write();
usable = true;
} catch (...) {
usable = false;
Expand Down Expand Up @@ -1083,9 +1082,7 @@ class HtmlServiceImpl final : public HtmlService {
if (auto sfnt = std::dynamic_pointer_cast<font::sfnt::SfntFont>(
font->embedded_font)) {
font::reencode_to_pua(*sfnt, extra);
std::ostringstream sfnt_out;
sfnt->write(sfnt_out);
reencoded = std::move(sfnt_out).str();
reencoded = sfnt->write();
} else if (auto cff = std::dynamic_pointer_cast<font::cff::CffFont>(
font->embedded_font)) {
reencoded = font::cff::wrap_to_otf(*cff, extra);
Expand Down
6 changes: 2 additions & 4 deletions test/src/internal/font/cff_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
#include <gtest/gtest.h>

#include <cstdint>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

Expand Down Expand Up @@ -432,7 +430,7 @@ TEST(CffFontTest, WrapsToLoadableOtf) {
// The wrap is a valid OTTO that parses back as an SFNT carrying the CFF as a
// pass-through table and a uniform PUA cmap over every glyph.
ASSERT_TRUE(sfnt::SfntFont::is_sfnt(otf));
const sfnt::SfntFont wrapped{std::make_unique<std::istringstream>(otf)};
const sfnt::SfntFont wrapped{otf};
EXPECT_EQ(wrapped.format(), FontFormat::opentype_cff);
EXPECT_EQ(wrapped.glyph_count(), cff.glyph_count());
// PUA code point U+E000+glyph maps back to that glyph.
Expand All @@ -451,7 +449,7 @@ TEST(CffFontTest, WrapDropsExtraEntriesPastGlyphCount) {
const std::string otf = cff::wrap_to_otf(cff, {{U'A', 1}, {U'B', 5}});

ASSERT_TRUE(sfnt::SfntFont::is_sfnt(otf));
const sfnt::SfntFont wrapped{std::make_unique<std::istringstream>(otf)};
const sfnt::SfntFont wrapped{otf};
EXPECT_EQ(wrapped.glyph_for_code_point('A'), 1);
EXPECT_EQ(wrapped.glyph_for_code_point('B'), 0); // dropped: not mapped
EXPECT_EQ(wrapped.glyph_for_code_point(pua_code_point(1)), 1);
Expand Down
4 changes: 1 addition & 3 deletions test/src/internal/font/font_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,7 @@ std::string name_table(const std::string &ascii) {
std::string
build_sfnt_bytes(std::uint32_t version,
std::vector<std::pair<std::string, std::string>> tables) {
std::ostringstream out;
build_sfnt(out, version, std::move(tables));
return out.str();
return build_sfnt(version, std::move(tables));
}

std::string sample_ttf() {
Expand Down
Loading
Loading