mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Merge pull request #333 from wiredfool/paddywwoof-truetype
Vertical Alignment of ttf rendering
This commit is contained in:
		
						commit
						dea45dafcb
					
				| 
						 | 
					@ -102,6 +102,8 @@ def getcolor(color, mode):
 | 
				
			||||||
    if mode == "RGB":
 | 
					    if mode == "RGB":
 | 
				
			||||||
        return color
 | 
					        return color
 | 
				
			||||||
    if mode == "RGBA":
 | 
					    if mode == "RGBA":
 | 
				
			||||||
 | 
					        if len(color) == 3:
 | 
				
			||||||
 | 
					          color = (color + (255,))
 | 
				
			||||||
        r, g, b, a = color
 | 
					        r, g, b, a = color
 | 
				
			||||||
        return r, g, b, a
 | 
					        return r, g, b, a
 | 
				
			||||||
    if Image.getmodebase(mode) == "L":
 | 
					    if Image.getmodebase(mode) == "L":
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,6 +157,9 @@ class FreeTypeFont:
 | 
				
			||||||
    def getsize(self, text):
 | 
					    def getsize(self, text):
 | 
				
			||||||
        return self.font.getsize(text)[0]
 | 
					        return self.font.getsize(text)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getoffset(self, text):
 | 
				
			||||||
 | 
					        return self.font.getsize(text)[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getmask(self, text, mode=""):
 | 
					    def getmask(self, text, mode=""):
 | 
				
			||||||
        return self.getmask2(text, mode)[0]
 | 
					        return self.getmask2(text, mode)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,7 +186,7 @@ class TransposedFont:
 | 
				
			||||||
        self.orientation = orientation # any 'transpose' argument, or None
 | 
					        self.orientation = orientation # any 'transpose' argument, or None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getsize(self, text):
 | 
					    def getsize(self, text):
 | 
				
			||||||
        w, h = self.font.getsize(text)
 | 
					        w, h = self.font.getsize(text)[0]
 | 
				
			||||||
        if self.orientation in (Image.ROTATE_90, Image.ROTATE_270):
 | 
					        if self.orientation in (Image.ROTATE_90, Image.ROTATE_270):
 | 
				
			||||||
            return h, w
 | 
					            return h, w
 | 
				
			||||||
        return w, h
 | 
					        return w, h
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/multiline_text.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/multiline_text.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.8 KiB  | 
| 
						 | 
					@ -35,7 +35,7 @@ def test_font_with_filelike():
 | 
				
			||||||
    #shared_bytes = _font_as_bytes()
 | 
					    #shared_bytes = _font_as_bytes()
 | 
				
			||||||
    #assert_no_exception(lambda: _render(shared_bytes))
 | 
					    #assert_no_exception(lambda: _render(shared_bytes))
 | 
				
			||||||
    #assert_exception(Exception, lambda: _render(shared_bytes))
 | 
					    #assert_exception(Exception, lambda: _render(shared_bytes))
 | 
				
			||||||
    _clean
 | 
					    _clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_font_with_open_file():
 | 
					def test_font_with_open_file():
 | 
				
			||||||
    with open(font_path, 'rb') as f:
 | 
					    with open(font_path, 'rb') as f:
 | 
				
			||||||
| 
						 | 
					@ -67,3 +67,21 @@ def test_render_equal():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_image_equal(img_path, img_filelike)
 | 
					    assert_image_equal(img_path, img_filelike)
 | 
				
			||||||
    _clean()
 | 
					    _clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_render_multiline():
 | 
				
			||||||
 | 
					    im = Image.new(mode='RGB', size=(300,100))
 | 
				
			||||||
 | 
					    ttf = ImageFont.truetype(font_path, font_size)
 | 
				
			||||||
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					    line_spacing = draw.textsize('A', font=ttf)[1] + 8
 | 
				
			||||||
 | 
					    lines = ['hey you', 'you are awesome', 'this looks awkward']
 | 
				
			||||||
 | 
					    y = 0
 | 
				
			||||||
 | 
					    for line in lines:
 | 
				
			||||||
 | 
					        draw.text((0, y), line, font=ttf)
 | 
				
			||||||
 | 
					        y += line_spacing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    target = 'Tests/images/multiline_text.png'
 | 
				
			||||||
 | 
					    target_img = Image.open(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert_image_equal(im, target_img)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								_imagingft.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								_imagingft.c
									
									
									
									
									
								
							| 
						 | 
					@ -183,7 +183,7 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
    int i, x, y_max, y_min;
 | 
					    int i, x, y_max, y_min;
 | 
				
			||||||
    FT_ULong ch;
 | 
					    FT_ULong ch;
 | 
				
			||||||
    FT_Face face;
 | 
					    FT_Face face;
 | 
				
			||||||
    int xoffset;
 | 
					    int xoffset, yoffset;
 | 
				
			||||||
    FT_Bool kerning = FT_HAS_KERNING(self->face);
 | 
					    FT_Bool kerning = FT_HAS_KERNING(self->face);
 | 
				
			||||||
    FT_UInt last_index = 0;
 | 
					    FT_UInt last_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,7 +203,7 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    face = NULL;
 | 
					    face = NULL;
 | 
				
			||||||
    xoffset = 0;
 | 
					    xoffset = yoffset = 0;
 | 
				
			||||||
    y_max = y_min = 0;
 | 
					    y_max = y_min = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (x = i = 0; font_getchar(string, i, &ch); i++) {
 | 
					    for (x = i = 0; font_getchar(string, i, &ch); i++) {
 | 
				
			||||||
| 
						 | 
					@ -232,6 +232,10 @@ 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 */
 | 
				
			||||||
 | 
					        if (face->glyph->metrics.horiBearingY > yoffset)
 | 
				
			||||||
 | 
					            yoffset = face->glyph->metrics.horiBearingY;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
        last_index = index;
 | 
					        last_index = index;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -248,12 +252,15 @@ font_getsize(FontObject* self, PyObject* args)
 | 
				
			||||||
            face->glyph->metrics.horiBearingX;
 | 
					            face->glyph->metrics.horiBearingX;
 | 
				
			||||||
        if (offset < 0)
 | 
					        if (offset < 0)
 | 
				
			||||||
            x -= offset;
 | 
					            x -= offset;
 | 
				
			||||||
 | 
					        /* difference between the font ascender and the distance of
 | 
				
			||||||
 | 
					         * the baseline from the top */
 | 
				
			||||||
 | 
					        yoffset = PIXEL(self->face->size->metrics.ascender - yoffset);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Py_BuildValue(
 | 
					    return Py_BuildValue(
 | 
				
			||||||
        "(ii)(ii)",
 | 
					        "(ii)(ii)",
 | 
				
			||||||
        PIXEL(x), PIXEL(y_max - y_min),
 | 
					        PIXEL(x), PIXEL(y_max - y_min),
 | 
				
			||||||
        PIXEL(xoffset), 0
 | 
					        PIXEL(xoffset), yoffset
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user