Skip to content

Commit

Permalink
Merge pull request #3593 from Kumataro:refix_freetype_loadFontData
Browse files Browse the repository at this point in the history
freetype: Add function to load font from buffer(additional patch)
  • Loading branch information
asmorkalov authored Nov 17, 2023
2 parents 7b97851 + 9b32dd9 commit e8ec6ac
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 5 deletions.
15 changes: 14 additions & 1 deletion modules/freetype/include/opencv2/freetype.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,27 @@ class CV_EXPORTS_W FreeType2 : public Algorithm
public:
/** @brief Load font data.
The function loadFontData loads font data.
The function loadFontData loads font data from file.
@param fontFileName FontFile Name
@param idx face_index to select a font faces in a single file.
*/

CV_WRAP virtual void loadFontData(String fontFileName, int idx) = 0;

/** @brief Load font data.
The function loadFontData loads font data from memory.
The data is not copied, the user needs to make sure the data lives at least as long as FreeType2.
After the FreeType2 object is destroyed, the buffer can be safely deallocated.
@param pBuf pointer to buffer containing font data
@param bufSize size of buffer
@param idx face_index to select a font faces in a single file.
*/

CV_WRAP virtual void loadFontData(char* pBuf, size_t bufSize, int idx) = 0;

/** @brief Set Split Number from Bezier-curve to line
The function setSplitNumber set the number of split points from bezier-curve to line.
Expand Down
47 changes: 43 additions & 4 deletions modules/freetype/src/freetype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class CV_EXPORTS_W FreeType2Impl CV_FINAL : public FreeType2
FreeType2Impl();
~FreeType2Impl();
void loadFontData(String fontFileName, int idx) CV_OVERRIDE;
void loadFontData(char* pBuf, size_t bufSize, int idx) CV_OVERRIDE;
void setSplitNumber( int num ) CV_OVERRIDE;
void putText(
InputOutputArray img, const String& text, Point org,
Expand All @@ -87,6 +88,8 @@ class CV_EXPORTS_W FreeType2Impl CV_FINAL : public FreeType2
int mCtoL;
hb_font_t *mHb_font;

void loadFontData(FT_Open_Args &args, int idx);

void putTextBitmapMono(
InputOutputArray img, const String& text, Point org,
int fontHeight, Scalar color,
Expand Down Expand Up @@ -179,18 +182,54 @@ FreeType2Impl::~FreeType2Impl()
}

void FreeType2Impl::loadFontData(String fontFileName, int idx)
{
FT_Open_Args args
{
FT_OPEN_PATHNAME,
nullptr, // memory_base
0, // memory_size
const_cast<FT_String*>(fontFileName.c_str()),
nullptr, // stream
nullptr, // driver
0, // num_params
nullptr // params
};

this->loadFontData(args, idx);
}

void FreeType2Impl::loadFontData(char* pBuf, size_t bufSize, int idx)
{
CV_Assert( pBuf != nullptr );

FT_Open_Args args
{
FT_OPEN_MEMORY,
reinterpret_cast<FT_Byte*>(pBuf),
static_cast<FT_Long>(bufSize),
nullptr, // pathname
nullptr, // stream
nullptr, // driver
0, // num_params
nullptr // params
};

this->loadFontData(args, idx);
}

void FreeType2Impl::loadFontData(FT_Open_Args &args, int idx)
{
CV_Assert( idx >= 0 );
if( mIsFaceAvailable == true )
if ( mIsFaceAvailable == true )
{
hb_font_destroy (mHb_font);
hb_font_destroy(mHb_font);
CV_Assert(!FT_Done_Face(mFace));
}

mIsFaceAvailable = false;
CV_Assert( !FT_New_Face( mLibrary, fontFileName.c_str(), static_cast<FT_Long>(idx), &(mFace) ) );
CV_Assert( !FT_Open_Face(mLibrary, &args, idx, &mFace) );

mHb_font = hb_ft_font_create (mFace, NULL);
mHb_font = hb_ft_font_create(mFace, NULL);
if ( mHb_font == NULL )
{
CV_Assert(!FT_Done_Face(mFace));
Expand Down
64 changes: 64 additions & 0 deletions modules/freetype/test/test_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,39 @@ TEST(Freetype_Basic, success )
EXPECT_NO_THROW( ft2->putText(dst, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
}

TEST(Freetype_Basic, in_memory_font )
{
const string root = cvtest::TS::ptr()->get_data_path();
const string font_path = root + "freetype/mplus/Mplus1-Regular.ttf";

cv::Ptr<cv::freetype::FreeType2> ft2;
EXPECT_NO_THROW( ft2 = cv::freetype::createFreeType2() );
EXPECT_NO_THROW( ft2->loadFontData( font_path, 0 ) );

Mat dst(600,600, CV_8UC3, Scalar::all(255) );
Scalar col(128,64,255,192);
EXPECT_NO_THROW( ft2->putText(dst, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );

FILE* fp = fopen(font_path.c_str(), "rb");
ASSERT_TRUE(fp != NULL);
fseek(fp, 0, SEEK_END);
const size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);

std::vector<char> font_buffer(file_size);
const size_t actual_read = fread(&font_buffer[0], 1, file_size, fp);
fclose(fp);
ASSERT_EQ(file_size, actual_read);

cv::Ptr<cv::freetype::FreeType2> ft2_in_memory;
EXPECT_NO_THROW( ft2_in_memory = cv::freetype::createFreeType2() );
EXPECT_NO_THROW( ft2_in_memory->loadFontData( &font_buffer[0], file_size, 0 ) );
Mat dst_in_memory(600,600, CV_8UC3, Scalar::all(255) );
EXPECT_NO_THROW( ft2_in_memory->putText(dst_in_memory, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );

EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), dst, dst_in_memory);
}

/******************
* loadFontData()
*****************/
Expand Down Expand Up @@ -105,6 +138,37 @@ TEST(Freetype_loadFontData, call_multiple)
EXPECT_NO_THROW( ft2->putText(dst, "call_mutilple", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
}

TEST(Freetype_loadFontDataMemory, nullptr )
{
cv::Ptr<cv::freetype::FreeType2> ft2;
EXPECT_NO_THROW( ft2 = cv::freetype::createFreeType2() );
EXPECT_ANY_THROW( ft2->loadFontData( nullptr, 0, 0 ) );
}

TEST(Freetype_loadFontDataMemory, broken_data )
{
const string root = cvtest::TS::ptr()->get_data_path();
const string font_path = root + "freetype/mplus/Mplus1-Regular.ttf";

FILE* fp = fopen(font_path.c_str(), "rb");
ASSERT_TRUE(fp != NULL);
fseek(fp, 0, SEEK_END);
const size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);

std::vector<char> font_buffer(file_size);
const size_t actual_read = fread(&font_buffer[0], 1, file_size, fp);
fclose(fp);
ASSERT_EQ(file_size, actual_read);

cv::Ptr<cv::freetype::FreeType2> ft2_in_memory;
EXPECT_NO_THROW( ft2_in_memory = cv::freetype::createFreeType2() );

font_buffer[0] = ~font_buffer[0]; // font buffer was broken.

EXPECT_ANY_THROW( ft2_in_memory->loadFontData( &font_buffer[0], file_size, 0 ) );
}

typedef testing::TestWithParam<int> idx_range;

TEST_P(idx_range, failed )
Expand Down

0 comments on commit e8ec6ac

Please sign in to comment.