Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible performance improvements #238

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
41 changes: 41 additions & 0 deletions src/SVGTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <algorithm>
#include <array>
#include <cstring>
#include <iostream>
#include <sstream>
#include "BoundingBox.hpp"
#include "DVIToSVG.hpp"
Expand Down Expand Up @@ -158,13 +159,45 @@ void SVGTree::transformPage (const Matrix &usermatrix) {
_page->setTransform(usermatrix);
}

class GlyphNodeParams {
public:
const int c;
const PhysicalFont *font;
GFGlyphTracer::Callback *cb;
bool USE_FONTS;
};

bool operator==(const GlyphNodeParams &a, const GlyphNodeParams &b) {
return a.c == b.c && a.font == b.font && a.cb == b.cb && a.USE_FONTS == b.USE_FONTS;
}
template <>
struct std::hash<GlyphNodeParams> {
std::size_t operator()(GlyphNodeParams const &p) const noexcept {
// based on https://en.cppreference.com/w/cpp/utility/hash#Example
// I don't *really* know what I'm doing
return std::hash<int>{}(p.c) ^
(std::hash<const void *>{}(p.font) << 1) ^
(std::hash<void *>{}(p.cb) << 2) ^
(std::hash<bool>{}(p.USE_FONTS) << 3);
}
};

std::unordered_map<GlyphNodeParams, unique_ptr<XMLElement>> glyphNodeCache = {};

/** Creates an SVG element for a single glyph.
* @param[in] c character number
* @param[in] font font to extract the glyph from
* @param[in] cb pointer to callback object for sending feedback to the glyph tracer (may be 0)
* @return pointer to element node if glyph exists, 0 otherwise */
static unique_ptr<XMLElement> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) {

GlyphNodeParams params = {c, &font, cb, SVGTree::USE_FONTS};
if (glyphNodeCache.count(params) > 0) {
std::cout << "cached!" << std::endl;
return util::static_unique_ptr_cast<XMLElement>(glyphNodeCache[params]->clone());

}

Glyph glyph;
if (!font.getGlyph(c, glyph, cb) || (!SVGTree::USE_FONTS && !SVGTree::CREATE_USE_ELEMENTS))
return nullptr;
Expand All @@ -191,6 +224,14 @@ static unique_ptr<XMLElement> createGlyphNode (int c, const PhysicalFont &font,
ostringstream oss;
glyph.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS, sx, sy);
glyphNode->addAttribute("d", oss.str());

// TODO this cache strategy is crude but better than nothing
if (glyphNodeCache.size() > 1<<14) {
glyphNodeCache.clear();
}
glyphNodeCache[params] = util::static_unique_ptr_cast<XMLElement>(glyphNode->clone());
std::cout << "size of cache: " << glyphNodeCache.size() << std::endl;

return glyphNode;
}

Expand Down