mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-20 03:55:47 +08:00
Developing
This commit is contained in:
@ -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)));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user