diff --git a/src/loaders/ttf/tvgTtfLoader.cpp b/src/loaders/ttf/tvgTtfLoader.cpp index 65b0f5ca..01d69a0b 100644 --- a/src/loaders/ttf/tvgTtfLoader.cpp +++ b/src/loaders/ttf/tvgTtfLoader.cpp @@ -221,17 +221,16 @@ void TtfLoader::clear() /************************************************************************/ -bool TtfLoader::transform(Paint* paint, float fontSize, bool italic) +float TtfLoader::transform(Paint* paint, FontMetrics& metrics, float fontSize, bool italic) { - if (!paint) return false; auto shift = 0.0f; auto dpi = 96.0f / 72.0f; //dpi base? - scale = fontSize * dpi / reader.metrics.unitsPerEm; + auto scale = fontSize * dpi / reader.metrics.unitsPerEm; if (italic) shift = -scale * 0.18f; //experimental decision. - Matrix m = {scale, shift, -(shift * reader.metrics.minw), 0, scale, 0, 0, 0, 1}; + Matrix m = {scale, shift, -(shift * metrics.minw), 0, scale, 0, 0, 0, 1}; paint->transform(m); - return true; + return scale; } @@ -277,21 +276,11 @@ bool TtfLoader::open(const char* data, uint32_t size, TVG_UNUSED const char* rpa } -bool TtfLoader::request(Shape* shape, char* text) -{ - this->shape = shape; - this->text = text; - - return true; -} - - -bool TtfLoader::read() +bool TtfLoader::read(Shape* shape, char* text, FontMetrics& out) { if (!text) return false; shape->reset(); - shape->fill(FillRule::EvenOdd); auto n = strlen(text); auto code = _codepoints(text, n); @@ -313,7 +302,7 @@ bool TtfLoader::read() lglyph = rglyph; //store the first glyph with outline min size for italic transform. if (loadMinw && gmetrics.outline) { - reader.metrics.minw = gmetrics.minw; + out.minw = gmetrics.minw; loadMinw = false; } } diff --git a/src/loaders/ttf/tvgTtfLoader.h b/src/loaders/ttf/tvgTtfLoader.h index f7dd3633..a84219c8 100644 --- a/src/loaders/ttf/tvgTtfLoader.h +++ b/src/loaders/ttf/tvgTtfLoader.h @@ -43,11 +43,12 @@ struct TtfLoader : public FontLoader ~TtfLoader(); using FontLoader::open; + using FontLoader::read; + bool open(const char* path) override; bool open(const char *data, uint32_t size, const char* rpath, bool copy) override; - bool transform(Paint* paint, float fontSize, bool italic) override; - bool request(Shape* shape, char* text) override; - bool read() override; + float transform(Paint* paint, FontMetrics& metrices, float fontSize, bool italic) override; + bool read(Shape* shape, char* text, FontMetrics& out) override; void clear(); }; diff --git a/src/loaders/ttf/tvgTtfReader.cpp b/src/loaders/ttf/tvgTtfReader.cpp index 0a91e028..97c43150 100644 --- a/src/loaders/ttf/tvgTtfReader.cpp +++ b/src/loaders/ttf/tvgTtfReader.cpp @@ -63,12 +63,10 @@ static int _cmpu32(const void *a, const void *b) bool TtfReader::validate(uint32_t offset, uint32_t margin) const { -#if 1 if ((offset > size) || (size - offset < margin)) { TVGERR("TTF", "Invalidate data"); return false; } -#endif return true; } @@ -195,8 +193,11 @@ uint32_t TtfReader::outlineOffset(uint32_t glyph) { uint32_t cur, next; - if (!loca) loca = table("loca"); - if (!glyf) glyf = table("glyf"); + auto loca = this->loca.load(); + if (loca == 0) this->loca = loca = table("loca"); + + auto glyf = this->glyf.load(); + if (glyf == 0) this->glyf = glyf = table("glyf"); if (metrics.locaFormat == 0) { auto base = loca + 2 * glyph; @@ -318,8 +319,8 @@ bool TtfReader::header() metrics.numHmtx = _u16(data, hhea + 34); //kerning - this->kern = table("kern"); - if (this->kern) { + auto kern = this->kern = table("kern"); + if (kern) { if (!validate(kern, 4)) return false; if (_u16(data, kern) != 0) return false; } @@ -330,8 +331,9 @@ bool TtfReader::header() uint32_t TtfReader::glyph(uint32_t codepoint) { + auto cmap = this->cmap.load(); if (cmap == 0) { - cmap = table("cmap"); + this->cmap = cmap = table("cmap"); if (!validate(cmap, 4)) return -1; } @@ -388,7 +390,8 @@ uint32_t TtfReader::glyph(uint32_t codepoint, TtfGlyphMetrics& gmetrics) bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics) { //horizontal metrics - if (!hmtx) hmtx = table("hmtx"); + auto hmtx = this->hmtx.load(); + if (hmtx == 0) this->hmtx = hmtx = table("hmtx"); //glyph is inside long metrics segment. if (glyphIndex < metrics.numHmtx) { @@ -442,7 +445,8 @@ bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& of if (outlineCnt == 0) return false; if (outlineCnt < 0) { uint16_t maxComponentDepth = 1U; - if (!maxp) maxp = table("maxp"); + auto maxp = this->maxp.load(); + if (maxp == 0) this->maxp = maxp = table("maxp"); if (validate(maxp, 32) && _u32(data, maxp) >= 0x00010000U) { // >= version 1.0 maxComponentDepth = _u16(data, maxp + 30); } @@ -598,7 +602,7 @@ void TtfReader::kerning(uint32_t lglyph, uint32_t rglyph, Point& out) if (!kern) return; - auto kern = this->kern; + auto kern = this->kern.load(); out.x = out.y = 0.0f; diff --git a/src/loaders/ttf/tvgTtfReader.h b/src/loaders/ttf/tvgTtfReader.h index b1f9a532..0ec7e8d4 100644 --- a/src/loaders/ttf/tvgTtfReader.h +++ b/src/loaders/ttf/tvgTtfReader.h @@ -23,6 +23,7 @@ #ifndef _TVG_TTF_READER_H #define _TVG_TTF_READER_H +#include #include "tvgCommon.h" #include "tvgArray.h" @@ -55,7 +56,6 @@ public: float lineGap; } hhea; - float minw; //first glyph width (used for italic) uint16_t unitsPerEm; uint16_t numHmtx; //the number of Horizontal metrics table uint8_t locaFormat; //0 for short offsets, 1 for long @@ -68,12 +68,12 @@ public: private: //table offsets - uint32_t cmap = 0; - uint32_t hmtx = 0; - uint32_t loca = 0; - uint32_t glyf = 0; - uint32_t kern = 0; - uint32_t maxp = 0; + atomic cmap{}; + atomic hmtx{}; + atomic loca{}; + atomic glyf{}; + atomic kern{}; + atomic maxp{}; uint32_t cmap_12_13(uint32_t table, uint32_t codepoint, int which) const; uint32_t cmap_4(uint32_t table, uint32_t codepoint) const; diff --git a/src/renderer/tvgLoadModule.h b/src/renderer/tvgLoadModule.h index 4e9bf007..fef8e2c7 100644 --- a/src/renderer/tvgLoadModule.h +++ b/src/renderer/tvgLoadModule.h @@ -23,6 +23,7 @@ #ifndef _TVG_LOAD_MODULE_H_ #define _TVG_LOAD_MODULE_H_ +#include #include "tvgCommon.h" #include "tvgRender.h" #include "tvgInlist.h" @@ -37,7 +38,7 @@ struct LoadModule char* hashpath = nullptr; FileType type; //current loader file type - uint16_t sharing = 0; //reference count + atomic sharing{}; //reference count bool readied = false; //read done already. bool cached = false; //cached for sharing @@ -82,7 +83,7 @@ struct LoadModule struct ImageLoader : LoadModule { - static ColorSpace cs; //desired value + static atomic cs; //desired value float w = 0, h = 0; //default image size RenderSurface surface; @@ -100,15 +101,23 @@ struct ImageLoader : LoadModule }; +struct FontMetrics +{ + //TODO: add necessary metrics + float minw; +}; + + struct FontLoader : LoadModule { - float scale = 1.0f; char* name = nullptr; FontLoader(FileType type) : LoadModule(type) {} - virtual bool request(Shape* shape, char* text) = 0; - virtual bool transform(Paint* paint, float fontSize, bool italic) = 0; + using LoadModule::read; + + virtual bool read(Shape* shape, char* text, FontMetrics& out) = 0; + virtual float transform(Paint* paint, FontMetrics& mertrics, float fontSize, bool italic) = 0; }; #endif //_TVG_LOAD_MODULE_H_ diff --git a/src/renderer/tvgLoader.cpp b/src/renderer/tvgLoader.cpp index 43f3e1d6..0e326383 100644 --- a/src/renderer/tvgLoader.cpp +++ b/src/renderer/tvgLoader.cpp @@ -20,6 +20,7 @@ * SOFTWARE. */ +#include #include "tvgInlist.h" #include "tvgStr.h" #include "tvgLoader.h" @@ -61,7 +62,8 @@ uintptr_t HASH_KEY(const char* data) /* Internal Class Implementation */ /************************************************************************/ -ColorSpace ImageLoader::cs = ColorSpace::ARGB8888; +//TODO: remove it. +atomic ImageLoader::cs{ColorSpace::ARGB8888}; static Key _key; static Inlist _activeLoaders; diff --git a/src/renderer/tvgText.h b/src/renderer/tvgText.h index 2c62c244..32b58077 100644 --- a/src/renderer/tvgText.h +++ b/src/renderer/tvgText.h @@ -24,6 +24,7 @@ #define _TVG_TEXT_H #include "tvgStr.h" +#include "tvgMath.h" #include "tvgShape.h" #include "tvgFill.h" #include "tvgLoader.h" @@ -34,6 +35,7 @@ struct Text::Impl : Paint::Impl { Shape* shape; //text shape FontLoader* loader = nullptr; + FontMetrics metrics; char* utf8 = nullptr; float fontSize; bool italic = false; @@ -42,6 +44,7 @@ struct Text::Impl : Paint::Impl Impl(Text* p) : Paint::Impl(p), shape(Shape::gen()) { PAINT(shape)->parent = p; + shape->fill(FillRule::EvenOdd); } ~Impl() @@ -96,27 +99,26 @@ struct Text::Impl : Paint::Impl return PAINT(shape)->render(renderer); } - bool load() + float load() { - if (!loader) return false; + if (!loader) return 0.0f; - loader->request(shape, utf8); //reload if (changed) { - loader->read(); + loader->read(shape, utf8, metrics); changed = false; } - return loader->transform(shape, fontSize, italic); + return loader->transform(shape, metrics, fontSize, italic); } RenderData update(RenderMethod* renderer, const Matrix& transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper) { - if (!load()) return nullptr; + auto scale = 1.0f / load(); + if (tvg::zero(scale)) return nullptr; //transform the gradient coordinates based on the final scaled font. auto fill = SHAPE(shape)->rs.fill; if (fill && SHAPE(shape)->renderFlag & RenderUpdateFlag::Gradient) { - auto scale = 1.0f / loader->scale; if (fill->type() == Type::LinearGradient) { LINEAR(fill)->x1 *= scale; LINEAR(fill)->y1 *= scale; @@ -137,7 +139,7 @@ struct Text::Impl : Paint::Impl Result bounds(Point* pt4, Matrix& m, bool obb, TVG_UNUSED bool stroking) { - if (!load()) return Result::InsufficientCondition; + if (load() == 0.0f) return Result::InsufficientCondition; return PAINT(shape)->bounds(pt4, &m, obb, true); }