Reduce storage by sharing face amongst lazy_loaders
This commit is contained in:
parent
bdd3c11a19
commit
ff7826e90b
@ -590,93 +590,106 @@ struct BEInt<Type, 4>
|
|||||||
* Lazy struct and blob loaders.
|
* Lazy struct and blob loaders.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename Subclass,
|
template <unsigned int WheresFace,
|
||||||
|
typename Subclass,
|
||||||
typename Returned,
|
typename Returned,
|
||||||
typename Stored = Returned>
|
typename Stored = Returned>
|
||||||
struct hb_base_lazy_loader_t
|
struct hb_base_lazy_loader_t
|
||||||
{
|
{
|
||||||
|
static_assert (WheresFace > 0, "");
|
||||||
|
|
||||||
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
||||||
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
|
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
|
||||||
|
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
|
||||||
|
|
||||||
inline void init (hb_face_t *face_)
|
inline void init (void)
|
||||||
{
|
{
|
||||||
face = face_;
|
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
}
|
}
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
if (instance)
|
||||||
|
thiz ()->destroy (instance);
|
||||||
|
}
|
||||||
|
|
||||||
inline const Returned * operator-> (void) const
|
inline const Returned * operator-> (void) const
|
||||||
{
|
{
|
||||||
return thiz ()->get ();
|
return thiz ()->get ();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
inline Stored * get_stored (void) const
|
||||||
hb_face_t *face;
|
|
||||||
mutable Stored *instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct hb_lazy_loader_t : hb_base_lazy_loader_t<hb_lazy_loader_t<T>, T>
|
|
||||||
{
|
|
||||||
inline void fini (void)
|
|
||||||
{
|
|
||||||
if (this->instance && this->instance != &Null(T))
|
|
||||||
{
|
|
||||||
this->instance->fini();
|
|
||||||
free (this->instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T* get (void) const
|
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
T *p = (T *) hb_atomic_ptr_get (&this->instance);
|
Stored *p = (Stored *) hb_atomic_ptr_get (&this->instance);
|
||||||
if (unlikely (!p))
|
if (unlikely (!p))
|
||||||
{
|
{
|
||||||
p = (T *) calloc (1, sizeof (T));
|
hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
|
||||||
if (unlikely (!p))
|
p = thiz ()->create (face);
|
||||||
p = const_cast<T *> (&Null(T));
|
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
|
||||||
else
|
|
||||||
p->init (this->face);
|
|
||||||
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&this->instance), nullptr, p)))
|
|
||||||
{
|
{
|
||||||
if (p != &Null(T))
|
thiz ()->destroy (p);
|
||||||
p->fini ();
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const Returned * get (void) const
|
||||||
|
{
|
||||||
|
return thiz ()->convert (get_stored ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const Returned* convert (const Stored *p)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Must only have one pointer. */
|
||||||
|
mutable Stored *instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <unsigned int WheresFace, typename T>
|
||||||
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<hb_table_lazy_loader_t<T>, T, hb_blob_t>
|
struct hb_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_lazy_loader_t<WheresFace, T>, T>
|
||||||
{
|
{
|
||||||
inline void fini (void)
|
static inline T *create (hb_face_t *face)
|
||||||
{
|
{
|
||||||
hb_blob_destroy (this->instance);
|
T *p = (T *) calloc (1, sizeof (T));
|
||||||
|
if (unlikely (!p))
|
||||||
|
p = const_cast<T *> (&Null(T));
|
||||||
|
else
|
||||||
|
p->init (face);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static inline void destroy (T *p)
|
||||||
|
{
|
||||||
|
if (p != &Null(T))
|
||||||
|
{
|
||||||
|
p->fini();
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned int WheresFace, typename T>
|
||||||
|
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
|
||||||
|
{
|
||||||
|
static inline hb_blob_t *create (hb_face_t *face)
|
||||||
|
{
|
||||||
|
return hb_sanitize_context_t ().reference_table<T> (face);
|
||||||
|
}
|
||||||
|
static inline void destroy (hb_blob_t *p)
|
||||||
|
{
|
||||||
|
hb_blob_destroy (p);
|
||||||
|
}
|
||||||
|
static inline const T* convert (const hb_blob_t *blob)
|
||||||
|
{
|
||||||
|
return blob->as<T> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline hb_blob_t* get_blob (void) const
|
inline hb_blob_t* get_blob (void) const
|
||||||
{
|
{
|
||||||
retry:
|
return this->get_stored ();
|
||||||
hb_blob_t *b = (hb_blob_t *) hb_atomic_ptr_get (&this->instance);
|
|
||||||
if (unlikely (!b))
|
|
||||||
{
|
|
||||||
b = hb_sanitize_context_t ().reference_table<T> (this->face);
|
|
||||||
if (!hb_atomic_ptr_cmpexch (&this->instance, nullptr, b))
|
|
||||||
{
|
|
||||||
hb_blob_destroy (b);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
this->instance = b;
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T* get (void) const
|
|
||||||
{
|
|
||||||
hb_blob_t *b = get_blob ();
|
|
||||||
return b->as<T> ();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,10 +44,12 @@ struct hb_ot_font_t
|
|||||||
OT::cmap::accelerator_t cmap;
|
OT::cmap::accelerator_t cmap;
|
||||||
OT::hmtx::accelerator_t h_metrics;
|
OT::hmtx::accelerator_t h_metrics;
|
||||||
OT::vmtx::accelerator_t v_metrics;
|
OT::vmtx::accelerator_t v_metrics;
|
||||||
hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
|
|
||||||
hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
|
hb_face_t *face; /* MUST be before the lazy loaders. */
|
||||||
hb_lazy_loader_t<OT::post::accelerator_t> post;
|
hb_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
|
||||||
hb_lazy_loader_t<OT::kern::accelerator_t> kern;
|
hb_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
|
||||||
|
hb_lazy_loader_t<3, OT::post::accelerator_t> post;
|
||||||
|
hb_lazy_loader_t<4, OT::kern::accelerator_t> kern;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -62,10 +64,11 @@ _hb_ot_font_create (hb_face_t *face)
|
|||||||
ot_font->cmap.init (face);
|
ot_font->cmap.init (face);
|
||||||
ot_font->h_metrics.init (face);
|
ot_font->h_metrics.init (face);
|
||||||
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
|
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
|
||||||
ot_font->glyf.init (face);
|
ot_font->face = face;
|
||||||
ot_font->cbdt.init (face);
|
ot_font->glyf.init ();
|
||||||
ot_font->post.init (face);
|
ot_font->cbdt.init ();
|
||||||
ot_font->kern.init (face);
|
ot_font->post.init ();
|
||||||
|
ot_font->kern.init ();
|
||||||
|
|
||||||
return ot_font;
|
return ot_font;
|
||||||
}
|
}
|
||||||
|
@ -172,11 +172,12 @@ struct hb_ot_layout_t
|
|||||||
const struct OT::GPOS *gpos;
|
const struct OT::GPOS *gpos;
|
||||||
|
|
||||||
/* TODO Move the following out of this struct. */
|
/* TODO Move the following out of this struct. */
|
||||||
hb_table_lazy_loader_t<struct OT::BASE> base;
|
hb_face_t *face; /* MUST be before the lazy loaders. */
|
||||||
hb_table_lazy_loader_t<struct OT::MATH> math;
|
hb_table_lazy_loader_t<1, struct OT::BASE> base;
|
||||||
hb_table_lazy_loader_t<struct OT::fvar> fvar;
|
hb_table_lazy_loader_t<2, struct OT::MATH> math;
|
||||||
hb_table_lazy_loader_t<struct OT::avar> avar;
|
hb_table_lazy_loader_t<3, struct OT::fvar> fvar;
|
||||||
hb_table_lazy_loader_t<struct AAT::morx> morx;
|
hb_table_lazy_loader_t<4, struct OT::avar> avar;
|
||||||
|
hb_table_lazy_loader_t<5, struct AAT::morx> morx;
|
||||||
|
|
||||||
unsigned int gsub_lookup_count;
|
unsigned int gsub_lookup_count;
|
||||||
unsigned int gpos_lookup_count;
|
unsigned int gpos_lookup_count;
|
||||||
|
@ -63,10 +63,11 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||||||
layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
|
layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
|
||||||
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
|
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
|
||||||
|
|
||||||
layout->math.init (face);
|
layout->face = face;
|
||||||
layout->fvar.init (face);
|
layout->math.init ();
|
||||||
layout->avar.init (face);
|
layout->fvar.init ();
|
||||||
layout->morx.init (face);
|
layout->avar.init ();
|
||||||
|
layout->morx.init ();
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user