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 -*-
    22
    33import os
    44import math
    55import gtk
    66import cairo
     7import pango
    78
    89from sugar.activity import activity
    910from sugar.graphics.icon import _IconBuffer
    class Globo: 
    165166    def set_texto(self, key, keyval, context, rect):
    166167        self.texto.insertar_texto(key, keyval, context)
    167168        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 renglon
    170             #y verifica si entra en cuadro si no es asi deshace la accion
    171             self.texto.deshacer(context)
    172             self.calc_area(self.texto.ancho, self.texto.alto)
    173169
    174170    def mover_a(self, x, y, rect):
    175171        if self.dx + x > (self.ancho):
    class Globo: 
    315311        alto_ant = self.alto
    316312        ancho_ant = self.ancho
    317313
     314        # FIXME: here should be possible to increase the globe size
     315        # just vertically.
     316
    318317        # if I am changing the size from the right or from the bottom
    319318        # change x / y to calculate like if changing from
    320319        # top and left
    class CuadroTexto: 
    798797        self.x = x
    799798        self.y = y
    800799
    801         self.texto = None
     800        self.texto = ''
    802801        #Posicion del cursor(en nro de caracteres)
    803802        self.cursor = 0
    804803
    class CuadroTexto: 
    808807        self.color_r, self.color_g, self.color_b = 0, 0, 0
    809808        self.italic = False
    810809        self.bold = False
     810        self.font_description = pango.FontDescription()
     811        self.font_description.set_family(font_name)
    811812
    812813        #Tamanio del renglon
    813814        self.alto_renglon = 12
    class CuadroTexto: 
    818819        #Dibujar o no el cursor
    819820        self.mostrar_cursor = False
    820821
    821         #texto en cada renglon
    822         self.renglones = []
    823         # 1 =el renglon i termino con un espacio
    824         # 0= el renglon i no termino con espacio
    825         self.esp_reg = []
    826 
    827822        # Lo uso para acentuar letras con comilla simple
    828823        self.double_key = None
    829824
    830825    def set_text(self, text):
    831826        self.texto = text
    832         self.renglones = self.texto.split('\r')
    833         for i in range(len(self.renglones)):
    834             self.esp_reg.append(0)
    835827        self.cursor = len(text)
    836828
    837829    def imprimir(self, context):
    class CuadroTexto: 
    844836            context.stroke()
    845837
    846838        # Insertando el texto
    847         slant = cairo.FONT_SLANT_NORMAL
     839        style = pango.STYLE_NORMAL
    848840        if self.italic:
    849             slant = cairo.FONT_SLANT_ITALIC
    850         weight = cairo.FONT_WEIGHT_NORMAL
     841            style = pango.STYLE_ITALIC
     842        weight = pango.WEIGHT_NORMAL
    851843        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)
    897871        context.stroke()
    898872
    899873    def insertar_texto(self, key, keyval, context):
    class CuadroTexto: 
    953927                    self.cursor -= 1
    954928
    955929            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
    956932                sum_ren = 0
    957933                #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 renglon
    963                             cur_ren = self.cursor - sum_ren
    964                             self.cursor = \
    965                                 min(sum_ren - len(self.renglones[i - 1])
    966                                 - self.esp_reg[i - 1] + \
    967                                 cur_ren, sum_ren - 1)
    968                         break
    969                     else:
    970                         sum_ren += (len(self.renglones[i]) + self.esp_reg[i])
    971934
    972935            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
    973938                sum_ren = 0
    974939                #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 renglon
    980                             cur_ren = self.cursor - sum_ren
    981                             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                         break
    989                     else:
    990                         sum_ren += (len(self.renglones[i]) + self.esp_reg[i])
    991940
    992941            else:
    993942                agregar = unicode(key, 'UTF8')
    class CuadroTexto: 
    1007956    """
    1008957
    1009958    def redimensionar(self, context):
    1010         pass
    1011959        """
    1012960        Establece el texto en cada renglon dependiendo de las dimensiones
    1013961        del cuadro, manteniendo fijo el ancho,
    1014962        y redimensionando el alto si es necesario
    1015963        """
    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
    1087966
    1088967    def mover_a(self, x, y):
    1089968        "Mueve el centro del cuadro a la posicion (x,y)"
    class CuadroTexto: 
    1098977        """
    1099978        self.ancho = ancho
    1100979        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 -= 1
    1107         self.alto -= self.alto_renglon
    1108         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 -*-
    22
    33import os
    44import gtk
    55import cairo
     6import pangocairo
    67
    78import globos
    89import persistencia
    import dbus 
    2829import logging
    2930
    3031
     32def _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
    3145class HistorietaActivity(activity.Activity):
    3246
    3347    _EXPORT_FORMATS = [['image/png', _('Save as Image'), _('PNG'), ""]]
    class HistorietaActivity(activity.Activity): 
    97111
    98112        self.page.empty_page = handle.object_id is None
    99113
     114        # This is needed because of the Globes Font Size
     115        # http://bugs.sugarlabs.org/ticket/3436
     116        self._set_screen_dpi()
     117
    100118        #print "screen witdh " , SCREEN_WIDTH
    101119        #print "page witdh " , self.page.size_request()
    102120
    class HistorietaActivity(activity.Activity): 
    275293        preview_data = ''.join(preview_data)
    276294        return dbus.ByteArray(preview_data)
    277295
     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
    278301DEF_SPACING = 6
    279302DEF_WIDTH = 4
    280303
  • persistencia.py

    diff --git a/persistencia.py b/persistencia.py
    index f8d62c1..a67b19d 100644
    a b class Persistence: 
    6565                globoData['text_x'], globoData['text_y'] = \
    6666                    globo.texto.x, globo.texto.y
    6767                globoData['text_text'] = globo.texto.texto
    68                 globoData['text_rows'] = globo.texto.renglones
    69                 globoData['text_sp_rows'] = globo.texto.esp_reg
    7068
    7169                globoData['text_row_height'] = globo.texto.alto_renglon
    7270                globoData['text_font_size'] = globo.texto.font_size
    class Persistence: 
    183181                    globo.texto.x, globo.texto.y = globoData['text_x'], \
    184182                        globoData['text_y']
    185183                    globo.texto.texto = globoData['text_text']
    186                     globo.texto.renglones = globoData['text_rows']
    187                     globo.texto.esp_reg = globoData['text_sp_rows']
    188184
    189185                    globo.texto.alto_renglon = globoData['text_row_height']
    190186                    globo.texto.font_size = globoData['text_font_size']