Developing

This commit is contained in:
Oleg Korshul
2022-05-31 15:26:36 +03:00
parent 32ac61f890
commit 19070ca5c9
8 changed files with 207 additions and 16 deletions

View File

@ -1,4 +1,26 @@
#include "./TextMeasurerEmbed.h"
#include "./../../fontengine/TextShaper.h"
#define RAW_POINTER(value) ((CPointerEmbedObject*)value->toObject()->getNative())->Data
class CExternalPointerJS : public NSShaper::CExternalPointer
{
public:
CExternalPointerJS() : NSShaper::CExternalPointer() {}
virtual ~CExternalPointerJS() {}
public:
virtual void Alloc(const unsigned int& len)
{
Len = len;
Data = NSAllocator::Alloc((size_t)Len);
}
virtual void Free()
{
if (Data)
NSAllocator::Free(Data, (size_t)Len);
}
};
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Malloc(JSSmart<CJSValue> typed_array_or_len)
{
@ -30,56 +52,74 @@ JSSmart<CJSValue> CTextMeasurerEmbed::FT_Free(JSSmart<CJSValue> pointer)
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Init()
{
CPointerEmbedObject* pointer = new CPointerEmbedObject(NSShaper::FT_Library_Init(), [](void* data) { NSShaper::FT_Library_Destroy(data); });
return pointer->createObject();
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Set_TrueType_HintProp(JSSmart<CJSValue> library, JSSmart<CJSValue> tt_interpreter)
{
return CJSContext::createInt(NSShaper::FT_Set_TrueType_HintProp(RAW_POINTER(library), tt_interpreter->toUInt32()));
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Open_Face(JSSmart<CJSValue> library, JSSmart<CJSValue> memory, JSSmart<CJSValue> size, JSSmart<CJSValue> face_index)
{
void* face = NSShaper::FT_Open_Face(RAW_POINTER(library), (unsigned char*)RAW_POINTER(memory), size->toUInt32(), face_index->toInt32());
CPointerEmbedObject* pointer = new CPointerEmbedObject(face, [](void* data) { NSShaper::FT_Done_Face(data); });
return pointer->createObject();
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_GetFaceInfo(JSSmart<CJSValue> face)
{
CExternalPointerJS result;
if (!NSShaper::FT_GetFaceInfo(RAW_POINTER(face), &result))
return CJSContext::createNull();
return CJSContext::createUint8Array(result.Data, result.Len, false);
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Load_Glyph(JSSmart<CJSValue> face, JSSmart<CJSValue> gid, JSSmart<CJSValue> mode)
{
return CJSContext::createInt(NSShaper::FT_Load_Glyph(RAW_POINTER(face), gid->toUInt32(), mode->toInt32()));
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Get_Glyph_Measure_Params(JSSmart<CJSValue> face, JSSmart<CJSValue> is_vector)
{
CExternalPointerJS result;
if (!NSShaper::FT_Get_Glyph_Measure_Params(RAW_POINTER(face), is_vector->toBool(), &result))
return CJSContext::createNull();
return CJSContext::createUint8Array(result.Data, result.Len, false);
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Get_Glyph_Render_Params(JSSmart<CJSValue> face, JSSmart<CJSValue> render_mode)
{
CExternalPointerJS result;
if (!NSShaper::FT_Get_Glyph_Render_Params(RAW_POINTER(face), render_mode->toInt32(), &result))
return CJSContext::createNull();
return CJSContext::createUint8Array(result.Data, result.Len, false);
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Get_Glyph_Render_Buffer(JSSmart<CJSValue> face)
{
void* Data = NSShaper::FT_Get_Glyph_Render_Buffer(RAW_POINTER(face));
CPointerEmbedObject* pObject = new CPointerEmbedObject(Data, NSPointerObjectDeleters::EmptyDeleter);
return pObject->createObject();
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Set_Transform(JSSmart<CJSValue> face, JSSmart<CJSValue> xx, JSSmart<CJSValue> yx, JSSmart<CJSValue> xy, JSSmart<CJSValue> yy)
{
NSShaper::FT_Set_Transform(RAW_POINTER(face), xx->toInt32(), yx->toInt32(), xy->toInt32(), yy->toInt32());
return CJSContext::createUndefined();
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_Set_Char_Size(JSSmart<CJSValue> face, JSSmart<CJSValue> char_width, JSSmart<CJSValue> char_height, JSSmart<CJSValue> hres, JSSmart<CJSValue> vres)
{
return CJSContext::createInt(NSShaper::FT_Set_Char_Size(RAW_POINTER(face), char_width->toInt32(), char_height->toInt32(), hres->toUInt32(), vres->toUInt32()));
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_SetCMapForCharCode(JSSmart<CJSValue> face, JSSmart<CJSValue> unicode)
{
return CJSContext::createUInt(NSShaper::FT_SetCMapForCharCode(RAW_POINTER(face), unicode->toUInt32()));
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_GetKerningX(JSSmart<CJSValue> face, JSSmart<CJSValue> gid1, JSSmart<CJSValue> gid2)
{
return CJSContext::createInt(NSShaper::FT_GetKerningX(RAW_POINTER(face), gid1->toUInt32(), gid2->toUInt32()));
}
JSSmart<CJSValue> CTextMeasurerEmbed::FT_GetFaceMaxAdvanceX(JSSmart<CJSValue> face)
{
return CJSContext::createInt(NSShaper::FT_GetFaceMaxAdvanceX(RAW_POINTER(face)));
}

View File

@ -51,7 +51,7 @@ JSSmart<CJSValue> CZipEmbed::getFile(JSSmart<CJSValue> filePath)
std::wstring sFilePath = filePath->toStringW();
IFolder::CBuffer* pBuffer;
if (m_pFolder->read(sFilePath, pBuffer))
if (!m_pFolder->read(sFilePath, pBuffer))
return CJSContext::createNull();
size_t nBufferSize = (size_t)pBuffer->Size;

View File

@ -40,6 +40,7 @@ namespace NSJSBase
virtual bool toBool() = 0;
virtual int toInt32() = 0;
virtual unsigned int toUInt32() = 0;
virtual double toDouble() = 0;
virtual std::string toStringA() = 0;
virtual std::wstring toStringW() = 0;
@ -250,6 +251,7 @@ namespace NSJSBase
static CJSValue* createNull();
static CJSValue* createBool(const bool& value);
static CJSValue* createInt(const int& value);
static CJSValue* createUInt(const unsigned int& value);
static CJSValue* createDouble(const double& value);
static CJSValue* createString(const char* value, const int& length = -1);
static CJSValue* createString(const std::string& value);

View File

@ -221,6 +221,13 @@ namespace NSJSBase
return _value;
}
CJSValue* CJSContext::createUInt(const unsigned int& value)
{
CJSValueV8* _value = new CJSValueV8();
_value->value = v8::Integer::NewFromUnsigned(CV8Worker::GetCurrent(), value);
return _value;
}
CJSValue* CJSContext::createDouble(const double& value)
{
CJSValueV8* _value = new CJSValueV8();

View File

@ -282,6 +282,11 @@ namespace NSJSBase
return 0;
}
virtual unsigned int toUInt32()
{
return 0;
}
virtual double toDouble()
{
return 0;
@ -342,6 +347,11 @@ namespace NSJSBase
return value.IsEmpty() ? 0 : value->Int32Value(V8ContextOneArg).V8ToChecked();
}
virtual unsigned int toUInt32()
{
return value.IsEmpty() ? 0 : value->Uint32Value(V8ContextOneArg).V8ToChecked();
}
virtual double toDouble()
{
return value.IsEmpty() ? 0 : value->NumberValue(V8ContextOneArg).V8ToChecked();

View File

@ -46,15 +46,12 @@
#include <freetype/internal/tttypes.h>
#include "ftmodapi.h"
#include <hb.h>
#include <hb-ft.h>
#include <hb-ot.h>
namespace NSShaper
{
#define ALLOC_WRITER(size) result->Alloc((size)); unsigned char* pCurData = result->Data
#define WRITE_INT(value) result->WriteInt(pCurData, value); pCurData += 4
#define WRITE_UINT(value) result->WriteUInt(pCurData, value); pCurData += 4
#define WRITE_UCHAR(value) *pCurData++ = value
CExternalPointer::CExternalPointer()
{
@ -617,3 +614,115 @@ namespace NSShaper
return true;
}
}
#ifdef SUPPORT_HARFBUZZ_SHAPER
#include <hb.h>
#include <hb-ft.h>
#include <hb-ot.h>
namespace NSShaper
{
#define g_userfeatures_count 5
hb_feature_t g_userfeatures[g_userfeatures_count];
bool g_userfeatures_init = false;
void* HB_LanguageFromString(const std::string language_bcp_47)
{
return (void*)hb_language_from_string(language_bcp_47.c_str(), language_bcp_47.length());
}
void HB_free(void* data)
{
HB_free(data);
}
void HB_ShapeText(void* face, void* font, char* text,
unsigned int nFeatures, unsigned int nScript, unsigned int nDirection, void* nLanguage, CExternalPointer* result)
{
// init features
if (!g_userfeatures_init)
{
hb_tag_t tags[] = {
HB_TAG('l','i','g','a'),
HB_TAG('c','l','i','g'),
HB_TAG('h','l','i','g'),
HB_TAG('d','l','i','g'),
HB_TAG('k','e','r','n')
};
for (int nTag = 0; nTag < g_userfeatures_count; ++nTag)
{
g_userfeatures[nTag].tag = tags[nTag];
g_userfeatures[nTag].value = 0;
g_userfeatures[nTag].start = HB_FEATURE_GLOBAL_START;
g_userfeatures[nTag].end = HB_FEATURE_GLOBAL_END;
}
g_userfeatures_init = true;
}
// font
hb_font_t* pFont;
if (NULL == font)
{
pFont = hb_ft_font_create((FT_Face)face, NULL);
hb_ft_font_set_funcs(pFont);
}
else
pFont = (hb_font_t*)font;
// features
for (int nTag = 0; nTag < g_userfeatures_count; ++nTag)
g_userfeatures[nTag].value = (nFeatures & (1 << nTag)) ? 1 : 0;
// buffer
hb_buffer_t* hbBuffer = hb_buffer_create();
hb_buffer_set_direction(hbBuffer, (hb_direction_t)nDirection);
hb_buffer_set_script(hbBuffer, (hb_script_t)nScript);
hb_buffer_set_language(hbBuffer, (hb_language_t)nLanguage);
hb_buffer_set_cluster_level(hbBuffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
int text_len = (int)strlen(text);
hb_buffer_add_utf8(hbBuffer, text, text_len, 0, text_len);
hb_buffer_guess_segment_properties(hbBuffer);
// shape
hb_shape(pFont, hbBuffer, g_userfeatures, g_userfeatures_count);
unsigned int glyph_count;
hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(hbBuffer, &glyph_count);
hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(hbBuffer, &glyph_count);
int nSize = 4 + 8 + glyph_count * (1 + 1 + 4 * 6);
ALLOC_WRITER(nSize);
WRITE_UINT(nSize);
uint64_t pFontPointer = (uint64_t)pFont;
WRITE_UINT(pFontPointer & 0xFFFFFFFF);
WRITE_UINT((pFontPointer >> 32) & 0xFFFFFFFF);
for (unsigned i = 0; i < glyph_count; ++i)
{
unsigned char nGlyphType = (unsigned char)hb_ot_layout_get_glyph_class(hb_font_get_face(pFont), glyph_info[i].codepoint);
unsigned char nGlyphFlags = (unsigned char)hb_glyph_info_get_glyph_flags(&glyph_info[i]);
WRITE_UCHAR(nGlyphType);
WRITE_UCHAR(nGlyphFlags);
WRITE_UINT(glyph_info[i].codepoint);
WRITE_UINT(glyph_info[i].cluster);
WRITE_INT(glyph_pos[i].x_advance);
WRITE_INT(glyph_pos[i].y_advance);
WRITE_INT(glyph_pos[i].x_offset);
WRITE_INT(glyph_pos[i].y_offset);
}
hb_buffer_destroy(hbBuffer);
}
void HB_FontFree(void* font)
{
hb_font_destroy((hb_font_t*)font);
}
}
#endif

View File

@ -77,6 +77,16 @@ namespace NSShaper
GRAPHICS_DECL unsigned int FT_SetCMapForCharCode(void* face, unsigned int unicode);
GRAPHICS_DECL int FT_GetKerningX(void* face, unsigned int prev_gid, unsigned int gid);
GRAPHICS_DECL int FT_GetFaceMaxAdvanceX(void* face);
#ifdef SUPPORT_HARFBUZZ_SHAPER
GRAPHICS_DECL void* HB_LanguageFromString(const std::string language_bcp_47);
GRAPHICS_DECL void HB_free(void* data);
GRAPHICS_DECL void HB_ShapeText(void* face, void* font, char* text,
unsigned int nFeatures, unsigned int nScript, unsigned int nDirection, void* nLanguage, CExternalPointer* result);
GRAPHICS_DECL void HB_FontFree(void* font);
#endif
}
#endif // _BUILD_TEXT_MANAGER_FONTMANAGER_H_

View File

@ -493,7 +493,20 @@ SOURCES += ./../../fontengine/FontsAssistant.cpp
HEADERS += ./../../fontengine/TextShaper.h
SOURCES += ./../../fontengine/TextShaper.cpp
include(./../../fontengine/js/common/graphics_shaper.pri)
CONFIG += enable_support_shaper
core_windows {
MSVC_VERSION_DETECT = $$(VisualStudioVersion)
lessThan(MSVC_VERSION_DETECT, 16.0) {
CONFIG -= enable_support_shaper
}
}
enable_support_shaper {
DEFINES += SUPPORT_HARFBUZZ_SHAPER
include(./../../fontengine/js/common/graphics_shaper.pri)
}
# -------------------------------------------------
core_ios {