mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
Merge c92ddd6cc2
into 0fa5d41c8d
This commit is contained in:
commit
f42688e751
8 changed files with 176 additions and 38 deletions
36
inc/thorvg.h
36
inc/thorvg.h
|
@ -284,6 +284,25 @@ struct Matrix
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A data structure representing metrics for a single glyph.
|
||||||
|
*
|
||||||
|
* @since Experimental API
|
||||||
|
*/
|
||||||
|
struct GlyphMetrics
|
||||||
|
{
|
||||||
|
Point kerning = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
float advanceWidth;
|
||||||
|
float leftSideBearing;
|
||||||
|
float yOffset;
|
||||||
|
float minw;
|
||||||
|
float minh;
|
||||||
|
//for glyph<->text mapping:
|
||||||
|
uint32_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Paint
|
* @class Paint
|
||||||
*
|
*
|
||||||
|
@ -1682,6 +1701,23 @@ public:
|
||||||
*/
|
*/
|
||||||
static Result unload(const char* filename) noexcept;
|
static Result unload(const char* filename) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the detailed metrics for each glyph in the current text object.
|
||||||
|
*
|
||||||
|
* This function allocates memory internally to hold an array of glyph metrics corresponding to the currently set text and font.
|
||||||
|
*
|
||||||
|
* @param[out] metrics Pointer to an array of glyph metrics. Valid until the text is modified.
|
||||||
|
* @param[out] size The number of glyphs returned in the metrics array.
|
||||||
|
*
|
||||||
|
* @retval Result::InsufficientCondition If font or text was not set, a @c nullptr is passed as @p metrics, or font data loading/reading failed.
|
||||||
|
*
|
||||||
|
* @note The caller is responsible for freeing the allocated memory by calling this function again with the same @p metrics pointer and a @c nullptr @p size pointer.
|
||||||
|
* @note Must be called after setting both font() and text().
|
||||||
|
*
|
||||||
|
* @since Experimental API
|
||||||
|
*/
|
||||||
|
Result metrics(GlyphMetrics** metrics, uint32_t* size) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new Text object.
|
* @brief Creates a new Text object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "tvgStr.h"
|
#include "tvgStr.h"
|
||||||
#include "tvgTtfLoader.h"
|
#include "tvgTtfLoader.h"
|
||||||
|
|
||||||
|
#define PX_PER_PT 1.333333f //1 pt = 1/72 in; 1 in = 96 px; -> 96/72
|
||||||
|
|
||||||
#if defined(_WIN32) && (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
|
#if defined(_WIN32) && (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
@ -196,6 +198,47 @@ static uint32_t* _codepoints(const char* text, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t* _codepointsLength(const char* text, size_t n) {
|
||||||
|
auto length = tvg::malloc<uint32_t*>(sizeof(uint32_t) * (n + 1));
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
auto p = text;
|
||||||
|
while(*p) {
|
||||||
|
if (!(*p & 0x80U)) {
|
||||||
|
length[i++] = 1;
|
||||||
|
++p;
|
||||||
|
} else if ((*p & 0xe0U) == 0xc0U) {
|
||||||
|
length[i++] = 2;
|
||||||
|
p += 2;
|
||||||
|
} else if ((*p & 0xf0U) == 0xe0U) {
|
||||||
|
length[i++] = 3;
|
||||||
|
p += 3;
|
||||||
|
} else if ((*p & 0xf8U) == 0xf0U) {
|
||||||
|
length[i++] = 4;
|
||||||
|
p += 4;
|
||||||
|
} else {
|
||||||
|
tvg::free(length);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
length[i] = 0;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _scale(GlyphMetrics& gmetric, float scale)
|
||||||
|
{
|
||||||
|
gmetric.kerning.x *= scale;
|
||||||
|
gmetric.kerning.y *= scale;
|
||||||
|
gmetric.advanceWidth *= scale;
|
||||||
|
gmetric.leftSideBearing *= scale;
|
||||||
|
gmetric.yOffset *= scale;
|
||||||
|
gmetric.minw *= scale;
|
||||||
|
gmetric.minh *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TtfLoader::clear()
|
void TtfLoader::clear()
|
||||||
{
|
{
|
||||||
if (nomap) {
|
if (nomap) {
|
||||||
|
@ -224,8 +267,7 @@ void TtfLoader::clear()
|
||||||
float TtfLoader::transform(Paint* paint, FontMetrics& metrics, float fontSize, bool italic)
|
float TtfLoader::transform(Paint* paint, FontMetrics& metrics, float fontSize, bool italic)
|
||||||
{
|
{
|
||||||
auto shift = 0.0f;
|
auto shift = 0.0f;
|
||||||
auto dpi = 96.0f / 72.0f; //dpi base?
|
auto scale = fontSize * PX_PER_PT / reader.metrics.unitsPerEm;
|
||||||
auto scale = fontSize * dpi / reader.metrics.unitsPerEm;
|
|
||||||
if (italic) shift = -scale * 0.18f; //experimental decision.
|
if (italic) shift = -scale * 0.18f; //experimental decision.
|
||||||
Matrix m = {scale, shift, -(shift * metrics.minw), 0, scale, 0, 0, 0, 1};
|
Matrix m = {scale, shift, -(shift * metrics.minw), 0, scale, 0, 0, 0, 1};
|
||||||
paint->transform(m);
|
paint->transform(m);
|
||||||
|
@ -289,21 +331,20 @@ bool TtfLoader::read(Shape* shape, char* text, FontMetrics& out)
|
||||||
//TODO: optimize with the texture-atlas?
|
//TODO: optimize with the texture-atlas?
|
||||||
TtfGlyphMetrics gmetrics;
|
TtfGlyphMetrics gmetrics;
|
||||||
Point offset = {0.0f, reader.metrics.hhea.ascent};
|
Point offset = {0.0f, reader.metrics.hhea.ascent};
|
||||||
Point kerning = {0.0f, 0.0f};
|
|
||||||
auto lglyph = INVALID_GLYPH;
|
auto lglyph = INVALID_GLYPH;
|
||||||
auto loadMinw = true;
|
auto loadMinw = true;
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
while (code[idx] && idx < n) {
|
while (code[idx] && idx < n) {
|
||||||
auto rglyph = reader.glyph(code[idx], gmetrics);
|
auto rglyph = reader.glyph(code[idx], gmetrics.metrics, &gmetrics.outline);
|
||||||
if (rglyph != INVALID_GLYPH) {
|
if (rglyph != INVALID_GLYPH) {
|
||||||
if (lglyph != INVALID_GLYPH) reader.kerning(lglyph, rglyph, kerning);
|
if (lglyph != INVALID_GLYPH) reader.kerning(lglyph, rglyph, gmetrics.metrics.kerning);
|
||||||
if (!reader.convert(shape, gmetrics, offset, kerning, 1U)) break;
|
if (!reader.convert(shape, gmetrics, offset, 1U)) break;
|
||||||
offset.x += (gmetrics.advanceWidth + kerning.x);
|
offset.x += (gmetrics.metrics.advanceWidth + gmetrics.metrics.kerning.x);
|
||||||
lglyph = rglyph;
|
lglyph = rglyph;
|
||||||
//store the first glyph with outline min size for italic transform.
|
//store the first glyph with outline min size for italic transform.
|
||||||
if (loadMinw && gmetrics.outline) {
|
if (loadMinw && gmetrics.outline) {
|
||||||
out.minw = gmetrics.minw;
|
out.minw = gmetrics.metrics.minw;
|
||||||
loadMinw = false;
|
loadMinw = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,5 +353,42 @@ bool TtfLoader::read(Shape* shape, char* text, FontMetrics& out)
|
||||||
|
|
||||||
tvg::free(code);
|
tvg::free(code);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TtfLoader::metrics(char* text, float fontSize, GlyphMetrics** metrics, uint32_t* size)
|
||||||
|
{
|
||||||
|
auto n = strlen(text);
|
||||||
|
auto code = _codepoints(text, n);
|
||||||
|
if (!code) return false;
|
||||||
|
auto length = _codepointsLength(text, n);
|
||||||
|
if (!length) return false;
|
||||||
|
|
||||||
|
GlyphMetrics gmetrics;
|
||||||
|
auto lglyph = INVALID_GLYPH, rglyph = INVALID_GLYPH;
|
||||||
|
Array<GlyphMetrics> out(n);
|
||||||
|
|
||||||
|
auto scale = fontSize * PX_PER_PT / reader.metrics.unitsPerEm;
|
||||||
|
|
||||||
|
size_t idx = 0;
|
||||||
|
while (code[idx] && idx < n) {
|
||||||
|
if ((rglyph = reader.glyph(code[idx], gmetrics, nullptr)) != INVALID_GLYPH) {
|
||||||
|
if (lglyph != INVALID_GLYPH) reader.kerning(lglyph, rglyph, gmetrics.kerning);
|
||||||
|
_scale(gmetrics, scale);
|
||||||
|
gmetrics.length = length[idx];
|
||||||
|
out.push(gmetrics);
|
||||||
|
lglyph = rglyph;
|
||||||
|
}
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
tvg::free(code);
|
||||||
|
tvg::free(length);
|
||||||
|
|
||||||
|
*metrics = out.data;
|
||||||
|
out.data = nullptr;
|
||||||
|
*size = out.count;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -49,6 +49,7 @@ struct TtfLoader : public FontLoader
|
||||||
bool open(const char *data, uint32_t size, const char* rpath, bool copy) override;
|
bool open(const char *data, uint32_t size, const char* rpath, bool copy) override;
|
||||||
float transform(Paint* paint, FontMetrics& metrices, float fontSize, bool italic) override;
|
float transform(Paint* paint, FontMetrics& metrices, float fontSize, bool italic) override;
|
||||||
bool read(Shape* shape, char* text, FontMetrics& out) override;
|
bool read(Shape* shape, char* text, FontMetrics& out) override;
|
||||||
|
bool metrics(char* text, float fontSize, GlyphMetrics** metrics, uint32_t* size) override;
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -377,17 +377,17 @@ uint32_t TtfReader::glyph(uint32_t codepoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t TtfReader::glyph(uint32_t codepoint, TtfGlyphMetrics& gmetrics)
|
uint32_t TtfReader::glyph(uint32_t codepoint, GlyphMetrics& gmetrics, uint32_t* goutline)
|
||||||
{
|
{
|
||||||
auto glyph = this->glyph(codepoint);
|
auto glyph = this->glyph(codepoint);
|
||||||
if (glyph == INVALID_GLYPH || !glyphMetrics(glyph, gmetrics)) {
|
if (glyph == INVALID_GLYPH || !glyphMetrics(glyph, gmetrics, goutline)) {
|
||||||
TVGERR("TTF", "invalid glyph id, codepoint(0x%x)", codepoint);
|
TVGERR("TTF", "invalid glyph id, codepoint(0x%x)", codepoint);
|
||||||
return INVALID_GLYPH;
|
return INVALID_GLYPH;
|
||||||
}
|
}
|
||||||
return glyph;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics)
|
bool TtfReader::glyphMetrics(uint32_t glyphIndex, GlyphMetrics& gmetrics, uint32_t* goutline)
|
||||||
{
|
{
|
||||||
//horizontal metrics
|
//horizontal metrics
|
||||||
auto hmtx = this->hmtx.load();
|
auto hmtx = this->hmtx.load();
|
||||||
|
@ -412,20 +412,21 @@ bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics)
|
||||||
gmetrics.leftSideBearing = _i16(data, offset);
|
gmetrics.leftSideBearing = _i16(data, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
gmetrics.outline = outlineOffset(glyphIndex);
|
auto outline = outlineOffset(glyphIndex);
|
||||||
|
if (goutline) *goutline = outline;
|
||||||
// glyph without outline
|
// glyph without outline
|
||||||
if (gmetrics.outline == 0) {
|
if (outline == 0) {
|
||||||
gmetrics.minw = gmetrics.minh = gmetrics.yOffset = 0;
|
gmetrics.minw = gmetrics.minh = gmetrics.yOffset = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!validate(gmetrics.outline, 10)) return false;
|
if (!validate(outline, 10)) return false;
|
||||||
|
|
||||||
//read the bounding box from the font file verbatim.
|
//read the bounding box from the font file verbatim.
|
||||||
float bbox[4];
|
float bbox[4];
|
||||||
bbox[0] = static_cast<float>(_i16(data, gmetrics.outline + 2));
|
bbox[0] = static_cast<float>(_i16(data, outline + 2));
|
||||||
bbox[1] = static_cast<float>(_i16(data, gmetrics.outline + 4));
|
bbox[1] = static_cast<float>(_i16(data, outline + 4));
|
||||||
bbox[2] = static_cast<float>(_i16(data, gmetrics.outline + 6));
|
bbox[2] = static_cast<float>(_i16(data, outline + 6));
|
||||||
bbox[3] = static_cast<float>(_i16(data, gmetrics.outline + 8));
|
bbox[3] = static_cast<float>(_i16(data, outline + 8));
|
||||||
|
|
||||||
if (bbox[2] <= bbox[0] || bbox[3] <= bbox[1]) return false;
|
if (bbox[2] <= bbox[0] || bbox[3] <= bbox[1]) return false;
|
||||||
|
|
||||||
|
@ -436,7 +437,7 @@ bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& offset, const Point& kerning, uint16_t componentDepth)
|
bool TtfReader::convert(Shape* shape, const TtfGlyphMetrics& gmetrics, const Point& offset, uint16_t componentDepth)
|
||||||
{
|
{
|
||||||
#define ON_CURVE 0x01
|
#define ON_CURVE 0x01
|
||||||
|
|
||||||
|
@ -451,7 +452,7 @@ bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& of
|
||||||
maxComponentDepth = _u16(data, maxp + 30);
|
maxComponentDepth = _u16(data, maxp + 30);
|
||||||
}
|
}
|
||||||
if (componentDepth > maxComponentDepth) return false;
|
if (componentDepth > maxComponentDepth) return false;
|
||||||
return convertComposite(shape, gmetrics, offset, kerning, componentDepth + 1);
|
return convertComposite(shape, gmetrics, offset, componentDepth + 1);
|
||||||
}
|
}
|
||||||
auto cntrsCnt = (uint32_t) outlineCnt;
|
auto cntrsCnt = (uint32_t) outlineCnt;
|
||||||
|
|
||||||
|
@ -471,7 +472,7 @@ bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& of
|
||||||
if (!this->flags(&outline, flags, ptsCnt)) return false;
|
if (!this->flags(&outline, flags, ptsCnt)) return false;
|
||||||
|
|
||||||
auto pts = (Point*)alloca(ptsCnt * sizeof(Point));
|
auto pts = (Point*)alloca(ptsCnt * sizeof(Point));
|
||||||
if (!this->points(outline, flags, pts, ptsCnt, offset + kerning)) return false;
|
if (!this->points(outline, flags, pts, ptsCnt, offset + gmetrics.metrics.kerning)) return false;
|
||||||
|
|
||||||
//generate tvg paths.
|
//generate tvg paths.
|
||||||
auto& pathCmds = SHAPE(shape)->rs.path.cmds;
|
auto& pathCmds = SHAPE(shape)->rs.path.cmds;
|
||||||
|
@ -526,7 +527,8 @@ bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& of
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TtfReader::convertComposite(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& offset, const Point& kerning, uint16_t componentDepth)
|
|
||||||
|
bool TtfReader::convertComposite(Shape* shape, const TtfGlyphMetrics& gmetrics, const Point& offset, uint16_t componentDepth)
|
||||||
{
|
{
|
||||||
#define ARG_1_AND_2_ARE_WORDS 0x0001
|
#define ARG_1_AND_2_ARE_WORDS 0x0001
|
||||||
#define ARGS_ARE_XY_VALUES 0x0002
|
#define ARGS_ARE_XY_VALUES 0x0002
|
||||||
|
@ -587,8 +589,8 @@ bool TtfReader::convertComposite(Shape* shape, TtfGlyphMetrics& gmetrics, const
|
||||||
// F2DOT14 yscale; /* Format 2.14 */
|
// F2DOT14 yscale; /* Format 2.14 */
|
||||||
pointer += 8U;
|
pointer += 8U;
|
||||||
}
|
}
|
||||||
if (!glyphMetrics(glyphIndex, componentGmetrics)) return false;
|
if (!glyphMetrics(glyphIndex, componentGmetrics.metrics, &componentGmetrics.outline)) return false;
|
||||||
if (!convert(shape, componentGmetrics, offset + componentOffset, kerning, componentDepth)) return false;
|
if (!convert(shape, componentGmetrics, offset + componentOffset, componentDepth)) return false;
|
||||||
} while (flags & MORE_COMPONENTS);
|
} while (flags & MORE_COMPONENTS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,7 @@
|
||||||
struct TtfGlyphMetrics
|
struct TtfGlyphMetrics
|
||||||
{
|
{
|
||||||
uint32_t outline; //glyph outline table offset
|
uint32_t outline; //glyph outline table offset
|
||||||
|
GlyphMetrics metrics;
|
||||||
float advanceWidth;
|
|
||||||
float leftSideBearing;
|
|
||||||
float yOffset;
|
|
||||||
float minw;
|
|
||||||
float minh;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,9 +57,9 @@ public:
|
||||||
} metrics;
|
} metrics;
|
||||||
|
|
||||||
bool header();
|
bool header();
|
||||||
uint32_t glyph(uint32_t codepoint, TtfGlyphMetrics& gmetrics);
|
uint32_t glyph(uint32_t codepoint, GlyphMetrics& gmetric, uint32_t* goutline);
|
||||||
void kerning(uint32_t lglyph, uint32_t rglyph, Point& out);
|
void kerning(uint32_t lglyph, uint32_t rglyph, Point& out);
|
||||||
bool convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& offset, const Point& kerning, uint16_t componentDepth);
|
bool convert(Shape* shape, const TtfGlyphMetrics& gmetric, const Point& offset, uint16_t componentDepth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//table offsets
|
//table offsets
|
||||||
|
@ -82,8 +77,8 @@ private:
|
||||||
uint32_t table(const char* tag);
|
uint32_t table(const char* tag);
|
||||||
uint32_t outlineOffset(uint32_t glyph);
|
uint32_t outlineOffset(uint32_t glyph);
|
||||||
uint32_t glyph(uint32_t codepoint);
|
uint32_t glyph(uint32_t codepoint);
|
||||||
bool glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics);
|
bool glyphMetrics(uint32_t glyphIndex, GlyphMetrics& gmetric, uint32_t* goutline);
|
||||||
bool convertComposite(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& offset, const Point& kerning, uint16_t componentDepth);
|
bool convertComposite(Shape* shape, const TtfGlyphMetrics& gmetric, const Point& offset, uint16_t componentDepth);
|
||||||
bool genPath(uint8_t* flags, uint16_t basePoint, uint16_t count);
|
bool genPath(uint8_t* flags, uint16_t basePoint, uint16_t count);
|
||||||
bool genSimpleOutline(Shape* shape, uint32_t outline, uint32_t cntrsCnt);
|
bool genSimpleOutline(Shape* shape, uint32_t outline, uint32_t cntrsCnt);
|
||||||
bool points(uint32_t outline, uint8_t* flags, Point* pts, uint32_t ptsCnt, const Point& offset);
|
bool points(uint32_t outline, uint8_t* flags, Point* pts, uint32_t ptsCnt, const Point& offset);
|
||||||
|
|
|
@ -118,6 +118,7 @@ struct FontLoader : LoadModule
|
||||||
|
|
||||||
virtual bool read(Shape* shape, char* text, FontMetrics& out) = 0;
|
virtual bool read(Shape* shape, char* text, FontMetrics& out) = 0;
|
||||||
virtual float transform(Paint* paint, FontMetrics& mertrics, float fontSize, bool italic) = 0;
|
virtual float transform(Paint* paint, FontMetrics& mertrics, float fontSize, bool italic) = 0;
|
||||||
|
virtual bool metrics(char* text, float fontSize, GlyphMetrics** metrics, uint32_t* size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_TVG_LOAD_MODULE_H_
|
#endif //_TVG_LOAD_MODULE_H_
|
||||||
|
|
|
@ -107,3 +107,9 @@ Type Text::type() const noexcept
|
||||||
{
|
{
|
||||||
return Type::Text;
|
return Type::Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result Text::metrics(GlyphMetrics** metrics, uint32_t* size) noexcept
|
||||||
|
{
|
||||||
|
return TEXT(this)->metrics(metrics, size);
|
||||||
|
}
|
|
@ -37,9 +37,9 @@ struct TextImpl : Text
|
||||||
Paint::Impl impl;
|
Paint::Impl impl;
|
||||||
Shape* shape; //text shape
|
Shape* shape; //text shape
|
||||||
FontLoader* loader = nullptr;
|
FontLoader* loader = nullptr;
|
||||||
FontMetrics metrics;
|
FontMetrics fmetrics;
|
||||||
char* utf8 = nullptr;
|
char* utf8 = nullptr;
|
||||||
float fontSize;
|
float fontSize = 0.0f;
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
@ -107,10 +107,10 @@ struct TextImpl : Text
|
||||||
|
|
||||||
//reload
|
//reload
|
||||||
if (changed) {
|
if (changed) {
|
||||||
loader->read(shape, utf8, metrics);
|
loader->read(shape, utf8, fmetrics);
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
return loader->transform(shape, metrics, fontSize, italic);
|
return loader->transform(shape, fmetrics, fontSize, italic);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
||||||
|
@ -172,6 +172,25 @@ struct TextImpl : Text
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result metrics(GlyphMetrics** metrics, uint32_t* size)
|
||||||
|
{
|
||||||
|
if (!metrics) return Result::InsufficientCondition;
|
||||||
|
|
||||||
|
//free allocated memory
|
||||||
|
if (*metrics && !size) {
|
||||||
|
tvg::free(*metrics);
|
||||||
|
*metrics = nullptr;
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!utf8 || tvg::zero(fontSize)) return Result::InsufficientCondition;
|
||||||
|
if (load() == 0.0f) return Result::InsufficientCondition;
|
||||||
|
|
||||||
|
if (!loader->metrics(utf8, fontSize, metrics, size)) return Result::InsufficientCondition;
|
||||||
|
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_TVG_TEXT_H
|
#endif //_TVG_TEXT_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue