Ticket #3436: 0001-Use-pango-to-handle-fonts-SL-3436.2.patch
File 0001-Use-pango-to-handle-fonts-SL-3436.2.patch, 16.1 KB (added by humitos, 12 years ago) |
---|
-
globos.py
From 46388275ef5604c61f65a182608ed38b0fcbe3a5 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann <humitos@gmail.com> Date: Thu, 7 Jun 2012 14:52:28 -0300 Subject: [PATCH v2 FotoToon] Use pango to handle fonts SL #3436 I changed the way that the fonts were handled to use pango and pangocairo because we needed the ability to set the dpi of the screen to render the font size properly in the XO. Because of it is a big change i has some regression issues: - 'Up' and 'Down' keys do not work to move between text lines - The user's cursor is not shown when a globe text is being edited - The ability to expand just vertically the globe doesn't work Signed-off-by: Manuel Kaufmann <humitos@gmail.com> --- globos.py | 217 ++++++++++---------------------------------------- historietaactivity.py | 25 +++++- persistencia.py | 4 - 3 files changed, 68 insertions(+), 178 deletions(-) diff --git a/globos.py b/globos.py index fc927c5..a53f6ac 100644
a b 1 # -*- coding: UTF-8 -*-1 # -*- coding: utf-8 -*- 2 2 3 3 import os 4 4 import math 5 5 import gtk 6 6 import cairo 7 import pango 7 8 8 9 from sugar.activity import activity 9 10 from sugar.graphics.icon import _IconBuffer … … class Globo: 165 166 def set_texto(self, key, keyval, context, rect): 166 167 self.texto.insertar_texto(key, keyval, context) 167 168 self.calc_area(self.texto.ancho, self.texto.alto) 168 if self.y - self.alto <= 0 or self.y + self.alto >= rect.height:169 #si se redimensiono significa que crecio en un renglon170 #y verifica si entra en cuadro si no es asi deshace la accion171 self.texto.deshacer(context)172 self.calc_area(self.texto.ancho, self.texto.alto)173 169 174 170 def mover_a(self, x, y, rect): 175 171 if self.dx + x > (self.ancho): … … class Globo: 315 311 alto_ant = self.alto 316 312 ancho_ant = self.ancho 317 313 314 # FIXME: here should be possible to increase the globe size 315 # just vertically. 316 318 317 # if I am changing the size from the right or from the bottom 319 318 # change x / y to calculate like if changing from 320 319 # top and left … … class CuadroTexto: 798 797 self.x = x 799 798 self.y = y 800 799 801 self.texto = None800 self.texto = '' 802 801 #Posicion del cursor(en nro de caracteres) 803 802 self.cursor = 0 804 803 … … class CuadroTexto: 808 807 self.color_r, self.color_g, self.color_b = 0, 0, 0 809 808 self.italic = False 810 809 self.bold = False 810 self.font_description = pango.FontDescription() 811 self.font_description.set_family(font_name) 811 812 812 813 #Tamanio del renglon 813 814 self.alto_renglon = 12 … … class CuadroTexto: 818 819 #Dibujar o no el cursor 819 820 self.mostrar_cursor = False 820 821 821 #texto en cada renglon822 self.renglones = []823 # 1 =el renglon i termino con un espacio824 # 0= el renglon i no termino con espacio825 self.esp_reg = []826 827 822 # Lo uso para acentuar letras con comilla simple 828 823 self.double_key = None 829 824 830 825 def set_text(self, text): 831 826 self.texto = text 832 self.renglones = self.texto.split('\r')833 for i in range(len(self.renglones)):834 self.esp_reg.append(0)835 827 self.cursor = len(text) 836 828 837 829 def imprimir(self, context): … … class CuadroTexto: 844 836 context.stroke() 845 837 846 838 # Insertando el texto 847 s lant = cairo.FONT_SLANT_NORMAL839 style = pango.STYLE_NORMAL 848 840 if self.italic: 849 s lant = cairo.FONT_SLANT_ITALIC850 weight = cairo.FONT_WEIGHT_NORMAL841 style = pango.STYLE_ITALIC 842 weight = pango.WEIGHT_NORMAL 851 843 if self.bold: 852 weight = cairo.FONT_WEIGHT_BOLD 853 854 context.select_font_face(self.font_type, slant, weight) 855 context.set_font_size(self.font_size) 856 857 if self.texto: 858 cursor_dib = self.cursor # dibujar cursor 859 860 for i in range(len(self.renglones)): 861 #text_reng = unicode(self.renglones[i],'UTF8') 862 text_reng = self.renglones[i] 863 xbearing, ybearing, width, height, xadvance, yadvance = \ 864 context.text_extents(self.renglones[i].replace(" ", "-")) 865 866 context.move_to(self.x - width / 2 - 1, 867 self.y - self.alto + (i + 1) * self.alto_renglon) 868 context.set_source_rgb(self.color_r, self.color_g, 869 self.color_b) 870 context.show_text(self.renglones[i]) 871 872 if self.mostrar_cursor: 873 if cursor_dib >= len(text_reng) + self.esp_reg[i]: 874 cursor_dib -= (len(text_reng) + self.esp_reg[i]) 875 876 elif cursor_dib != -99: 877 try: 878 xbearing1, ybearing1, width1, \ 879 height1, xadvance1, yadvance1 = \ 880 context.text_extents( \ 881 text_reng[0:cursor_dib].replace(" ", "-")) 882 context.move_to(self.x - width / 2 - 1 + width1, 883 self.y - self.alto + \ 884 (i + 1) * self.alto_renglon) 885 context.show_text("_") 886 # para que no lo vuelva a dibujar en otro renglon 887 cursor_dib = - 99 888 except: 889 print "ERROR", \ 890 text_reng[0:cursor_dib].replace(" ", "-") 891 892 elif self.mostrar_cursor: 893 context.move_to(self.x, self.y - self.alto + self.alto_renglon) 894 context.set_source_rgb(0, 0, 0) 895 context.show_text("_") 896 844 weight = pango.WEIGHT_BOLD 845 self.font_description.set_family(self.font_type) 846 self.font_description.set_weight(weight) 847 self.font_description.set_style(style) 848 self.font_description.set_size(self.font_size * pango.SCALE) 849 850 text = self.texto 851 852 self.layout = context.create_layout() 853 self.layout.set_font_description(self.font_description) 854 self.layout.set_wrap(pango.WRAP_WORD_CHAR) 855 self.layout.set_alignment(pango.ALIGN_CENTER) 856 self.layout.set_width(int(self.ancho) * pango.SCALE * 2) 857 self.layout.set_single_paragraph_mode(False) 858 self.layout.set_text(text) 859 860 drawn, logical = self.layout.get_extents() 861 width = logical[2] / float(pango.SCALE) 862 height = logical[3] / float(pango.SCALE) 863 context.move_to(self.x - self.ancho, 864 self.y - self.alto) 865 866 # FIXME: the old version (that used just cairo to handle 867 # fonts) had the ability to show where was the user's cursor 868 # position with a "_" 869 870 context.show_layout(self.layout) 897 871 context.stroke() 898 872 899 873 def insertar_texto(self, key, keyval, context): … … class CuadroTexto: 953 927 self.cursor -= 1 954 928 955 929 elif keyval == gtk.gdk.keyval_from_name('Up'): 930 # FIXME: we are handling lines from pango directly so 931 # we didn't know in which line is the user's cursor 956 932 sum_ren = 0 957 933 #se averigua en que renglon esta el cursor 958 for i in range(len(self.renglones)):959 if sum_ren <= self.cursor < \960 (sum_ren + len(self.renglones[i]) + self.esp_reg[i]):961 if i != 0:962 #calculo desplazamiento dentro de un renglon963 cur_ren = self.cursor - sum_ren964 self.cursor = \965 min(sum_ren - len(self.renglones[i - 1])966 - self.esp_reg[i - 1] + \967 cur_ren, sum_ren - 1)968 break969 else:970 sum_ren += (len(self.renglones[i]) + self.esp_reg[i])971 934 972 935 elif keyval == gtk.gdk.keyval_from_name('Down'): 936 # FIXME: we are handling lines from pango directly so 937 # we didn't know in which line is the user's cursor 973 938 sum_ren = 0 974 939 #se averigua en que renglon esta el cursor 975 for i in range(len(self.renglones)):976 if sum_ren <= self.cursor < (sum_ren +977 len(self.renglones[i]) + self.esp_reg[i]):978 if i != len(self.renglones) - 1:979 #calculo desplazamiento dentro de un renglon980 cur_ren = self.cursor - sum_ren981 self.cursor = min(sum_ren + \982 len(self.renglones[i]) + \983 self.esp_reg[i] + cur_ren, \984 sum_ren + len(self.renglones[i]) + \985 self.esp_reg[i] + \986 len(self.renglones[i + 1]) + \987 self.esp_reg[i + 1] - 1)988 break989 else:990 sum_ren += (len(self.renglones[i]) + self.esp_reg[i])991 940 992 941 else: 993 942 agregar = unicode(key, 'UTF8') … … class CuadroTexto: 1007 956 """ 1008 957 1009 958 def redimensionar(self, context): 1010 pass1011 959 """ 1012 960 Establece el texto en cada renglon dependiendo de las dimensiones 1013 961 del cuadro, manteniendo fijo el ancho, 1014 962 y redimensionando el alto si es necesario 1015 963 """ 1016 1017 if self.texto is not None: 1018 1019 texto_oracion = self.texto.split("\n") 1020 1021 self.renglones = [] # texto en cada renglon 1022 self.esp_reg = [] # 1=indica si el renglon termino con un espacio. 1023 1024 for j in range(len(texto_oracion)): 1025 1026 texto_renglon = texto_oracion[j] 1027 1028 while texto_renglon is not None: 1029 1030 for i in range(len(texto_renglon.split(" "))): 1031 1032 xbearing, ybearing, width, height, \ 1033 xadvance, yadvance = \ 1034 context.text_extents( \ 1035 texto_renglon.rsplit(" ", i)[0].replace(" ", "-")) 1036 # es remplazado " " por "-" para que pueda calcular 1037 # el ancho considerando los 1038 # espacios (el caracter - tiene el mismo ancho 1039 # que el espacio) 1040 1041 if width <= self.ancho * 2: 1042 1043 self.renglones.append(texto_renglon.rsplit(" ", \ 1044 i)[0]) 1045 self.esp_reg.append(1) 1046 1047 if i != 0: 1048 posi_space = len(texto_renglon.split(" ")) 1049 texto_renglon = \ 1050 texto_renglon.split(" ", 1051 posi_space - i)[posi_space - i] 1052 else: 1053 texto_renglon = None 1054 break 1055 1056 elif i == (len(texto_renglon.split(" ")) - 1): 1057 #este es el caso que no entra ni una palabra 1058 1059 #tiene problemas de performance:se podria mejorar 1060 #empezando desde la izq 1061 1062 palabra = (texto_renglon.rsplit(" ", i)[0]) 1063 if i != 0: 1064 posi_space = len(texto_renglon.split(" ")) 1065 texto_renglon = " " + \ 1066 texto_renglon.split(" ", 1067 posi_space - i)[posi_space - i] 1068 else: 1069 texto_renglon = "" 1070 1071 for k in range(1, len(palabra)): 1072 xbearing, ybearing, width, height, \ 1073 xadvance, yadvance = \ 1074 context.text_extents( \ 1075 palabra[:len(palabra) - k]) 1076 if width <= self.ancho * 2: 1077 self.renglones.append( \ 1078 palabra[:len(palabra) - k]) 1079 self.esp_reg.append(0) 1080 texto_renglon = \ 1081 palabra[len(palabra) - k:len(palabra)] + \ 1082 texto_renglon 1083 break 1084 1085 if len(self.renglones) * self.alto_renglon > self.alto * 2: 1086 self.alto = len(self.renglones) * self.alto_renglon / 2 964 width, height = self.layout.get_pixel_size() 965 self.alto = height / 2 1087 966 1088 967 def mover_a(self, x, y): 1089 968 "Mueve el centro del cuadro a la posicion (x,y)" … … class CuadroTexto: 1098 977 """ 1099 978 self.ancho = ancho 1100 979 self.alto = alto 1101 1102 def deshacer(self, context):1103 "Se utiliza para deshacer la creacion de un nuevo renglon de texto"1104 self.texto = self.texto[0:self.cursor - 1] + \1105 self.texto[self.cursor:len(self.texto)]1106 self.cursor -= 11107 self.alto -= self.alto_renglon1108 self.redimensionar(context) -
historietaactivity.py
diff --git a/historietaactivity.py b/historietaactivity.py index f46567d..27add5b 100644
a b 1 # -*- coding: UTF-8 -*-1 # -*- coding: utf-8 -*- 2 2 3 3 import os 4 4 import gtk 5 5 import cairo 6 import pangocairo 6 7 7 8 import globos 8 9 import persistencia … … import dbus 28 29 import logging 29 30 30 31 32 def _get_screen_dpi(): 33 xft_dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') 34 dpi = float(xft_dpi / 1024) 35 logging.debug('Setting dpi to: %f', dpi) 36 # HACK: if the DPI detected is 200.0 it seems we are on an XO, so 37 # we return 133 because the XO manage its resolution in a complex 38 # way. More information here: 39 # http://wiki.laptop.org/go/Display 40 if 200 == int(dpi): 41 return 133 42 return dpi 43 44 31 45 class HistorietaActivity(activity.Activity): 32 46 33 47 _EXPORT_FORMATS = [['image/png', _('Save as Image'), _('PNG'), ""]] … … class HistorietaActivity(activity.Activity): 97 111 98 112 self.page.empty_page = handle.object_id is None 99 113 114 # This is needed because of the Globes Font Size 115 # http://bugs.sugarlabs.org/ticket/3436 116 self._set_screen_dpi() 117 100 118 #print "screen witdh " , SCREEN_WIDTH 101 119 #print "page witdh " , self.page.size_request() 102 120 … … class HistorietaActivity(activity.Activity): 275 293 preview_data = ''.join(preview_data) 276 294 return dbus.ByteArray(preview_data) 277 295 296 def _set_screen_dpi(self): 297 dpi = _get_screen_dpi() 298 font_map_default = pangocairo.cairo_font_map_get_default() 299 font_map_default.set_resolution(dpi) 300 278 301 DEF_SPACING = 6 279 302 DEF_WIDTH = 4 280 303 -
persistencia.py
diff --git a/persistencia.py b/persistencia.py index f8d62c1..a67b19d 100644
a b class Persistence: 65 65 globoData['text_x'], globoData['text_y'] = \ 66 66 globo.texto.x, globo.texto.y 67 67 globoData['text_text'] = globo.texto.texto 68 globoData['text_rows'] = globo.texto.renglones69 globoData['text_sp_rows'] = globo.texto.esp_reg70 68 71 69 globoData['text_row_height'] = globo.texto.alto_renglon 72 70 globoData['text_font_size'] = globo.texto.font_size … … class Persistence: 183 181 globo.texto.x, globo.texto.y = globoData['text_x'], \ 184 182 globoData['text_y'] 185 183 globo.texto.texto = globoData['text_text'] 186 globo.texto.renglones = globoData['text_rows']187 globo.texto.esp_reg = globoData['text_sp_rows']188 184 189 185 globo.texto.alto_renglon = globoData['text_row_height'] 190 186 globo.texto.font_size = globoData['text_font_size']