mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Corrected ttb text positioning
This commit is contained in:
		
							parent
							
								
									169961649d
								
							
						
					
					
						commit
						1c1447f563
					
				| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NotoNastaliqUrdu-Regular.ttf:
 | 
					NotoNastaliqUrdu-Regular.ttf, from https://github.com/googlei18n/noto-fonts
 | 
				
			||||||
 | 
					NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/
 | 
				
			||||||
(from https://github.com/googlei18n/noto-fonts)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
All Noto fonts are published under the SIL Open Font License (OFL) v1.1 (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL), which allows you to copy, modify, and redistribute them if you need to.
 | 
					All Noto fonts are published under the SIL Open Font License (OFL) v1.1 (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL), which allows you to copy, modify, and redistribute them if you need to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/fonts/NotoSansJP-Regular.otf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/fonts/NotoSansJP-Regular.otf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Tests/images/test_direction_ttb.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/test_direction_ttb.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.7 KiB  | 
| 
						 | 
					@ -104,6 +104,22 @@ class TestImagecomplextext(PillowTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assert_image_similar(im, target_img, .5)
 | 
					        self.assert_image_similar(im, target_img, .5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_text_direction_ttb(self):
 | 
				
			||||||
 | 
					        ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        im = Image.new(mode='RGB', size=(100, 300))
 | 
				
			||||||
 | 
					        draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            draw.text((0, 0), 'English あい', font=ttf, fill=500, direction='ttb')
 | 
				
			||||||
 | 
					        except ValueError as ex:
 | 
				
			||||||
 | 
					            if str(ex) == "libraqm 0.6 or greater required for 'ttb' direction":
 | 
				
			||||||
 | 
					                self.skipTest('libraqm 0.6 or greater not available')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        target = 'Tests/images/test_direction_ttb.png'
 | 
				
			||||||
 | 
					        target_img = Image.open(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assert_image_similar(im, target_img, 1.15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ligature_features(self):
 | 
					    def test_ligature_features(self):
 | 
				
			||||||
        ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					        ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										159
									
								
								src/_imagingft.c
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								src/_imagingft.c
									
									
									
									
									
								
							| 
						 | 
					@ -54,7 +54,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int index, x_offset, x_advance, y_offset;
 | 
					  int index, x_offset, x_advance, y_offset, y_advance;
 | 
				
			||||||
  unsigned int cluster;
 | 
					  unsigned int cluster;
 | 
				
			||||||
} GlyphInfo;
 | 
					} GlyphInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,9 +407,17 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject *
 | 
				
			||||||
            direction = RAQM_DIRECTION_RTL;
 | 
					            direction = RAQM_DIRECTION_RTL;
 | 
				
			||||||
        else if (strcmp(dir, "ltr") == 0)
 | 
					        else if (strcmp(dir, "ltr") == 0)
 | 
				
			||||||
            direction = RAQM_DIRECTION_LTR;
 | 
					            direction = RAQM_DIRECTION_LTR;
 | 
				
			||||||
        else if (strcmp(dir, "ttb") == 0)
 | 
					        else if (strcmp(dir, "ttb") == 0) {
 | 
				
			||||||
            direction = RAQM_DIRECTION_TTB;
 | 
					            direction = RAQM_DIRECTION_TTB;
 | 
				
			||||||
        else {
 | 
					#if !defined(_MSC_VER)
 | 
				
			||||||
 | 
					            if (!dlsym(p_raqm.raqm, "raqm_set_invisible_glyph")) {
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            if (!GetProcAddress(p_raqm.raqm, "raqm_set_invisible_glyph")) {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                PyErr_SetString(PyExc_ValueError, "libraqm 0.6 or greater required for 'ttb' direction");
 | 
				
			||||||
 | 
					                goto failed;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            PyErr_SetString(PyExc_ValueError, "direction must be either 'rtl', 'ltr' or 'ttb'");
 | 
					            PyErr_SetString(PyExc_ValueError, "direction must be either 'rtl', 'ltr' or 'ttb'");
 | 
				
			||||||
            goto failed;
 | 
					            goto failed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -502,6 +510,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject *
 | 
				
			||||||
            (*glyph_info)[i].x_offset = glyphs_01[i].x_offset;
 | 
					            (*glyph_info)[i].x_offset = glyphs_01[i].x_offset;
 | 
				
			||||||
            (*glyph_info)[i].x_advance = glyphs_01[i].x_advance;
 | 
					            (*glyph_info)[i].x_advance = glyphs_01[i].x_advance;
 | 
				
			||||||
            (*glyph_info)[i].y_offset = glyphs_01[i].y_offset;
 | 
					            (*glyph_info)[i].y_offset = glyphs_01[i].y_offset;
 | 
				
			||||||
 | 
					            (*glyph_info)[i].y_advance = glyphs_01[i].y_advance;
 | 
				
			||||||
            (*glyph_info)[i].cluster = glyphs_01[i].cluster;
 | 
					            (*glyph_info)[i].cluster = glyphs_01[i].cluster;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -510,6 +519,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject *
 | 
				
			||||||
            (*glyph_info)[i].x_offset = glyphs[i].x_offset;
 | 
					            (*glyph_info)[i].x_offset = glyphs[i].x_offset;
 | 
				
			||||||
            (*glyph_info)[i].x_advance = glyphs[i].x_advance;
 | 
					            (*glyph_info)[i].x_advance = glyphs[i].x_advance;
 | 
				
			||||||
            (*glyph_info)[i].y_offset = glyphs[i].y_offset;
 | 
					            (*glyph_info)[i].y_offset = glyphs[i].y_offset;
 | 
				
			||||||
 | 
					            (*glyph_info)[i].y_advance = glyphs[i].y_advance;
 | 
				
			||||||
            (*glyph_info)[i].cluster = glyphs[i].cluster;
 | 
					            (*glyph_info)[i].cluster = glyphs[i].cluster;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -576,9 +586,11 @@ text_layout_fallback(PyObject* string, FontObject* self, const char* dir, PyObje
 | 
				
			||||||
            if (FT_Get_Kerning(self->face, last_index, (*glyph_info)[i].index,
 | 
					            if (FT_Get_Kerning(self->face, last_index, (*glyph_info)[i].index,
 | 
				
			||||||
                           ft_kerning_default,&delta) == 0)
 | 
					                           ft_kerning_default,&delta) == 0)
 | 
				
			||||||
            (*glyph_info)[i-1].x_advance += PIXEL(delta.x);
 | 
					            (*glyph_info)[i-1].x_advance += PIXEL(delta.x);
 | 
				
			||||||
 | 
					            (*glyph_info)[i-1].y_advance += PIXEL(delta.y);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        (*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
 | 
					        (*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
 | 
				
			||||||
 | 
					        (*glyph_info)[i].y_advance = glyph->metrics.vertAdvance;
 | 
				
			||||||
        last_index = (*glyph_info)[i].index;
 | 
					        last_index = (*glyph_info)[i].index;
 | 
				
			||||||
        (*glyph_info)[i].cluster = ch;
 | 
					        (*glyph_info)[i].cluster = ch;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -602,9 +614,10 @@ text_layout(PyObject* string, FontObject* self, const char* dir, PyObject *featu
 | 
				
			||||||
static PyObject*
 | 
					static PyObject*
 | 
				
			||||||
font_getsize(FontObject* self, PyObject* args)
 | 
					font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int x, y_max, y_min;
 | 
					    int x_max, x_min, y_max, y_min;
 | 
				
			||||||
    FT_Face face;
 | 
					    FT_Face face;
 | 
				
			||||||
    int xoffset, yoffset;
 | 
					    int xoffset, yoffset;
 | 
				
			||||||
 | 
					    int horizontal_dir;
 | 
				
			||||||
    const char *dir = NULL;
 | 
					    const char *dir = NULL;
 | 
				
			||||||
    const char *lang = NULL;
 | 
					    const char *lang = NULL;
 | 
				
			||||||
    size_t i, count;
 | 
					    size_t i, count;
 | 
				
			||||||
| 
						 | 
					@ -619,15 +632,15 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    face = NULL;
 | 
					    face = NULL;
 | 
				
			||||||
    xoffset = yoffset = 0;
 | 
					    xoffset = yoffset = 0;
 | 
				
			||||||
    y_max = y_min = 0;
 | 
					    x_max = x_min = y_max = y_min = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    count = text_layout(string, self, dir, features, lang, &glyph_info, 0);
 | 
					    count = text_layout(string, self, dir, features, lang, &glyph_info, 0);
 | 
				
			||||||
    if (PyErr_Occurred()) {
 | 
					    if (PyErr_Occurred()) {
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
 | 
				
			||||||
    for (x = i = 0; i < count; i++) {
 | 
					    for (i = 0; i < count; i++) {
 | 
				
			||||||
        int index, error;
 | 
					        int index, error;
 | 
				
			||||||
        FT_BBox bbox;
 | 
					        FT_BBox bbox;
 | 
				
			||||||
        FT_Glyph glyph;
 | 
					        FT_Glyph glyph;
 | 
				
			||||||
| 
						 | 
					@ -640,25 +653,35 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
        if (error)
 | 
					        if (error)
 | 
				
			||||||
            return geterror(error);
 | 
					            return geterror(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (i == 0 && face->glyph->metrics.horiBearingX < 0) {
 | 
					        if (i == 0) {
 | 
				
			||||||
 | 
					            if (horizontal_dir) {
 | 
				
			||||||
 | 
					                if (face->glyph->metrics.horiBearingX < 0) {
 | 
				
			||||||
                    xoffset = face->glyph->metrics.horiBearingX;
 | 
					                    xoffset = face->glyph->metrics.horiBearingX;
 | 
				
			||||||
            x -= xoffset;
 | 
					                    x_max -= xoffset;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                if (face->glyph->metrics.vertBearingY < 0) {
 | 
				
			||||||
 | 
					                    yoffset = face->glyph->metrics.vertBearingY;
 | 
				
			||||||
 | 
					                    y_max -= yoffset;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        x += glyph_info[i].x_advance;
 | 
					        FT_Get_Glyph(face->glyph, &glyph);
 | 
				
			||||||
 | 
					        FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_SUBPIXELS, &bbox);
 | 
				
			||||||
 | 
					        if (horizontal_dir) {
 | 
				
			||||||
 | 
					            x_max += glyph_info[i].x_advance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (i == count - 1)
 | 
					            if (i == count - 1) {
 | 
				
			||||||
        {
 | 
					                // trim end gap from final glyph
 | 
				
			||||||
                int offset;
 | 
					                int offset;
 | 
				
			||||||
                offset = glyph_info[i].x_advance -
 | 
					                offset = glyph_info[i].x_advance -
 | 
				
			||||||
                        face->glyph->metrics.width -
 | 
					                        face->glyph->metrics.width -
 | 
				
			||||||
                        face->glyph->metrics.horiBearingX;
 | 
					                        face->glyph->metrics.horiBearingX;
 | 
				
			||||||
                if (offset < 0)
 | 
					                if (offset < 0)
 | 
				
			||||||
                x -= offset;
 | 
					                    x_max -= offset;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FT_Get_Glyph(face->glyph, &glyph);
 | 
					 | 
				
			||||||
        FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_SUBPIXELS, &bbox);
 | 
					 | 
				
			||||||
            bbox.yMax -= glyph_info[i].y_offset;
 | 
					            bbox.yMax -= glyph_info[i].y_offset;
 | 
				
			||||||
            bbox.yMin -= glyph_info[i].y_offset;
 | 
					            bbox.yMin -= glyph_info[i].y_offset;
 | 
				
			||||||
            if (bbox.yMax > y_max)
 | 
					            if (bbox.yMax > y_max)
 | 
				
			||||||
| 
						 | 
					@ -666,9 +689,27 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
            if (bbox.yMin < y_min)
 | 
					            if (bbox.yMin < y_min)
 | 
				
			||||||
                y_min = bbox.yMin;
 | 
					                y_min = bbox.yMin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* find max distance of baseline from top */
 | 
					            // find max distance of baseline from top
 | 
				
			||||||
            if (face->glyph->metrics.horiBearingY > yoffset)
 | 
					            if (face->glyph->metrics.horiBearingY > yoffset)
 | 
				
			||||||
                yoffset = face->glyph->metrics.horiBearingY;
 | 
					                yoffset = face->glyph->metrics.horiBearingY;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            y_max -= glyph_info[i].y_advance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (i == count - 1) {
 | 
				
			||||||
 | 
					                // trim end gap from final glyph
 | 
				
			||||||
 | 
					                int offset;
 | 
				
			||||||
 | 
					                offset = -glyph_info[i].y_advance -
 | 
				
			||||||
 | 
					                        face->glyph->metrics.height -
 | 
				
			||||||
 | 
					                        face->glyph->metrics.vertBearingY;
 | 
				
			||||||
 | 
					                if (offset < 0)
 | 
				
			||||||
 | 
					                    y_max -= offset;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (bbox.xMax > x_max)
 | 
				
			||||||
 | 
					                x_max = bbox.xMax;
 | 
				
			||||||
 | 
					            if (i == 0 || bbox.xMin < x_min)
 | 
				
			||||||
 | 
					                x_min = bbox.xMin;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FT_Done_Glyph(glyph);
 | 
					        FT_Done_Glyph(glyph);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -679,20 +720,28 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (face) {
 | 
					    if (face) {
 | 
				
			||||||
 | 
					        if (horizontal_dir) {
 | 
				
			||||||
        /* left bearing */
 | 
					            // left bearing
 | 
				
			||||||
            if (xoffset < 0)
 | 
					            if (xoffset < 0)
 | 
				
			||||||
            x -= xoffset;
 | 
					                x_max -= xoffset;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                xoffset = 0;
 | 
					                xoffset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* difference between the font ascender and the distance of
 | 
					            /* difference between the font ascender and the distance of
 | 
				
			||||||
             * the baseline from the top */
 | 
					             * the baseline from the top */
 | 
				
			||||||
            yoffset = PIXEL(self->face->size->metrics.ascender - yoffset);
 | 
					            yoffset = PIXEL(self->face->size->metrics.ascender - yoffset);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // top bearing
 | 
				
			||||||
 | 
					            if (yoffset < 0)
 | 
				
			||||||
 | 
					                y_max -= yoffset;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                yoffset = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Py_BuildValue(
 | 
					    return Py_BuildValue(
 | 
				
			||||||
        "(ii)(ii)",
 | 
					        "(ii)(ii)",
 | 
				
			||||||
        PIXEL(x), PIXEL(y_max - y_min),
 | 
					        PIXEL(x_max - x_min), PIXEL(y_max - y_min),
 | 
				
			||||||
        PIXEL(xoffset), yoffset
 | 
					        PIXEL(xoffset), yoffset
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -703,7 +752,7 @@ font_render(FontObject* self, PyObject* args)
 | 
				
			||||||
    int x;
 | 
					    int x;
 | 
				
			||||||
    unsigned int y;
 | 
					    unsigned int y;
 | 
				
			||||||
    Imaging im;
 | 
					    Imaging im;
 | 
				
			||||||
    int index, error, ascender;
 | 
					    int index, error, ascender, horizontal_dir;
 | 
				
			||||||
    int load_flags;
 | 
					    int load_flags;
 | 
				
			||||||
    unsigned char *source;
 | 
					    unsigned char *source;
 | 
				
			||||||
    FT_GlyphSlot glyph;
 | 
					    FT_GlyphSlot glyph;
 | 
				
			||||||
| 
						 | 
					@ -714,6 +763,8 @@ font_render(FontObject* self, PyObject* args)
 | 
				
			||||||
    int mask = 0;
 | 
					    int mask = 0;
 | 
				
			||||||
    int temp;
 | 
					    int temp;
 | 
				
			||||||
    int xx, x0, x1;
 | 
					    int xx, x0, x1;
 | 
				
			||||||
 | 
					    int yy;
 | 
				
			||||||
 | 
					    unsigned int bitmap_y;
 | 
				
			||||||
    const char *dir = NULL;
 | 
					    const char *dir = NULL;
 | 
				
			||||||
    const char *lang = NULL;
 | 
					    const char *lang = NULL;
 | 
				
			||||||
    size_t i, count;
 | 
					    size_t i, count;
 | 
				
			||||||
| 
						 | 
					@ -747,27 +798,34 @@ font_render(FontObject* self, PyObject* args)
 | 
				
			||||||
            return geterror(error);
 | 
					            return geterror(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glyph = self->face->glyph;
 | 
					        glyph = self->face->glyph;
 | 
				
			||||||
        temp = (glyph->bitmap.rows - glyph->bitmap_top);
 | 
					        temp = glyph->bitmap.rows - glyph->bitmap_top;
 | 
				
			||||||
        temp -= PIXEL(glyph_info[i].y_offset);
 | 
					        temp -= PIXEL(glyph_info[i].y_offset);
 | 
				
			||||||
        if (temp > ascender)
 | 
					        if (temp > ascender)
 | 
				
			||||||
            ascender = temp;
 | 
					            ascender = temp;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (x = i = 0; i < count; i++) {
 | 
					    x = y = 0;
 | 
				
			||||||
 | 
					    horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
 | 
				
			||||||
 | 
					    for (i = 0; i < count; i++) {
 | 
				
			||||||
        index = glyph_info[i].index;
 | 
					        index = glyph_info[i].index;
 | 
				
			||||||
        error = FT_Load_Glyph(self->face, index, load_flags);
 | 
					        error = FT_Load_Glyph(self->face, index, load_flags);
 | 
				
			||||||
        if (error)
 | 
					        if (error)
 | 
				
			||||||
            return geterror(error);
 | 
					            return geterror(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        glyph = self->face->glyph;
 | 
				
			||||||
 | 
					        if (horizontal_dir) {
 | 
				
			||||||
            if (i == 0 && self->face->glyph->metrics.horiBearingX < 0) {
 | 
					            if (i == 0 && self->face->glyph->metrics.horiBearingX < 0) {
 | 
				
			||||||
                x = -self->face->glyph->metrics.horiBearingX;
 | 
					                x = -self->face->glyph->metrics.horiBearingX;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        glyph = self->face->glyph;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        source = (unsigned char*) glyph->bitmap.buffer;
 | 
					 | 
				
			||||||
            xx = PIXEL(x) + glyph->bitmap_left;
 | 
					            xx = PIXEL(x) + glyph->bitmap_left;
 | 
				
			||||||
            xx += PIXEL(glyph_info[i].x_offset);
 | 
					            xx += PIXEL(glyph_info[i].x_offset);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (self->face->glyph->metrics.vertBearingX < 0) {
 | 
				
			||||||
 | 
					                x = -self->face->glyph->metrics.vertBearingX;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            xx = im->xsize / 2 - glyph->bitmap.width / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        x0 = 0;
 | 
					        x0 = 0;
 | 
				
			||||||
        x1 = glyph->bitmap.width;
 | 
					        x1 = glyph->bitmap.width;
 | 
				
			||||||
        if (xx < 0)
 | 
					        if (xx < 0)
 | 
				
			||||||
| 
						 | 
					@ -775,45 +833,42 @@ font_render(FontObject* self, PyObject* args)
 | 
				
			||||||
        if (xx + x1 > im->xsize)
 | 
					        if (xx + x1 > im->xsize)
 | 
				
			||||||
            x1 = im->xsize - xx;
 | 
					            x1 = im->xsize - xx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (mask) {
 | 
					        source = (unsigned char*) glyph->bitmap.buffer;
 | 
				
			||||||
            /* use monochrome mask (on palette images, etc) */
 | 
					        for (bitmap_y = 0; bitmap_y < glyph->bitmap.rows; bitmap_y++) {
 | 
				
			||||||
            for (y = 0; y < glyph->bitmap.rows; y++) {
 | 
					            if (horizontal_dir) {
 | 
				
			||||||
                int yy = y + im->ysize - (PIXEL(glyph->metrics.horiBearingY) + ascender);
 | 
					                yy = bitmap_y + im->ysize - (PIXEL(glyph->metrics.horiBearingY) + ascender);
 | 
				
			||||||
                yy -= PIXEL(glyph_info[i].y_offset);
 | 
					                yy -= PIXEL(glyph_info[i].y_offset);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                yy = bitmap_y + PIXEL(y + glyph->metrics.vertBearingY) + ascender;
 | 
				
			||||||
 | 
					                yy += PIXEL(glyph_info[i].y_offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (yy >= 0 && yy < im->ysize) {
 | 
					            if (yy >= 0 && yy < im->ysize) {
 | 
				
			||||||
                    /* blend this glyph into the buffer */
 | 
					                // blend this glyph into the buffer
 | 
				
			||||||
                unsigned char *target = im->image8[yy] + xx;
 | 
					                unsigned char *target = im->image8[yy] + xx;
 | 
				
			||||||
                    int i, j, m = 128;
 | 
					                if (mask) {
 | 
				
			||||||
                    for (i = j = 0; j < x1; j++) {
 | 
					                    // use monochrome mask (on palette images, etc)
 | 
				
			||||||
                        if (j >= x0 && (source[i] & m))
 | 
					                    int j, k, m = 128;
 | 
				
			||||||
 | 
					                    for (j = k = 0; j < x1; j++) {
 | 
				
			||||||
 | 
					                        if (j >= x0 && (source[k] & m))
 | 
				
			||||||
                            target[j] = 255;
 | 
					                            target[j] = 255;
 | 
				
			||||||
                        if (!(m >>= 1)) {
 | 
					                        if (!(m >>= 1)) {
 | 
				
			||||||
                            m = 128;
 | 
					                            m = 128;
 | 
				
			||||||
                            i++;
 | 
					                            k++;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                source += glyph->bitmap.pitch;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
            /* use antialiased rendering */
 | 
					                    // use antialiased rendering
 | 
				
			||||||
            for (y = 0; y < glyph->bitmap.rows; y++) {
 | 
					                    int k;
 | 
				
			||||||
                int yy = y + im->ysize - (PIXEL(glyph->metrics.horiBearingY) + ascender);
 | 
					                    for (k = x0; k < x1; k++) {
 | 
				
			||||||
                yy -= PIXEL(glyph_info[i].y_offset);
 | 
					                        if (target[k] < source[k])
 | 
				
			||||||
                if (yy >= 0 && yy < im->ysize) {
 | 
					                            target[k] = source[k];
 | 
				
			||||||
                    /* blend this glyph into the buffer */
 | 
					                    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    int i;
 | 
					 | 
				
			||||||
                    unsigned char *target = im->image8[yy] + xx;
 | 
					 | 
				
			||||||
                    for (i = x0; i < x1; i++) {
 | 
					 | 
				
			||||||
                        if (target[i] < source[i])
 | 
					 | 
				
			||||||
                            target[i] = source[i];
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            source += glyph->bitmap.pitch;
 | 
					            source += glyph->bitmap.pitch;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        x += glyph_info[i].x_advance;
 | 
					        x += glyph_info[i].x_advance;
 | 
				
			||||||
 | 
					        y -= glyph_info[i].y_advance;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PyMem_Del(glyph_info);
 | 
					    PyMem_Del(glyph_info);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user