Skip to content

Commit e8ec6ac

Browse files
authored
Merge pull request #3593 from Kumataro:refix_freetype_loadFontData
freetype: Add function to load font from buffer(additional patch)
2 parents 7b97851 + 9b32dd9 commit e8ec6ac

File tree

3 files changed

+121
-5
lines changed

3 files changed

+121
-5
lines changed

modules/freetype/include/opencv2/freetype.hpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,27 @@ class CV_EXPORTS_W FreeType2 : public Algorithm
7676
public:
7777
/** @brief Load font data.
7878
79-
The function loadFontData loads font data.
79+
The function loadFontData loads font data from file.
8080
8181
@param fontFileName FontFile Name
8282
@param idx face_index to select a font faces in a single file.
8383
*/
8484

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

87+
/** @brief Load font data.
88+
89+
The function loadFontData loads font data from memory.
90+
The data is not copied, the user needs to make sure the data lives at least as long as FreeType2.
91+
After the FreeType2 object is destroyed, the buffer can be safely deallocated.
92+
93+
@param pBuf pointer to buffer containing font data
94+
@param bufSize size of buffer
95+
@param idx face_index to select a font faces in a single file.
96+
*/
97+
98+
CV_WRAP virtual void loadFontData(char* pBuf, size_t bufSize, int idx) = 0;
99+
87100
/** @brief Set Split Number from Bezier-curve to line
88101
89102
The function setSplitNumber set the number of split points from bezier-curve to line.

modules/freetype/src/freetype.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class CV_EXPORTS_W FreeType2Impl CV_FINAL : public FreeType2
6767
FreeType2Impl();
6868
~FreeType2Impl();
6969
void loadFontData(String fontFileName, int idx) CV_OVERRIDE;
70+
void loadFontData(char* pBuf, size_t bufSize, int idx) CV_OVERRIDE;
7071
void setSplitNumber( int num ) CV_OVERRIDE;
7172
void putText(
7273
InputOutputArray img, const String& text, Point org,
@@ -87,6 +88,8 @@ class CV_EXPORTS_W FreeType2Impl CV_FINAL : public FreeType2
8788
int mCtoL;
8889
hb_font_t *mHb_font;
8990

91+
void loadFontData(FT_Open_Args &args, int idx);
92+
9093
void putTextBitmapMono(
9194
InputOutputArray img, const String& text, Point org,
9295
int fontHeight, Scalar color,
@@ -179,18 +182,54 @@ FreeType2Impl::~FreeType2Impl()
179182
}
180183

181184
void FreeType2Impl::loadFontData(String fontFileName, int idx)
185+
{
186+
FT_Open_Args args
187+
{
188+
FT_OPEN_PATHNAME,
189+
nullptr, // memory_base
190+
0, // memory_size
191+
const_cast<FT_String*>(fontFileName.c_str()),
192+
nullptr, // stream
193+
nullptr, // driver
194+
0, // num_params
195+
nullptr // params
196+
};
197+
198+
this->loadFontData(args, idx);
199+
}
200+
201+
void FreeType2Impl::loadFontData(char* pBuf, size_t bufSize, int idx)
202+
{
203+
CV_Assert( pBuf != nullptr );
204+
205+
FT_Open_Args args
206+
{
207+
FT_OPEN_MEMORY,
208+
reinterpret_cast<FT_Byte*>(pBuf),
209+
static_cast<FT_Long>(bufSize),
210+
nullptr, // pathname
211+
nullptr, // stream
212+
nullptr, // driver
213+
0, // num_params
214+
nullptr // params
215+
};
216+
217+
this->loadFontData(args, idx);
218+
}
219+
220+
void FreeType2Impl::loadFontData(FT_Open_Args &args, int idx)
182221
{
183222
CV_Assert( idx >= 0 );
184-
if( mIsFaceAvailable == true )
223+
if ( mIsFaceAvailable == true )
185224
{
186-
hb_font_destroy (mHb_font);
225+
hb_font_destroy(mHb_font);
187226
CV_Assert(!FT_Done_Face(mFace));
188227
}
189228

190229
mIsFaceAvailable = false;
191-
CV_Assert( !FT_New_Face( mLibrary, fontFileName.c_str(), static_cast<FT_Long>(idx), &(mFace) ) );
230+
CV_Assert( !FT_Open_Face(mLibrary, &args, idx, &mFace) );
192231

193-
mHb_font = hb_ft_font_create (mFace, NULL);
232+
mHb_font = hb_ft_font_create(mFace, NULL);
194233
if ( mHb_font == NULL )
195234
{
196235
CV_Assert(!FT_Done_Face(mFace));

modules/freetype/test/test_basic.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,39 @@ TEST(Freetype_Basic, success )
5555
EXPECT_NO_THROW( ft2->putText(dst, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
5656
}
5757

58+
TEST(Freetype_Basic, in_memory_font )
59+
{
60+
const string root = cvtest::TS::ptr()->get_data_path();
61+
const string font_path = root + "freetype/mplus/Mplus1-Regular.ttf";
62+
63+
cv::Ptr<cv::freetype::FreeType2> ft2;
64+
EXPECT_NO_THROW( ft2 = cv::freetype::createFreeType2() );
65+
EXPECT_NO_THROW( ft2->loadFontData( font_path, 0 ) );
66+
67+
Mat dst(600,600, CV_8UC3, Scalar::all(255) );
68+
Scalar col(128,64,255,192);
69+
EXPECT_NO_THROW( ft2->putText(dst, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
70+
71+
FILE* fp = fopen(font_path.c_str(), "rb");
72+
ASSERT_TRUE(fp != NULL);
73+
fseek(fp, 0, SEEK_END);
74+
const size_t file_size = ftell(fp);
75+
fseek(fp, 0, SEEK_SET);
76+
77+
std::vector<char> font_buffer(file_size);
78+
const size_t actual_read = fread(&font_buffer[0], 1, file_size, fp);
79+
fclose(fp);
80+
ASSERT_EQ(file_size, actual_read);
81+
82+
cv::Ptr<cv::freetype::FreeType2> ft2_in_memory;
83+
EXPECT_NO_THROW( ft2_in_memory = cv::freetype::createFreeType2() );
84+
EXPECT_NO_THROW( ft2_in_memory->loadFontData( &font_buffer[0], file_size, 0 ) );
85+
Mat dst_in_memory(600,600, CV_8UC3, Scalar::all(255) );
86+
EXPECT_NO_THROW( ft2_in_memory->putText(dst_in_memory, "Basic,success", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
87+
88+
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), dst, dst_in_memory);
89+
}
90+
5891
/******************
5992
* loadFontData()
6093
*****************/
@@ -105,6 +138,37 @@ TEST(Freetype_loadFontData, call_multiple)
105138
EXPECT_NO_THROW( ft2->putText(dst, "call_mutilple", Point( 0, 50), 50, col, -1, LINE_AA, true ) );
106139
}
107140

141+
TEST(Freetype_loadFontDataMemory, nullptr )
142+
{
143+
cv::Ptr<cv::freetype::FreeType2> ft2;
144+
EXPECT_NO_THROW( ft2 = cv::freetype::createFreeType2() );
145+
EXPECT_ANY_THROW( ft2->loadFontData( nullptr, 0, 0 ) );
146+
}
147+
148+
TEST(Freetype_loadFontDataMemory, broken_data )
149+
{
150+
const string root = cvtest::TS::ptr()->get_data_path();
151+
const string font_path = root + "freetype/mplus/Mplus1-Regular.ttf";
152+
153+
FILE* fp = fopen(font_path.c_str(), "rb");
154+
ASSERT_TRUE(fp != NULL);
155+
fseek(fp, 0, SEEK_END);
156+
const size_t file_size = ftell(fp);
157+
fseek(fp, 0, SEEK_SET);
158+
159+
std::vector<char> font_buffer(file_size);
160+
const size_t actual_read = fread(&font_buffer[0], 1, file_size, fp);
161+
fclose(fp);
162+
ASSERT_EQ(file_size, actual_read);
163+
164+
cv::Ptr<cv::freetype::FreeType2> ft2_in_memory;
165+
EXPECT_NO_THROW( ft2_in_memory = cv::freetype::createFreeType2() );
166+
167+
font_buffer[0] = ~font_buffer[0]; // font buffer was broken.
168+
169+
EXPECT_ANY_THROW( ft2_in_memory->loadFontData( &font_buffer[0], file_size, 0 ) );
170+
}
171+
108172
typedef testing::TestWithParam<int> idx_range;
109173

110174
TEST_P(idx_range, failed )

0 commit comments

Comments
 (0)