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

Skip to content

Commit 4230469

Browse files
committed
Cleanup wrapper
1 parent e868fbc commit 4230469

File tree

4 files changed

+413
-75
lines changed

4 files changed

+413
-75
lines changed

src/forward.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
struct PyFT2Font;
4+
5+
class FT2Font;

src/ft2font.cpp

Lines changed: 196 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,12 @@ FT2Font::get_path()
325325

326326
FT2Font::FT2Font(FT_Open_Args &open_args,
327327
long hinting_factor_,
328-
std::vector<FT2Font *> &fallback_list)
328+
std::vector<FT2Font *> &fallback_list,
329+
PyFT2Font *py_pointer)
329330
: image(), face(NULL)
330331
{
331332
clear();
333+
py_font = py_pointer;
332334

333335
FT_Error error = FT_Open_Face(_ft2Library, &open_args, 0, &face);
334336

@@ -372,12 +374,9 @@ FT2Font::~FT2Font()
372374
}
373375

374376
if (face) {
377+
printf("Deleting face from: %lu\n", face->num_glyphs);
375378
FT_Done_Face(face);
376379
}
377-
378-
for (uint i = 0; i < fallbacks.size(); i ++) {
379-
fallbacks[i]->~FT2Font();
380-
}
381380
}
382381

383382
void FT2Font::clear()
@@ -390,6 +389,8 @@ void FT2Font::clear()
390389
}
391390

392391
glyphs.clear();
392+
glyph_to_font.clear();
393+
char_to_font.clear();
393394

394395
for (uint i = 0; i < fallbacks.size(); i ++) {
395396
fallbacks[i]->clear();
@@ -435,8 +436,19 @@ void FT2Font::select_charmap(unsigned long i)
435436
}
436437
}
437438

438-
int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode)
439+
int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, bool fallback = false)
439440
{
441+
if (fallback && glyph_to_font.find(left) != glyph_to_font.end() &&
442+
glyph_to_font.find(right) != glyph_to_font.end()) {
443+
FT2Font *left_ft_object = glyph_to_font[left];
444+
FT2Font *right_ft_object = glyph_to_font[right];
445+
if (left_ft_object != right_ft_object) {
446+
printf("Prev FT2Font != Curr FT2Font!\n");
447+
}
448+
// if left_ft_object is not the same the right_ft_object,
449+
// do the exact same thing which set_text does.
450+
return right_ft_object->get_kerning(left, right, mode, false);
451+
}
440452
if (!FT_HAS_KERNING(face)) {
441453
return 0;
442454
}
@@ -499,11 +511,12 @@ void FT2Font::set_text(
499511
FT_UInt final_glyph_index;
500512
FT_Error charcode_error, glyph_error;
501513
FT2Font *ft_object_with_glyph = this;
502-
load_char_with_fallback(ft_object_with_glyph, final_glyph_index, glyphs, codepoints[n],
503-
flags, charcode_error, glyph_error);
504-
if (charcode_error || glyph_error) {
514+
bool was_found = load_char_with_fallback(ft_object_with_glyph, final_glyph_index, glyphs,
515+
char_to_font, glyph_to_font, codepoints[n], flags,
516+
charcode_error, glyph_error, false);
517+
if (!was_found) {
505518
ft_glyph_warn((FT_ULong)codepoints[n]);
506-
return;
519+
continue;
507520
}
508521

509522
glyph_index = final_glyph_index;
@@ -544,50 +557,175 @@ void FT2Font::set_text(
544557
}
545558
}
546559

547-
void FT2Font::load_char(long charcode, FT_Int32 flags)
560+
void FT2Font::fill_glyphs(
561+
size_t N, uint32_t *codepoints, double angle, FT_Int32 flags, bool warn = false)
548562
{
549-
FT_UInt glyph_index = ft_get_char_index_or_warn(face, (FT_ULong)charcode);
550-
if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) {
551-
throw_ft_error("Could not load charcode", error);
563+
FT_Matrix matrix; /* transformation matrix */
564+
565+
angle = angle / 360.0 * 2 * M_PI;
566+
567+
// this computes width and height in subpixels so we have to divide by 64
568+
matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
569+
matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
570+
matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
571+
matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);
572+
573+
FT_Bool use_kerning = FT_HAS_KERNING(face);
574+
FT_UInt previous = 0;
575+
576+
clear();
577+
578+
bbox.xMin = bbox.yMin = 32000;
579+
bbox.xMax = bbox.yMax = -32000;
580+
581+
for (unsigned int n = 0; n < N; n++) {
582+
FT_UInt glyph_index;
583+
FT_BBox glyph_bbox;
584+
FT_Pos last_advance;
585+
586+
FT_UInt final_glyph_index;
587+
FT_Error charcode_error, glyph_error;
588+
FT2Font *ft_object_with_glyph = this;
589+
bool was_found = load_char_with_fallback(ft_object_with_glyph, final_glyph_index, glyphs,
590+
char_to_font, glyph_to_font, codepoints[n], flags,
591+
charcode_error, glyph_error, false);
592+
if (!was_found) {
593+
if (warn) ft_glyph_warn((FT_ULong)codepoints[n]);
594+
continue;
595+
}
596+
597+
glyph_index = final_glyph_index;
598+
599+
// retrieve kerning distance and move pen position
600+
if (use_kerning && previous && glyph_index) {
601+
FT_Vector delta;
602+
ft_object_with_glyph->get_kerning(previous, glyph_index, FT_KERNING_DEFAULT, delta);
603+
pen.x += delta.x / (hinting_factor << kerning_factor);
604+
}
605+
606+
// extract glyph image and store it in our table
607+
608+
FT_Glyph &thisGlyph = glyphs[glyphs.size() - 1];
609+
610+
last_advance = ft_object_with_glyph->get_face()->glyph->advance.x;
611+
FT_Glyph_Transform(thisGlyph, 0, &pen);
612+
FT_Glyph_Transform(thisGlyph, &matrix, 0);
613+
614+
FT_Glyph_Get_CBox(thisGlyph, FT_GLYPH_BBOX_SUBPIXELS, &glyph_bbox);
615+
616+
bbox.xMin = std::min(bbox.xMin, glyph_bbox.xMin);
617+
bbox.xMax = std::max(bbox.xMax, glyph_bbox.xMax);
618+
bbox.yMin = std::min(bbox.yMin, glyph_bbox.yMin);
619+
bbox.yMax = std::max(bbox.yMax, glyph_bbox.yMax);
620+
621+
pen.x += last_advance;
622+
623+
previous = glyph_index;
552624
}
553-
FT_Glyph thisGlyph;
554-
if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) {
555-
throw_ft_error("Could not get glyph", error);
625+
626+
FT_Vector_Transform(&pen, &matrix);
627+
advance = pen.x;
628+
629+
if (bbox.xMin > bbox.xMax) {
630+
bbox.xMin = bbox.yMin = bbox.xMax = bbox.yMax = 0;
556631
}
557-
glyphs.push_back(thisGlyph);
558632
}
559633

560-
void FT2Font::load_char_with_fallback(FT2Font* &ft_object_with_glyph,
634+
void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool fallback = false)
635+
{
636+
// if this is parent FT2Font, cache will be filled in 2 ways:
637+
// 1. set_text was previously called
638+
// 2. set_text was not called and fallback was enabled
639+
if (fallback && char_to_font.find(charcode) != char_to_font.end()) {
640+
ft_object = char_to_font[charcode];
641+
// since it will be assigned to this object anyway
642+
FT2Font *throwaway = NULL;
643+
ft_object->load_char(charcode, flags, throwaway, false);
644+
} else if (fallback) {
645+
FT_UInt final_glyph_index;
646+
FT_Error charcode_error, glyph_error;
647+
FT2Font *ft_object_with_glyph = this;
648+
bool was_found = load_char_with_fallback(ft_object_with_glyph, final_glyph_index, glyphs, char_to_font,
649+
glyph_to_font, charcode, flags, charcode_error, glyph_error, true);
650+
if (!was_found) {
651+
ft_glyph_warn(charcode);
652+
if (charcode_error) throw_ft_error("Could not load charcode", charcode_error);
653+
else if (glyph_error) throw_ft_error("Could not load charcode", glyph_error);
654+
}
655+
ft_object = ft_object_with_glyph;
656+
} else {
657+
ft_object = this;
658+
FT_UInt glyph_index = ft_get_char_index_or_warn(face, (FT_ULong)charcode);
659+
660+
if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) {
661+
throw_ft_error("Could not load charcode", error);
662+
}
663+
FT_Glyph thisGlyph;
664+
if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) {
665+
throw_ft_error("Could not get glyph", error);
666+
}
667+
glyphs.push_back(thisGlyph);
668+
}
669+
}
670+
671+
bool FT2Font::load_char_with_fallback(FT2Font *&ft_object_with_glyph,
561672
FT_UInt &final_glyph_index,
562673
std::vector<FT_Glyph> &parent_glyphs,
674+
std::unordered_map<long, FT2Font *> &parent_char_to_font,
675+
std::unordered_map<FT_UInt, FT2Font *> &parent_glyph_to_font,
563676
long charcode,
564677
FT_Int32 flags,
565678
FT_Error &charcode_error,
566-
FT_Error &glyph_error)
679+
FT_Error &glyph_error,
680+
bool override = false)
567681
{
568682
FT_UInt glyph_index = FT_Get_Char_Index(face, charcode);
569683

570-
if (glyph_index) {
684+
if (glyph_index || override) {
571685
charcode_error = FT_Load_Glyph(face, glyph_index, flags);
572686
FT_Glyph thisGlyph;
573687
glyph_error = FT_Get_Glyph(face->glyph, &thisGlyph);
688+
689+
if (charcode_error || glyph_error) {
690+
return false;
691+
}
574692
final_glyph_index = glyph_index;
693+
694+
// cache the result for future
695+
// need to store this for anytime a character is loaded from a parent
696+
// FT2Font object or to generate a mapping of individual characters to fonts
697+
ft_object_with_glyph = this;
698+
parent_glyph_to_font[final_glyph_index] = this;
699+
parent_char_to_font[charcode] = this;
575700
parent_glyphs.push_back(thisGlyph);
701+
return true;
576702
}
577703

578704
else {
579705
for (uint i = 0; i < fallbacks.size(); ++i) {
580-
uint current_size = parent_glyphs.size();
581-
fallbacks[i]->load_char_with_fallback(ft_object_with_glyph, final_glyph_index,
582-
parent_glyphs, charcode, flags, charcode_error,
583-
glyph_error);
584-
// jump out if glyph size increased
585-
if (parent_glyphs.size() == current_size + 1) {
586-
ft_object_with_glyph = fallbacks[i];
587-
return;
588-
}
706+
bool was_found = fallbacks[i]->load_char_with_fallback(
707+
ft_object_with_glyph, final_glyph_index, parent_glyphs, parent_char_to_font,
708+
parent_glyph_to_font, charcode, flags, charcode_error, glyph_error, override);
709+
if (was_found)
710+
return true;
589711
}
712+
return false;
713+
}
714+
}
715+
716+
void FT2Font::load_glyph(FT_UInt glyph_index,
717+
FT_Int32 flags,
718+
FT2Font *&ft_object,
719+
bool fallback = false)
720+
{
721+
// cache is only for parent FT2Font
722+
if (fallback && glyph_to_font.find(glyph_index) != glyph_to_font.end()) {
723+
ft_object = glyph_to_font[glyph_index];
724+
} else {
725+
ft_object = this;
590726
}
727+
728+
ft_object->load_glyph(glyph_index, flags);
591729
}
592730

593731
void FT2Font::load_glyph(FT_UInt glyph_index, FT_Int32 flags)
@@ -602,6 +740,27 @@ void FT2Font::load_glyph(FT_UInt glyph_index, FT_Int32 flags)
602740
glyphs.push_back(thisGlyph);
603741
}
604742

743+
FT_UInt FT2Font::get_char_index(FT_ULong charcode, bool fallback = false)
744+
{
745+
FT2Font *ft_object = NULL;
746+
if (fallback && char_to_font.find(charcode) != char_to_font.end()) {
747+
// fallback denotes whether we want to search fallback list.
748+
// should call set_text/load_char_with_fallback to parent FT2Font before
749+
// wanting to use fallback list here. (since that populates the cache)
750+
ft_object = char_to_font[charcode];
751+
} else {
752+
// set as self
753+
ft_object = this;
754+
}
755+
756+
return ft_get_char_index_or_warn(ft_object->get_face(), charcode);
757+
}
758+
759+
void FT2Font::get_cbox(FT_BBox &bbox)
760+
{
761+
FT_Glyph_Get_CBox(glyphs.back(), ft_glyph_bbox_subpixels, &bbox);
762+
}
763+
605764
void FT2Font::get_width_height(long *width, long *height)
606765
{
607766
*width = advance;
@@ -692,8 +851,14 @@ void FT2Font::draw_glyph_to_bitmap(FT2Image &im, int x, int y, size_t glyphInd,
692851
im.draw_bitmap(&bitmap->bitmap, x + bitmap->left, y);
693852
}
694853

695-
void FT2Font::get_glyph_name(unsigned int glyph_number, char *buffer)
854+
void FT2Font::get_glyph_name(unsigned int glyph_number, char *buffer, bool fallback = false)
696855
{
856+
if (fallback && glyph_to_font.find(glyph_number) != glyph_to_font.end()) {
857+
// cache is only for parent FT2Font
858+
FT2Font *ft_object = glyph_to_font[glyph_number];
859+
ft_object->get_glyph_name(glyph_number, buffer, false);
860+
return;
861+
}
697862
if (!FT_HAS_GLYPH_NAMES(face)) {
698863
/* Note that this generated name must match the name that
699864
is generated by ttconv in ttfont_CharStrings_getname. */

0 commit comments

Comments
 (0)