diff --git a/app/src/main/cpp/CvText.cpp b/app/src/main/cpp/CvText.cpp index ef63ec56..06ebe018 100644 --- a/app/src/main/cpp/CvText.cpp +++ b/app/src/main/cpp/CvText.cpp @@ -14,780 +14,785 @@ #include namespace cv { -namespace ft { - - using namespace std; - - class FreeType2Impl : public FreeType2 - { - public: - FreeType2Impl(); - ~FreeType2Impl(); - void loadFontData(String fontFileName, int idx); - void setSplitNumber( int num ); - void putText( - InputOutputArray img, const String& text, Point org, - int fontHeight, Scalar color, - int thickness, int line_type, bool bottomLeftOrigin - ); - Size getTextSize( - const String& text, int fontHeight, int thickness, - CV_OUT int* baseLine - ); - - private: - FT_Library mLibrary; - FT_Face mFace; - FT_Outline_Funcs mFn; - - bool mIsFaceAvailable; - int mCtoL; - - void putTextBitmapMono( - InputOutputArray img, const String& text, Point org, - int fontHeight, Scalar color, - int thickness, int line_type, bool bottomLeftOrigin - ); - - void putTextBitmapBlend( - InputOutputArray img, const String& text, Point org, - int fontHeight, Scalar color, - int thickness, int line_type, bool bottomLeftOrigin - ); - - void putTextOutline( - InputOutputArray img, const String& text, Point org, - int fontHeight, Scalar color, - int thickness, int line_type, bool bottomLeftOrigin - ); - - typedef void (putPixel_mono_fn)( Mat& _dst, const int _py, const int _px, const uint8_t *_col); - putPixel_mono_fn putPixel_8UC1_mono; - putPixel_mono_fn putPixel_8UC3_mono; - putPixel_mono_fn putPixel_8UC4_mono; - - typedef void (putPixel_blend_fn)( Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha); - putPixel_blend_fn putPixel_8UC1_blend; - putPixel_blend_fn putPixel_8UC3_blend; - putPixel_blend_fn putPixel_8UC4_blend; - - static int mvFn( const FT_Vector *to, void * user); - static int lnFn( const FT_Vector *to, void * user); - static int coFn( const FT_Vector *cnt, - const FT_Vector *to, - void * user); - static int cuFn( const FT_Vector *cnt1, - const FT_Vector *cnt2, - const FT_Vector *to, - void * user); - - /** - * Convert from FT_F26Dot6 to int(coodinate of OpenCV) - * (FT_F26Dot6 is signed 26.6 real) - */ - static int ftd(FT_F26Dot6 fixedInt){ - if ( fixedInt > 0 ) { - return ( fixedInt + 32 ) / 64 ; - }else{ - return ( fixedInt - 32 ) / 64 ; - } - } - - class PathUserData{ - private: - public: - PathUserData( InputOutputArray _img) : mImg(_img) {}; - - InputOutputArray mImg; - Scalar mColor; - int mThickness; - int mLine_type; - FT_Vector mOldP; - int mCtoL; - std::vector < Point > mPts; - }; - }; - - FreeType2Impl::FreeType2Impl() - { - FT_Init_FreeType(&(this->mLibrary) ); - - mCtoL = 16; - mFn.shift = 0; - mFn.delta = 0; - mFn.move_to = FreeType2Impl::mvFn; - mFn.line_to = FreeType2Impl::lnFn; - mFn.cubic_to = FreeType2Impl::cuFn; - mFn.conic_to = FreeType2Impl::coFn; - - mIsFaceAvailable = false; - } - - FreeType2Impl::~FreeType2Impl() - { - if( mIsFaceAvailable == true ) - { + namespace ft { + + using namespace std; + + class FreeType2Impl : public FreeType2 + { + public: + FreeType2Impl(); + ~FreeType2Impl(); + void loadFontData(String fontFileName, int idx); + void setSplitNumber(int num); + void putText( + InputOutputArray img, const String& text, Point org, + int fontHeight, Scalar color, + int thickness, int line_type, bool bottomLeftOrigin + ); + Size getTextSize( + const String& text, int fontHeight, int thickness, + CV_OUT int* baseLine + ); + + private: + FT_Library mLibrary; + FT_Face mFace; + FT_Outline_Funcs mFn; + + bool mIsFaceAvailable; + int mCtoL; + + void putTextBitmapMono( + InputOutputArray img, const String& text, Point org, + int fontHeight, Scalar color, + int thickness, int line_type, bool bottomLeftOrigin + ); + + void putTextBitmapBlend( + InputOutputArray img, const String& text, Point org, + int fontHeight, Scalar color, + int thickness, int line_type, bool bottomLeftOrigin + ); + + void putTextOutline( + InputOutputArray img, const String& text, Point org, + int fontHeight, Scalar color, + int thickness, int line_type, bool bottomLeftOrigin + ); + + typedef void (putPixel_mono_fn)(Mat& _dst, const int _py, const int _px, const uint8_t *_col); + putPixel_mono_fn putPixel_8UC1_mono; + putPixel_mono_fn putPixel_8UC3_mono; + putPixel_mono_fn putPixel_8UC4_mono; + + typedef void (putPixel_blend_fn)(Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha); + putPixel_blend_fn putPixel_8UC1_blend; + putPixel_blend_fn putPixel_8UC3_blend; + putPixel_blend_fn putPixel_8UC4_blend; + + static int mvFn(const FT_Vector *to, void * user); + static int lnFn(const FT_Vector *to, void * user); + static int coFn(const FT_Vector *cnt, + const FT_Vector *to, + void * user); + static int cuFn(const FT_Vector *cnt1, + const FT_Vector *cnt2, + const FT_Vector *to, + void * user); + + /** + * Convert from FT_F26Dot6 to int(coodinate of OpenCV) + * (FT_F26Dot6 is signed 26.6 real) + */ + static int ftd(FT_F26Dot6 fixedInt) { + if (fixedInt > 0) { + return (fixedInt + 32) / 64; + } + else { + return (fixedInt - 32) / 64; + } + } + + class PathUserData { + private: + public: + PathUserData(InputOutputArray _img) : mImg(_img) {}; + + InputOutputArray mImg; + Scalar mColor; + int mThickness; + int mLine_type; + FT_Vector mOldP; + int mCtoL; + std::vector < Point > mPts; + }; + }; + + FreeType2Impl::FreeType2Impl() + { + FT_Init_FreeType(&(this->mLibrary)); + + mCtoL = 16; + mFn.shift = 0; + mFn.delta = 0; + mFn.move_to = FreeType2Impl::mvFn; + mFn.line_to = FreeType2Impl::lnFn; + mFn.cubic_to = FreeType2Impl::cuFn; + mFn.conic_to = FreeType2Impl::coFn; + + mIsFaceAvailable = false; + } + + FreeType2Impl::~FreeType2Impl() + { + if (mIsFaceAvailable == true) + { #if 0 - hb_font_destroy (mHb_font); + hb_font_destroy(mHb_font); #endif - CV_Assert(!FT_Done_Face(mFace)); - mIsFaceAvailable = false; - } - CV_Assert(!FT_Done_FreeType(mLibrary)); - } - - void FreeType2Impl::loadFontData(String fontFileName, int idx) - { - CV_Assert( idx >= 0 ); - if( mIsFaceAvailable == true ) - { + CV_Assert(!FT_Done_Face(mFace)); + mIsFaceAvailable = false; + } + CV_Assert(!FT_Done_FreeType(mLibrary)); + } + + void FreeType2Impl::loadFontData(String fontFileName, int idx) + { + CV_Assert(idx >= 0); + if (mIsFaceAvailable == true) + { #if 0 - hb_font_destroy (mHb_font); + hb_font_destroy(mHb_font); #endif - CV_Assert(!FT_Done_Face(mFace)); - } + CV_Assert(!FT_Done_Face(mFace)); + } - mIsFaceAvailable = false; - CV_Assert( !FT_New_Face( mLibrary, fontFileName.c_str(), static_cast(idx), &(mFace) ) ); + mIsFaceAvailable = false; + CV_Assert(!FT_New_Face(mLibrary, fontFileName.c_str(), static_cast(idx), &(mFace))); #if 0 - mHb_font = hb_ft_font_create (mFace, NULL); - if ( mHb_font == NULL ) - { - CV_Assert(!FT_Done_Face(mFace)); - return; - } - CV_Assert( mHb_font != NULL ); + mHb_font = hb_ft_font_create(mFace, NULL); + if (mHb_font == NULL) + { + CV_Assert(!FT_Done_Face(mFace)); + return; + } + CV_Assert(mHb_font != NULL); #endif - mIsFaceAvailable = true; - } - - void FreeType2Impl::setSplitNumber(int num ){ - CV_Assert( num > 0 ); - mCtoL = num; - } - - void FreeType2Impl::putText( - InputOutputArray _img, const String& _text, Point _org, - int _fontHeight, Scalar _color, - int _thickness, int _line_type, bool _bottomLeftOrigin - ) - { - CV_Assert ( mIsFaceAvailable == true ); - CV_Assert ( _img.empty() == false ); - CV_Assert ( _img.isMat() == true ); - CV_Assert ( _img.dims() == 2 ); - CV_Assert( ( _img.type() == CV_8UC1 ) || - ( _img.type() == CV_8UC3 ) || - ( _img.type() == CV_8UC4 ) ); - CV_Assert( ( _line_type == LINE_AA) || - ( _line_type == LINE_4 ) || - ( _line_type == LINE_8 ) ); - CV_Assert ( _fontHeight >= 0 ); - - if ( _text.empty() ) - { - return; - } - if ( _fontHeight == 0 ) - { - return; - } - - CV_Assert(!FT_Set_Pixel_Sizes( mFace, _fontHeight, _fontHeight )); - - if( _thickness < 0 ) // CV_FILLED - { - if ( _line_type == LINE_AA ) { - putTextBitmapBlend( _img, _text, _org, _fontHeight, _color, - _thickness, _line_type, _bottomLeftOrigin ); - }else{ - putTextBitmapMono( _img, _text, _org, _fontHeight, _color, - _thickness, _line_type, _bottomLeftOrigin ); - } - }else{ - putTextOutline( _img, _text, _org, _fontHeight, _color, - _thickness, _line_type, _bottomLeftOrigin ); - } - } - - void FreeType2Impl::putTextOutline( - InputOutputArray _img, const String& _text, Point _org, - int _fontHeight, Scalar _color, - int _thickness, int _line_type, bool _bottomLeftOrigin ) - { + mIsFaceAvailable = true; + } + + void FreeType2Impl::setSplitNumber(int num) { + CV_Assert(num > 0); + mCtoL = num; + } + + void FreeType2Impl::putText( + InputOutputArray _img, const String& _text, Point _org, + int _fontHeight, Scalar _color, + int _thickness, int _line_type, bool _bottomLeftOrigin + ) + { + CV_Assert(mIsFaceAvailable == true); + CV_Assert(_img.empty() == false); + CV_Assert(_img.isMat() == true); + CV_Assert(_img.dims() == 2); + CV_Assert((_img.type() == CV_8UC1) || + (_img.type() == CV_8UC3) || + (_img.type() == CV_8UC4)); + CV_Assert((_line_type == LINE_AA) || + (_line_type == LINE_4) || + (_line_type == LINE_8)); + CV_Assert(_fontHeight >= 0); + + if (_text.empty()) + { + return; + } + if (_fontHeight == 0) + { + return; + } + + CV_Assert(!FT_Set_Pixel_Sizes(mFace, _fontHeight, _fontHeight)); + + if (_thickness < 0) // CV_FILLED + { + if (_line_type == LINE_AA) { + putTextBitmapBlend(_img, _text, _org, _fontHeight, _color, + _thickness, _line_type, _bottomLeftOrigin); + } + else { + putTextBitmapMono(_img, _text, _org, _fontHeight, _color, + _thickness, _line_type, _bottomLeftOrigin); + } + } + else { + putTextOutline(_img, _text, _org, _fontHeight, _color, + _thickness, _line_type, _bottomLeftOrigin); + } + } + + void FreeType2Impl::putTextOutline( + InputOutputArray _img, const String& _text, Point _org, + int _fontHeight, Scalar _color, + int _thickness, int _line_type, bool _bottomLeftOrigin) + { #if 0 - hb_buffer_t *hb_buffer = hb_buffer_create (); - CV_Assert( hb_buffer != NULL ); + hb_buffer_t *hb_buffer = hb_buffer_create(); + CV_Assert(hb_buffer != NULL); - hb_buffer_add_utf8 (hb_buffer, _text.c_str(), -1, 0, -1); - hb_buffer_guess_segment_properties (hb_buffer); - hb_shape (mHb_font, hb_buffer, NULL, 0); + hb_buffer_add_utf8(hb_buffer, _text.c_str(), -1, 0, -1); + hb_buffer_guess_segment_properties(hb_buffer); + hb_shape(mHb_font, hb_buffer, NULL, 0); - unsigned int textLen = 0; - hb_glyph_info_t *info = - hb_buffer_get_glyph_infos(hb_buffer,&textLen ); - CV_Assert( info != NULL ); + unsigned int textLen = 0; + hb_glyph_info_t *info = + hb_buffer_get_glyph_infos(hb_buffer, &textLen); + CV_Assert(info != NULL); #else - std::wstring_convert> converter; - wstring wstr = converter.from_bytes(_text); + std::wstring_convert> converter; + wstring wstr = converter.from_bytes(_text); #endif - PathUserData *userData = new PathUserData( _img ); - userData->mColor = _color; - userData->mCtoL = mCtoL; - userData->mThickness = _thickness; - userData->mLine_type = _line_type; + PathUserData *userData = new PathUserData(_img); + userData->mColor = _color; + userData->mCtoL = mCtoL; + userData->mThickness = _thickness; + userData->mLine_type = _line_type; - // Initilize currentPosition ( in FreeType coordinates) - FT_Vector currentPos = {0,0}; - currentPos.x = _org.x * 64; - currentPos.y = _org.y * 64; + // Initilize currentPosition ( in FreeType coordinates) + FT_Vector currentPos = { 0,0 }; + currentPos.x = _org.x * 64; + currentPos.y = _org.y * 64; - // Update currentPosition with bottomLeftOrigin ( in FreeType coordinates) - if( _bottomLeftOrigin != true ){ - currentPos.y += _fontHeight * 64; - } + // Update currentPosition with bottomLeftOrigin ( in FreeType coordinates) + if (_bottomLeftOrigin != true) { + currentPos.y += _fontHeight * 64; + } #if defined(USING_HB) - for( unsigned int i = 0 ; i < textLen ; i ++ ){ - CV_Assert( !FT_Load_Glyph(mFace, info[i].codepoint, 0 ) ); + for (unsigned int i = 0; i < textLen; i++) { + CV_Assert(!FT_Load_Glyph(mFace, info[i].codepoint, 0)); #else - for( unsigned int i = 0 ; i < wstr.size() ; i ++ ){ - CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0 )); + for (unsigned int i = 0; i < wstr.size(); i++) { + CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0)); #endif - FT_GlyphSlot slot = mFace->glyph; - FT_Outline outline = slot->outline; + FT_GlyphSlot slot = mFace->glyph; + FT_Outline outline = slot->outline; - // Flip ( in FreeType coordinates ) - FT_Matrix mtx = { 1 << 16 , 0 , 0 , -(1 << 16) }; - FT_Outline_Transform(&outline, &mtx); + // Flip ( in FreeType coordinates ) + FT_Matrix mtx = { 1 << 16 , 0 , 0 , -(1 << 16) }; + FT_Outline_Transform(&outline, &mtx); - // Move to current position ( in FreeType coordinates ) - FT_Outline_Translate(&outline, - currentPos.x, - currentPos.y); + // Move to current position ( in FreeType coordinates ) + FT_Outline_Translate(&outline, + currentPos.x, + currentPos.y); - // Draw ( in FreeType coordinates ) - CV_Assert( !FT_Outline_Decompose(&outline, &mFn, (void*)userData) ); + // Draw ( in FreeType coordinates ) + CV_Assert(!FT_Outline_Decompose(&outline, &mFn, (void*)userData)); - // Draw (Last Path) ( in FreeType coordinates ) - mvFn( NULL, (void*)userData ); + // Draw (Last Path) ( in FreeType coordinates ) + mvFn(NULL, (void*)userData); - // Update current position ( in FreeType coordinates ) - currentPos.x += mFace->glyph->advance.x; - currentPos.y += mFace->glyph->advance.y; - } - delete userData; + // Update current position ( in FreeType coordinates ) + currentPos.x += mFace->glyph->advance.x; + currentPos.y += mFace->glyph->advance.y; + } + delete userData; #if defined(USING_HB) - hb_buffer_destroy (hb_buffer); + hb_buffer_destroy(hb_buffer); #endif 0 - } - - void FreeType2Impl::putPixel_8UC1_mono( Mat& _dst, const int _py, const int _px, const uint8_t *_col) - { - uint8_t* ptr = _dst.ptr( _py, _px ); - (*ptr) = _col[0]; - } - - void FreeType2Impl::putPixel_8UC3_mono ( Mat& _dst, const int _py, const int _px, const uint8_t *_col) - { - cv::Vec3b* ptr = _dst.ptr( _py, _px ); - (*ptr)[0] = _col[0]; - (*ptr)[1] = _col[1]; - (*ptr)[2] = _col[2]; - } - - void FreeType2Impl::putPixel_8UC4_mono( Mat& _dst, const int _py, const int _px, const uint8_t *_col) - { - cv::Vec4b* ptr = _dst.ptr( _py, _px ); - (*ptr)[0] = _col[0]; - (*ptr)[1] = _col[1]; - (*ptr)[2] = _col[2]; - (*ptr)[3] = _col[3]; - } - - void FreeType2Impl::putTextBitmapMono( - InputOutputArray _img, const String& _text, Point _org, - int _fontHeight, Scalar _color, - int _thickness, int _line_type, bool _bottomLeftOrigin ) - { - CV_Assert( _thickness < 0 ); - CV_Assert( _line_type == LINE_4 || _line_type == LINE_8); - - Mat dst = _img.getMat(); + } + + void FreeType2Impl::putPixel_8UC1_mono(Mat& _dst, const int _py, const int _px, const uint8_t *_col) + { + uint8_t* ptr = _dst.ptr(_py, _px); + (*ptr) = _col[0]; + } + + void FreeType2Impl::putPixel_8UC3_mono(Mat& _dst, const int _py, const int _px, const uint8_t *_col) + { + cv::Vec3b* ptr = _dst.ptr(_py, _px); + (*ptr)[0] = _col[0]; + (*ptr)[1] = _col[1]; + (*ptr)[2] = _col[2]; + } + + void FreeType2Impl::putPixel_8UC4_mono(Mat& _dst, const int _py, const int _px, const uint8_t *_col) + { + cv::Vec4b* ptr = _dst.ptr(_py, _px); + (*ptr)[0] = _col[0]; + (*ptr)[1] = _col[1]; + (*ptr)[2] = _col[2]; + (*ptr)[3] = _col[3]; + } + + void FreeType2Impl::putTextBitmapMono( + InputOutputArray _img, const String& _text, Point _org, + int _fontHeight, Scalar _color, + int _thickness, int _line_type, bool _bottomLeftOrigin) + { + CV_Assert(_thickness < 0); + CV_Assert(_line_type == LINE_4 || _line_type == LINE_8); + + Mat dst = _img.getMat(); #if defined(USING_HB) - hb_buffer_t *hb_buffer = hb_buffer_create (); - CV_Assert( hb_buffer != NULL ); + hb_buffer_t *hb_buffer = hb_buffer_create(); + CV_Assert(hb_buffer != NULL); - hb_buffer_add_utf8 (hb_buffer, _text.c_str(), -1, 0, -1); - hb_buffer_guess_segment_properties (hb_buffer); - hb_shape (mHb_font, hb_buffer, NULL, 0); + hb_buffer_add_utf8(hb_buffer, _text.c_str(), -1, 0, -1); + hb_buffer_guess_segment_properties(hb_buffer); + hb_shape(mHb_font, hb_buffer, NULL, 0); - unsigned int textLen = 0; - hb_glyph_info_t *info = - hb_buffer_get_glyph_infos(hb_buffer,&textLen ); - CV_Assert( info != NULL ); + unsigned int textLen = 0; + hb_glyph_info_t *info = + hb_buffer_get_glyph_infos(hb_buffer, &textLen); + CV_Assert(info != NULL); #else - std::wstring_convert> converter; - wstring wstr = converter.from_bytes(_text); + std::wstring_convert> converter; + wstring wstr = converter.from_bytes(_text); #endif - _org.y += _fontHeight; - if( _bottomLeftOrigin == true ){ - _org.y -= _fontHeight; - } + _org.y += _fontHeight; + if (_bottomLeftOrigin == true) { + _org.y -= _fontHeight; + } - const uint8_t _colorUC8n[4] = { - static_cast(_color[0]), - static_cast(_color[1]), - static_cast(_color[2]), - static_cast(_color[3]) }; + const uint8_t _colorUC8n[4] = { + static_cast(_color[0]), + static_cast(_color[1]), + static_cast(_color[2]), + static_cast(_color[3]) }; - void (cv::ft::FreeType2Impl::*putPixel)( Mat&, const int, const int, const uint8_t*) = - (_img.type() == CV_8UC4)?(&FreeType2Impl::putPixel_8UC4_mono): - (_img.type() == CV_8UC3)?(&FreeType2Impl::putPixel_8UC3_mono): - (&FreeType2Impl::putPixel_8UC1_mono); + void (cv::ft::FreeType2Impl::*putPixel)(Mat&, const int, const int, const uint8_t*) = + (_img.type() == CV_8UC4) ? (&FreeType2Impl::putPixel_8UC4_mono) : + (_img.type() == CV_8UC3) ? (&FreeType2Impl::putPixel_8UC3_mono) : + (&FreeType2Impl::putPixel_8UC1_mono); #if defined(USING_HB) - for( unsigned int i = 0 ; i < textLen ; i ++ ){ - CV_Assert( !FT_Load_Glyph(mFace, info[i].codepoint, 0 ) ); + for (unsigned int i = 0; i < textLen; i++) { + CV_Assert(!FT_Load_Glyph(mFace, info[i].codepoint, 0)); #else - for( unsigned int i = 0 ; i < wstr.size() ; i ++ ){ - CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0 )); + for (unsigned int i = 0; i < wstr.size(); i++) { + CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0)); #endif - CV_Assert( !FT_Render_Glyph( mFace->glyph, FT_RENDER_MODE_MONO ) ); - FT_Bitmap *bmp = &(mFace->glyph->bitmap); - - Point gPos = _org; - gPos.y -= ( mFace->glyph->metrics.horiBearingY >> 6) ; - gPos.x += ( mFace->glyph->metrics.horiBearingX >> 6) ; - - for (int row = 0; row < (int)bmp->rows; row ++) { - if( gPos.y + row < 0 ) { - continue; - } - if( gPos.y + row >= dst.rows ) { - break; - } - - for (int col = 0; col < bmp->pitch; col ++) { - int cl = bmp->buffer[ row * bmp->pitch + col ]; - if ( cl == 0 ) { - continue; - } - for(int bit = 7; bit >= 0; bit -- ){ - if( gPos.x + col * 8 + (7 - bit) < 0 ) - { - continue; - } - if( gPos.x + col * 8 + (7 - bit) >= dst.cols ) - { - break; - } - - if ( ( (cl >> bit) & 0x01 ) == 1 ) { - (this->*putPixel)( dst, gPos.y + row, gPos.x + col * 8 + (7 - bit), _colorUC8n ); - } - } - } - } - - _org.x += ( mFace->glyph->advance.x ) >> 6; - _org.y += ( mFace->glyph->advance.y ) >> 6; - } + CV_Assert(!FT_Render_Glyph(mFace->glyph, FT_RENDER_MODE_MONO)); + FT_Bitmap *bmp = &(mFace->glyph->bitmap); + + Point gPos = _org; + gPos.y -= (mFace->glyph->metrics.horiBearingY >> 6); + gPos.x += (mFace->glyph->metrics.horiBearingX >> 6); + + for (int row = 0; row < (int)bmp->rows; row++) { + if (gPos.y + row < 0) { + continue; + } + if (gPos.y + row >= dst.rows) { + break; + } + + for (int col = 0; col < bmp->pitch; col++) { + int cl = bmp->buffer[row * bmp->pitch + col]; + if (cl == 0) { + continue; + } + for (int bit = 7; bit >= 0; bit--) { + if (gPos.x + col * 8 + (7 - bit) < 0) + { + continue; + } + if (gPos.x + col * 8 + (7 - bit) >= dst.cols) + { + break; + } + + if (((cl >> bit) & 0x01) == 1) { + (this->*putPixel)(dst, gPos.y + row, gPos.x + col * 8 + (7 - bit), _colorUC8n); + } + } + } + } + + _org.x += (mFace->glyph->advance.x) >> 6; + _org.y += (mFace->glyph->advance.y) >> 6; + } #if defined(USING_HB) - hb_buffer_destroy (hb_buffer); + hb_buffer_destroy(hb_buffer); #endif - } - -// Alpha composite algorithm is porting from imgproc. -// See https://github.com/opencv/opencv/blob/4.6.0/modules/imgproc/src/drawing.cpp -// static void LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) -// ICV_PUT_POINT Macro. - - void FreeType2Impl::putPixel_8UC1_blend( Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) - { - const int a = alpha; - const int cb = _col[0]; - uint8_t* tptr = _dst.ptr( _py, _px ); - - int _cb = static_cast(tptr[0]); - _cb += ((cb - _cb)*a + 127)>> 8; - _cb += ((cb - _cb)*a + 127)>> 8; - - tptr[0] = static_cast(_cb); - } - - void FreeType2Impl::putPixel_8UC3_blend ( Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) - { - const int a = alpha; - const int cb = _col[0]; - const int cg = _col[1]; - const int cr = _col[2]; - uint8_t* tptr = _dst.ptr( _py, _px ); - - int _cb = static_cast(tptr[0]); - _cb += ((cb - _cb)*a + 127)>> 8; - _cb += ((cb - _cb)*a + 127)>> 8; - - int _cg = static_cast(tptr[1]); - _cg += ((cg - _cg)*a + 127)>> 8; - _cg += ((cg - _cg)*a + 127)>> 8; - - int _cr = static_cast(tptr[2]); - _cr += ((cr - _cr)*a + 127)>> 8; - _cr += ((cr - _cr)*a + 127)>> 8; - - tptr[0] = static_cast(_cb); - tptr[1] = static_cast(_cg); - tptr[2] = static_cast(_cr); - } - - void FreeType2Impl::putPixel_8UC4_blend( Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) - { - const uint8_t a = alpha; - const int cb = _col[0]; - const int cg = _col[1]; - const int cr = _col[2]; - const int ca = _col[3]; - uint8_t* tptr = _dst.ptr( _py, _px ); - - int _cb = static_cast(tptr[0]); - _cb += ((cb - _cb)*a + 127)>> 8; - _cb += ((cb - _cb)*a + 127)>> 8; - - int _cg = static_cast(tptr[1]); - _cg += ((cg - _cg)*a + 127)>> 8; - _cg += ((cg - _cg)*a + 127)>> 8; - - int _cr = static_cast(tptr[2]); - _cr += ((cr - _cr)*a + 127)>> 8; - _cr += ((cr - _cr)*a + 127)>> 8; - - int _ca = static_cast(tptr[3]); - _ca += ((ca - _ca)*a + 127)>> 8; - _ca += ((ca - _ca)*a + 127)>> 8; - - tptr[0] = static_cast(_cb); - tptr[1] = static_cast(_cg); - tptr[2] = static_cast(_cr); - tptr[3] = static_cast(_ca); - } - - void FreeType2Impl::putTextBitmapBlend( - InputOutputArray _img, const String& _text, Point _org, - int _fontHeight, Scalar _color, - int _thickness, int _line_type, bool _bottomLeftOrigin ) - { - - CV_Assert( _thickness < 0 ); - CV_Assert( _line_type == LINE_AA ); - - Mat dst = _img.getMat(); + } + + // Alpha composite algorithm is porting from imgproc. + // See https://github.com/opencv/opencv/blob/4.6.0/modules/imgproc/src/drawing.cpp + // static void LineAA( Mat& img, Point2l pt1, Point2l pt2, const void* color ) + // ICV_PUT_POINT Macro. + + void FreeType2Impl::putPixel_8UC1_blend(Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) + { + const int a = alpha; + const int cb = _col[0]; + uint8_t* tptr = _dst.ptr(_py, _px); + + int _cb = static_cast(tptr[0]); + _cb += ((cb - _cb)*a + 127) >> 8; + _cb += ((cb - _cb)*a + 127) >> 8; + + tptr[0] = static_cast(_cb); + } + + void FreeType2Impl::putPixel_8UC3_blend(Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) + { + const int a = alpha; + const int cb = _col[0]; + const int cg = _col[1]; + const int cr = _col[2]; + uint8_t* tptr = _dst.ptr(_py, _px); + + int _cb = static_cast(tptr[0]); + _cb += ((cb - _cb)*a + 127) >> 8; + _cb += ((cb - _cb)*a + 127) >> 8; + + int _cg = static_cast(tptr[1]); + _cg += ((cg - _cg)*a + 127) >> 8; + _cg += ((cg - _cg)*a + 127) >> 8; + + int _cr = static_cast(tptr[2]); + _cr += ((cr - _cr)*a + 127) >> 8; + _cr += ((cr - _cr)*a + 127) >> 8; + + tptr[0] = static_cast(_cb); + tptr[1] = static_cast(_cg); + tptr[2] = static_cast(_cr); + } + + void FreeType2Impl::putPixel_8UC4_blend(Mat& _dst, const int _py, const int _px, const uint8_t *_col, const uint8_t alpha) + { + const uint8_t a = alpha; + const int cb = _col[0]; + const int cg = _col[1]; + const int cr = _col[2]; + const int ca = _col[3]; + uint8_t* tptr = _dst.ptr(_py, _px); + + int _cb = static_cast(tptr[0]); + _cb += ((cb - _cb)*a + 127) >> 8; + _cb += ((cb - _cb)*a + 127) >> 8; + + int _cg = static_cast(tptr[1]); + _cg += ((cg - _cg)*a + 127) >> 8; + _cg += ((cg - _cg)*a + 127) >> 8; + + int _cr = static_cast(tptr[2]); + _cr += ((cr - _cr)*a + 127) >> 8; + _cr += ((cr - _cr)*a + 127) >> 8; + + int _ca = static_cast(tptr[3]); + _ca += ((ca - _ca)*a + 127) >> 8; + _ca += ((ca - _ca)*a + 127) >> 8; + + tptr[0] = static_cast(_cb); + tptr[1] = static_cast(_cg); + tptr[2] = static_cast(_cr); + tptr[3] = static_cast(_ca); + } + + void FreeType2Impl::putTextBitmapBlend( + InputOutputArray _img, const String& _text, Point _org, + int _fontHeight, Scalar _color, + int _thickness, int _line_type, bool _bottomLeftOrigin) + { + + CV_Assert(_thickness < 0); + CV_Assert(_line_type == LINE_AA); + + Mat dst = _img.getMat(); #if defined(USING_HB) - hb_buffer_t *hb_buffer = hb_buffer_create (); - CV_Assert( hb_buffer != NULL ); + hb_buffer_t *hb_buffer = hb_buffer_create(); + CV_Assert(hb_buffer != NULL); - hb_buffer_add_utf8 (hb_buffer, _text.c_str(), -1, 0, -1); - hb_buffer_guess_segment_properties (hb_buffer); - hb_shape (mHb_font, hb_buffer, NULL, 0); + hb_buffer_add_utf8(hb_buffer, _text.c_str(), -1, 0, -1); + hb_buffer_guess_segment_properties(hb_buffer); + hb_shape(mHb_font, hb_buffer, NULL, 0); - unsigned int textLen = 0; - hb_glyph_info_t *info = - hb_buffer_get_glyph_infos(hb_buffer,&textLen ); - CV_Assert( info != NULL ); + unsigned int textLen = 0; + hb_glyph_info_t *info = + hb_buffer_get_glyph_infos(hb_buffer, &textLen); + CV_Assert(info != NULL); #else - std::wstring_convert> converter; - wstring wstr = converter.from_bytes(_text); + std::wstring_convert> converter; + wstring wstr = converter.from_bytes(_text); #endif - _org.y += _fontHeight; - if( _bottomLeftOrigin == true ){ - _org.y -= _fontHeight; - } + _org.y += _fontHeight; + if (_bottomLeftOrigin == true) { + _org.y -= _fontHeight; + } - const uint8_t _colorUC8n[4] = { - static_cast(_color[0]), - static_cast(_color[1]), - static_cast(_color[2]), - static_cast(_color[3]) }; + const uint8_t _colorUC8n[4] = { + static_cast(_color[0]), + static_cast(_color[1]), + static_cast(_color[2]), + static_cast(_color[3]) }; - void (cv::ft::FreeType2Impl::*putPixel)( Mat&, const int, const int, const uint8_t*, const uint8_t) = - (_img.type() == CV_8UC4)?(&FreeType2Impl::putPixel_8UC4_blend): - (_img.type() == CV_8UC3)?(&FreeType2Impl::putPixel_8UC3_blend): - (&FreeType2Impl::putPixel_8UC1_blend); + void (cv::ft::FreeType2Impl::*putPixel)(Mat&, const int, const int, const uint8_t*, const uint8_t) = + (_img.type() == CV_8UC4) ? (&FreeType2Impl::putPixel_8UC4_blend) : + (_img.type() == CV_8UC3) ? (&FreeType2Impl::putPixel_8UC3_blend) : + (&FreeType2Impl::putPixel_8UC1_blend); #if defined(USING_HB) - for( unsigned int i = 0 ; i < textLen ; i ++ ){ - CV_Assert( !FT_Load_Glyph(mFace, info[i].codepoint, 0 ) ); + for (unsigned int i = 0; i < textLen; i++) { + CV_Assert(!FT_Load_Glyph(mFace, info[i].codepoint, 0)); #else - for( unsigned int i = 0 ; i < wstr.size() ; i ++ ){ - CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0 )); + for (unsigned int i = 0; i < wstr.size(); i++) { + CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0)); #endif - CV_Assert( !FT_Render_Glyph( mFace->glyph, FT_RENDER_MODE_NORMAL ) ); - FT_Bitmap *bmp = &(mFace->glyph->bitmap); - - Point gPos = _org; - gPos.y -= ( mFace->glyph->metrics.horiBearingY >> 6) ; - gPos.x += ( mFace->glyph->metrics.horiBearingX >> 6) ; - - for (int row = 0; row < (int)bmp->rows; row ++) { - if( gPos.y + row < 0 ) { - continue; - } - if( gPos.y + row >= dst.rows ) { - break; - } - - for (int col = 0; col < bmp->pitch; col ++) { - uint8_t cl = bmp->buffer[ row * bmp->pitch + col ]; - if ( cl == 0 ) { - continue; - } - if( gPos.x + col < 0 ) - { - continue; - } - if( gPos.x + col >= dst.cols ) - { - break; - } - - (this->*putPixel)( dst, gPos.y + row, gPos.x + col, _colorUC8n, cl ); - } - } - _org.x += ( mFace->glyph->advance.x ) >> 6; - _org.y += ( mFace->glyph->advance.y ) >> 6; - } + CV_Assert(!FT_Render_Glyph(mFace->glyph, FT_RENDER_MODE_NORMAL)); + FT_Bitmap *bmp = &(mFace->glyph->bitmap); + + Point gPos = _org; + gPos.y -= (mFace->glyph->metrics.horiBearingY >> 6); + gPos.x += (mFace->glyph->metrics.horiBearingX >> 6); + + for (int row = 0; row < (int)bmp->rows; row++) { + if (gPos.y + row < 0) { + continue; + } + if (gPos.y + row >= dst.rows) { + break; + } + + for (int col = 0; col < bmp->pitch; col++) { + uint8_t cl = bmp->buffer[row * bmp->pitch + col]; + if (cl == 0) { + continue; + } + if (gPos.x + col < 0) + { + continue; + } + if (gPos.x + col >= dst.cols) + { + break; + } + + (this->*putPixel)(dst, gPos.y + row, gPos.x + col, _colorUC8n, cl); + } + } + _org.x += (mFace->glyph->advance.x) >> 6; + _org.y += (mFace->glyph->advance.y) >> 6; + } #if defined(USING_HB) - hb_buffer_destroy (hb_buffer); + hb_buffer_destroy(hb_buffer); #endif - } - - Size FreeType2Impl::getTextSize( - const String& _text, - int _fontHeight, - int _thickness, - CV_OUT int* _baseLine) - { - if ( _text.empty() ) - { - return Size(0,0); - } - - CV_Assert( _fontHeight >= 0 ) ; - if ( _fontHeight == 0 ) - { - return Size(0,0); - } - - CV_Assert(!FT_Set_Pixel_Sizes( mFace, _fontHeight, _fontHeight )); - - FT_Vector currentPos = {0,0}; + } + + Size FreeType2Impl::getTextSize( + const String& _text, + int _fontHeight, + int _thickness, + CV_OUT int* _baseLine) + { + if (_text.empty()) + { + return Size(0, 0); + } + + CV_Assert(_fontHeight >= 0); + if (_fontHeight == 0) + { + return Size(0, 0); + } + + CV_Assert(!FT_Set_Pixel_Sizes(mFace, _fontHeight, _fontHeight)); + + FT_Vector currentPos = { 0,0 }; #if defined(USING_HB) - hb_buffer_t *hb_buffer = hb_buffer_create (); - CV_Assert( hb_buffer != NULL ); + hb_buffer_t *hb_buffer = hb_buffer_create(); + CV_Assert(hb_buffer != NULL); - hb_buffer_add_utf8 (hb_buffer, _text.c_str(), -1, 0, -1); - hb_buffer_guess_segment_properties (hb_buffer); - hb_shape (mHb_font, hb_buffer, NULL, 0); + hb_buffer_add_utf8(hb_buffer, _text.c_str(), -1, 0, -1); + hb_buffer_guess_segment_properties(hb_buffer); + hb_shape(mHb_font, hb_buffer, NULL, 0); - unsigned int textLen = 0; - hb_glyph_info_t *info = - hb_buffer_get_glyph_infos(hb_buffer,&textLen ); - CV_Assert( info != NULL ); + unsigned int textLen = 0; + hb_glyph_info_t *info = + hb_buffer_get_glyph_infos(hb_buffer, &textLen); + CV_Assert(info != NULL); #else - std::wstring_convert> converter; - wstring wstr = converter.from_bytes(_text); + std::wstring_convert> converter; + wstring wstr = converter.from_bytes(_text); #endif - // Initilize BoundaryBox ( in OpenCV coordinates ) - int xMin = INT_MAX, yMin = INT_MAX; - int xMax = INT_MIN, yMax = INT_MIN; + // Initilize BoundaryBox ( in OpenCV coordinates ) + int xMin = INT_MAX, yMin = INT_MAX; + int xMax = INT_MIN, yMax = INT_MIN; #if defined(USING_HB) - for( unsigned int i = 0 ; i < textLen ; i ++ ){ - CV_Assert(!FT_Load_Glyph(mFace, info[i].codepoint, 0 )); + for (unsigned int i = 0; i < textLen; i++) { + CV_Assert(!FT_Load_Glyph(mFace, info[i].codepoint, 0)); #else - for( unsigned int i = 0 ; i < wstr.size() ; i ++ ){ - CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0 )); + for (unsigned int i = 0; i < wstr.size(); i++) { + CV_Assert(!FT_Load_Glyph(mFace, FT_Get_Char_Index(mFace, wstr[i]), 0)); #endif - FT_GlyphSlot slot = mFace->glyph; - FT_Outline outline = slot->outline; - FT_BBox bbox ; - - // Flip ( in FreeType coordinates ) - FT_Matrix mtx = { 1 << 16 , 0 , 0 , -(1 << 16) }; - FT_Outline_Transform(&outline, &mtx); - - // Move to current position ( in FreeType coordinates ) - FT_Outline_Translate(&outline, - currentPos.x, - currentPos.y ); - - // Get BoundaryBox ( in FreeType coordinatrs ) - CV_Assert( !FT_Outline_Get_BBox( &outline, &bbox ) ); - - // If codepoint is space(0x20), it has no glyph. - // A dummy boundary box is needed when last code is space. - if( - (bbox.xMin == 0 ) && (bbox.xMax == 0 ) && - (bbox.yMin == 0 ) && (bbox.yMax == 0 ) - ){ - bbox.xMin = currentPos.x ; - bbox.xMax = currentPos.x + ( mFace->glyph->advance.x ); - bbox.yMin = yMin; - bbox.yMax = yMax; - } - - // Update current position ( in FreeType coordinates ) - currentPos.x += mFace->glyph->advance.x; - currentPos.y += mFace->glyph->advance.y; - - // Update BoundaryBox ( in OpenCV coordinates ) - xMin = cv::min ( xMin, ftd(bbox.xMin) ); - xMax = cv::max ( xMax, ftd(bbox.xMax) ); - yMin = cv::min ( yMin, ftd(bbox.yMin) ); - yMax = cv::max ( yMax, ftd(bbox.yMax) ); - } + FT_GlyphSlot slot = mFace->glyph; + FT_Outline outline = slot->outline; + FT_BBox bbox; + + // Flip ( in FreeType coordinates ) + FT_Matrix mtx = { 1 << 16 , 0 , 0 , -(1 << 16) }; + FT_Outline_Transform(&outline, &mtx); + + // Move to current position ( in FreeType coordinates ) + FT_Outline_Translate(&outline, + currentPos.x, + currentPos.y); + + // Get BoundaryBox ( in FreeType coordinatrs ) + CV_Assert(!FT_Outline_Get_BBox(&outline, &bbox)); + + // If codepoint is space(0x20), it has no glyph. + // A dummy boundary box is needed when last code is space. + if ( + (bbox.xMin == 0) && (bbox.xMax == 0) && + (bbox.yMin == 0) && (bbox.yMax == 0) + ) { + bbox.xMin = currentPos.x; + bbox.xMax = currentPos.x + (mFace->glyph->advance.x); + bbox.yMin = yMin; + bbox.yMax = yMax; + } + + // Update current position ( in FreeType coordinates ) + currentPos.x += mFace->glyph->advance.x; + currentPos.y += mFace->glyph->advance.y; + + // Update BoundaryBox ( in OpenCV coordinates ) + xMin = cv::min(xMin, ftd(bbox.xMin)); + xMax = cv::max(xMax, ftd(bbox.xMax)); + yMin = cv::min(yMin, ftd(bbox.yMin)); + yMax = cv::max(yMax, ftd(bbox.yMax)); + } #if defined(USING_HB) - hb_buffer_destroy (hb_buffer); + hb_buffer_destroy(hb_buffer); #endif - // Calcurate width/height/baseline ( in OpenCV coordinates ) - int width = xMax - xMin ; - int height = -yMin ; - - if ( _thickness > 0 ) { - width = cvRound(width + _thickness * 2); - height = cvRound(height + _thickness * 1); - }else{ - width = cvRound(width + 1); - height = cvRound(height + 1); - } - - if ( _baseLine ) { - *_baseLine = yMax; - } - - return Size( width, height ); - } - - int FreeType2Impl::mvFn( const FT_Vector *to, void * user) - { - if(user == NULL ) { return 1; } - PathUserData *p = (PathUserData*)user; - - // Draw polylines( in OpenCV coordinates ). - if( p->mPts.size() > 0 ){ - Mat dst = p->mImg.getMat(); - const Point *ptsList[] = { &(p->mPts[0]) }; - int npt[1]; npt[0] = p->mPts.size(); - polylines( - dst, - ptsList, - npt, - 1, - false, - p->mColor, - p->mThickness, - p->mLine_type, - 0 - ); - } - - p->mPts.clear(); - - if( to == NULL ) { return 1; } - - // Store points to draw( in OpenCV coordinates ). - p->mPts.push_back( Point ( ftd(to->x), ftd(to->y) ) ); - p->mOldP = *to; - return 0; - } - - int FreeType2Impl::lnFn( const FT_Vector *to, void * user) - { - if(to == NULL ) { return 1; } - if(user == NULL ) { return 1; } - - PathUserData *p = (PathUserData *)user; - - // Store points to draw( in OpenCV coordinates ). - p->mPts.push_back( Point ( ftd(to->x), ftd(to->y) ) ); - p->mOldP = *to; - return 0; - } - - int FreeType2Impl::coFn( const FT_Vector *cnt, - const FT_Vector *to, - void * user) - { - if(cnt == NULL ) { return 1; } - if(to == NULL ) { return 1; } - if(user == NULL ) { return 1; } - - PathUserData *p = (PathUserData *)user; - - // Bezier to Line - for(int i = 0;i <= p->mCtoL; i++){ - // Split Bezier to lines ( in FreeType coordinates ). - double u = (double)i * 1.0 / (p->mCtoL) ; - double nu = 1.0 - u; - double p0 = nu * nu; - double p1 = 2.0 * u * nu; - double p2 = u * u; - - double X = (p->mOldP.x) * p0 + cnt->x * p1 + to->x * p2; - double Y = (p->mOldP.y) * p0 + cnt->y * p1 + to->y * p2; - - // Store points to draw( in OpenCV coordinates ). - p->mPts.push_back( Point ( ftd(X), ftd(Y) ) ); - } - p->mOldP = *to; - return 0; - } - - int FreeType2Impl::cuFn( const FT_Vector *cnt1, - const FT_Vector *cnt2, - const FT_Vector *to, - void * user) - { - if(cnt1 == NULL ) { return 1; } - if(cnt2 == NULL ) { return 1; } - if(to == NULL ) { return 1; } - if(user == NULL ) { return 1; } - - PathUserData *p = (PathUserData *)user; - - // Bezier to Line - for(int i = 0; i <= p->mCtoL ;i++){ - // Split Bezier to lines ( in FreeType coordinates ). - double u = (double)i * 1.0 / (p->mCtoL) ; - double nu = 1.0 - u; - double p0 = nu * nu * nu; - double p1 = 3.0 * u * nu * nu; - double p2 = 3.0 * u * u * nu; - double p3 = u * u * u; - - double X = (p->mOldP.x) * p0 + (cnt1->x) * p1 + - (cnt2->x ) * p2 + (to->x ) * p3; - double Y = (p->mOldP.y) * p0 + (cnt1->y) * p1 + - (cnt2->y ) * p2 + (to->y ) * p3; - - // Store points to draw( in OpenCV coordinates ). - p->mPts.push_back( Point ( ftd(X), ftd(Y) ) ); - } - p->mOldP = *to; - return 0; - } - - CV_EXPORTS_W Ptr createFreeType2() - { - return Ptr (new FreeType2Impl () ); - } - - -}} // namespace freetype2 + // Calcurate width/height/baseline ( in OpenCV coordinates ) + int width = xMax - xMin; + int height = -yMin; + + if (_thickness > 0) { + width = cvRound(width + _thickness * 2); + height = cvRound(height + _thickness * 1); + } + else { + width = cvRound(width + 1); + height = cvRound(height + 1); + } + + if (_baseLine) { + *_baseLine = yMax; + } + + return Size(width, height); + } + + int FreeType2Impl::mvFn(const FT_Vector *to, void * user) + { + if (user == NULL) { return 1; } + PathUserData *p = (PathUserData*)user; + + // Draw polylines( in OpenCV coordinates ). + if (p->mPts.size() > 0) { + Mat dst = p->mImg.getMat(); + const Point *ptsList[] = { &(p->mPts[0]) }; + int npt[1]; npt[0] = p->mPts.size(); + polylines( + dst, + ptsList, + npt, + 1, + false, + p->mColor, + p->mThickness, + p->mLine_type, + 0 + ); + } + + p->mPts.clear(); + + if (to == NULL) { return 1; } + + // Store points to draw( in OpenCV coordinates ). + p->mPts.push_back(Point(ftd(to->x), ftd(to->y))); + p->mOldP = *to; + return 0; + } + + int FreeType2Impl::lnFn(const FT_Vector *to, void * user) + { + if (to == NULL) { return 1; } + if (user == NULL) { return 1; } + + PathUserData *p = (PathUserData *)user; + + // Store points to draw( in OpenCV coordinates ). + p->mPts.push_back(Point(ftd(to->x), ftd(to->y))); + p->mOldP = *to; + return 0; + } + + int FreeType2Impl::coFn(const FT_Vector *cnt, + const FT_Vector *to, + void * user) + { + if (cnt == NULL) { return 1; } + if (to == NULL) { return 1; } + if (user == NULL) { return 1; } + + PathUserData *p = (PathUserData *)user; + + // Bezier to Line + for (int i = 0; i <= p->mCtoL; i++) { + // Split Bezier to lines ( in FreeType coordinates ). + double u = (double)i * 1.0 / (p->mCtoL); + double nu = 1.0 - u; + double p0 = nu * nu; + double p1 = 2.0 * u * nu; + double p2 = u * u; + + double X = (p->mOldP.x) * p0 + cnt->x * p1 + to->x * p2; + double Y = (p->mOldP.y) * p0 + cnt->y * p1 + to->y * p2; + + // Store points to draw( in OpenCV coordinates ). + p->mPts.push_back(Point(ftd(X), ftd(Y))); + } + p->mOldP = *to; + return 0; + } + + int FreeType2Impl::cuFn(const FT_Vector *cnt1, + const FT_Vector *cnt2, + const FT_Vector *to, + void * user) + { + if (cnt1 == NULL) { return 1; } + if (cnt2 == NULL) { return 1; } + if (to == NULL) { return 1; } + if (user == NULL) { return 1; } + + PathUserData *p = (PathUserData *)user; + + // Bezier to Line + for (int i = 0; i <= p->mCtoL; i++) { + // Split Bezier to lines ( in FreeType coordinates ). + double u = (double)i * 1.0 / (p->mCtoL); + double nu = 1.0 - u; + double p0 = nu * nu * nu; + double p1 = 3.0 * u * nu * nu; + double p2 = 3.0 * u * u * nu; + double p3 = u * u * u; + + double X = (p->mOldP.x) * p0 + (cnt1->x) * p1 + + (cnt2->x) * p2 + (to->x) * p3; + double Y = (p->mOldP.y) * p0 + (cnt1->y) * p1 + + (cnt2->y) * p2 + (to->y) * p3; + + // Store points to draw( in OpenCV coordinates ). + p->mPts.push_back(Point(ftd(X), ftd(Y))); + } + p->mOldP = *to; + return 0; + } + + CV_EXPORTS_W Ptr createFreeType2() + { + return Ptr(new FreeType2Impl()); + } + + + } + } // namespace freetype2