Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@razaqq
Copy link
Contributor

@razaqq razaqq commented Oct 30, 2023

There currently is no way to load a freetype font from a memory buffer (for example embedded resources etc). This small PR adds a simple function adding that functionality.

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@razaqq razaqq force-pushed the freetype_loadFontData branch from e4d776b to b2bb3d6 Compare October 30, 2023 16:24
@param idx face_index to select a font faces in a single file.
*/

CV_WRAP virtual void loadFontData(uchar* pBuf, size_t bufSize, int idx) = 0;
Copy link
Contributor

@Kumataro Kumataro Oct 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix compile error for pyhton-binding error, it maybe better to use char* instead of uchar*.

mIsFaceAvailable = false;
CV_Assert( !FT_New_Face( mLibrary, fontFileName.c_str(), static_cast<FT_Long>(idx), &(mFace) ) );
FT_Open_Args args{ FT_OPEN_MEMORY, (FT_Byte*)pBuf, static_cast<FT_Long>(bufSize), nullptr, nullptr, nullptr, 0, nullptr };
CV_Assert( !FT_Open_Face(mLibrary, &args, idx, &mFace) );
Copy link
Contributor

@Kumataro Kumataro Oct 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two functions reference different Freetype APIs. It would be better to have one or the other in common.

  • Idea1) To use FT_Open_Face() for file and memory.
    • both functrions construct FT_Open_Args for file and memory.
    • new helper function receives FT_Open_Args and idx.
  • Idea2) To use FT_New_Face() for file, and to use FT_New_Memory_Face() for memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs for FT_New_Face and docs for FT_New_Memory_Face say explicitly to use FT_Open_Face for both loading from file or buffer. My PR was specific to adding more functionality, so i didnt want to change old code in the same PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your comment. It is OK. I think there is no problem.
In this pull-request, the FreeType function to be called was switched with an additional commit, so I confirmed the intention. thank you very much !!

}

void FreeType2Impl::loadFontData(uchar* pBuf, size_t bufSize, int idx)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think to check pBuf and bufSize is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but i do not want to assert.
i think both loading functions should return a result indicating if the loading was successful.
loading from file is an inherently failable i/o operation, so asserting there is very bad practice imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why the loadFontData() function has no return value is because there is no way to recover if this function fails. If this function returns some errors, I believe it is difficult/hard to do anything. Is it better to continue with missing drawing ?

And If an inappropriate/invalid argument is set, it would be better to use CV_Assert() to indicate that there is a problem with the user program implementation/calling.

  • If pBuf == nullptr and/or bufSize == 0 are invalid input. (We can omit to check bufSize.)
  • In other case, if pBuf[0...bufSize] are invalid/broken font data, we expects Face_Open_args() will be return with failed. It will be captured with CV_Assert().
  • In other case if pBug[] buffer is smaller than bufSize, we cannot do anything. Only what we can do is user-application handle it correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could recover by trying to load another font. A lot of cpp programs (including all of mine) have exceptions disabled, by asserting you remove their option to handle it in a way they want to. If a user wants to, he can still assert the return value

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think it is difficult to use another/alternative fonts.
  • Cases where header data is corrupted can be caught at loadFontData() stage. This is a case where clearly incorrect data such as image data is specified.
  • Cases where glyph data is corrupted cannot be caught until the putText() stage, which reads and renders the glyph data.(When glyph data of A is broken, if A is not contained strings for putText(), there are no problem.)

With your design, that means if putText() failed, we should re-call loadFontData() with another font and retry to call putText(). I think it is too complex.

  1. Exception handling is a prerequisite for using OpenCV. Following is OpenCV Introduction Error Handling Section section.

OpenCV uses exceptions to signal critical errors. When the input data has a correct format and belongs to the specified value range, but the algorithm cannot succeed for some reason.

@Kumataro
Copy link
Contributor

I believe to add some test is required to merge it. ( Opencv-extra contains font data. )
Please could you try on modules/freetype/test/ codes ?

@asmorkalov
Copy link
Contributor

@razaqq Friendly reminder.

@asmorkalov
Copy link
Contributor

@Kumataro I already added simple test for the new method.

@Kumataro
Copy link
Contributor

Thank you for your comment.

I created a patch on my own repository based on razaqq's repository and created a pull request ( #3593 ).

However, maybe I was able to commit directly to razaqq's repository?
In that case my pull request is unnecessary/redundant. I'm sorry if I'm wrong.

@asmorkalov asmorkalov merged commit 9e71621 into opencv:4.x Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants