[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Maposmatic-dev] [PATCH 2/2] multi-page index: wrap long labels over sev
From: |
David MENTRE |
Subject: |
[Maposmatic-dev] [PATCH 2/2] multi-page index: wrap long labels over several lines |
Date: |
Sat, 31 Mar 2012 10:52:12 +0200 |
Signed-off-by: David MENTRE <address@hidden>
---
ocitysmap2/indexlib/commons.py | 43 +++++++++++++-----
ocitysmap2/indexlib/multi_page_renderer.py | 66 ++++++++++++++++++++-------
2 files changed, 80 insertions(+), 29 deletions(-)
diff --git a/ocitysmap2/indexlib/commons.py b/ocitysmap2/indexlib/commons.py
index 45a72eb..a91f0c1 100644
--- a/ocitysmap2/indexlib/commons.py
+++ b/ocitysmap2/indexlib/commons.py
@@ -122,15 +122,21 @@ class IndexItem:
% (repr(self.label), self.endpoint1, self.endpoint2,
repr(self.location_str), repr(self.page_number)))
- def min_drawing_width(self, layout, em):
+ def label_drawing_width(self, layout):
layout.set_text(self.label)
- label_w = float(layout.get_size()[0]) / pango.SCALE
+ return float(layout.get_size()[0]) / pango.SCALE
+
+ def label_drawing_height(self, layout):
+ layout.set_text(self.label)
+ return float(layout.get_size()[1]) / pango.SCALE
+
+ def location_drawing_width(self, layout):
layout.set_text(self.location_str)
- location_w = float(layout.get_size()[0]) / pango.SCALE
- return (label_w + location_w + 2 * em)
+ return float(layout.get_size()[0]) / pango.SCALE
- def draw(self, rtl, ctx, pc, layout, fascent, fheight,
- baseline_x, baseline_y):
+ def draw(self, rtl, ctx, pc, column_layout, fascent, fheight,
+ baseline_x, baseline_y,
+ label_layout=None, label_height=0, location_width=0):
"""Draw this index item to the provided Cairo context. It prints the
label, the squares definition and the dotted line, with respect to the
RTL setting.
@@ -140,14 +146,25 @@ class IndexItem:
ctx (cairo.Context): the Cairo context to draw to.
pc (pangocairo.PangoCairo): the PangoCairo context for text
drawing.
- layout (pango.Layout): the Pango layout to use for text
+ column_layout (pango.Layout): the Pango layout to use for text
rendering, pre-configured with the appropriate font.
fascent (int): font ascent.
fheight (int): font height.
baseline_x (int): X axis coordinate of the baseline.
baseline_y (int): Y axis coordinate of the baseline.
+ Optional args (in case of label wrapping):
+ label_layout (pango.Layout): the Pango layout to use for text
+ rendering, in case the label should be wrapped
+ label_height (int): height of the big label
+ location_width (int): width of the 'location' part
"""
+ # Fallbacks in case we dont't have a wrapping label
+ if label_layout == None:
+ label_layout = column_layout
+ if label_height == 0:
+ label_height = fheight
+
if not self.location_str:
location_str = '???'
else:
@@ -155,22 +172,24 @@ class IndexItem:
ctx.save()
if not rtl:
- _, _, line_start = draw_utils.draw_text_left(ctx, pc, layout,
+ _, _, line_start = draw_utils.draw_text_left(ctx, pc, label_layout,
fascent, fheight,
baseline_x,
baseline_y,
self.label)
- line_end, _, _ = draw_utils.draw_text_right(ctx, pc, layout,
+ line_end, _, _ = draw_utils.draw_text_right(ctx, pc, column_layout,
fascent, fheight,
baseline_x, baseline_y,
location_str)
else:
- _, _, line_start = draw_utils.draw_text_left(ctx, pc, layout,
+ _, _, line_start = draw_utils.draw_text_left(ctx, pc,
column_layout,
fascent, fheight,
baseline_x,
baseline_y,
location_str)
- line_end, _, _ = draw_utils.draw_text_right(ctx, pc, layout,
+ line_end, _, _ = draw_utils.draw_text_right(ctx, pc, label_layout,
fascent, fheight,
- baseline_x, baseline_y,
+ (baseline_x
+ + location_width),
+ baseline_y,
self.label)
# In case of empty label, we don't draw the dots
diff --git a/ocitysmap2/indexlib/multi_page_renderer.py
b/ocitysmap2/indexlib/multi_page_renderer.py
index 43f4505..9000141 100644
--- a/ocitysmap2/indexlib/multi_page_renderer.py
+++ b/ocitysmap2/indexlib/multi_page_renderer.py
@@ -21,6 +21,7 @@ import cairo
import ocitysmap2.layoutlib.commons as UTILS
import pango
import pangocairo
+import math
class MultiPageStreetIndexRenderer:
"""
@@ -60,18 +61,22 @@ class MultiPageStreetIndexRenderer:
pc = pangocairo.CairoContext(self.ctx)
header_fd = pango.FontDescription("Georgia Bold 12")
- label_fd = pango.FontDescription("DejaVu 8")
+ label_column_fd = pango.FontDescription("DejaVu 8")
header_layout, header_fascent, header_fheight, header_em = \
self._create_layout_with_font(pc, header_fd)
label_layout, label_fascent, label_fheight, label_em = \
- self._create_layout_with_font(pc, label_fd)
+ self._create_layout_with_font(pc, label_column_fd)
+ column_layout, _, _, _ = \
+ self._create_layout_with_font(pc, label_column_fd)
# By OCitysmap's convention, the default resolution is 72 dpi,
# which maps to the default pangocairo resolution (96 dpi
# according to pangocairo docs). If we want to render with
# another resolution (different from 72), we have to scale the
# pangocairo resolution accordingly:
+ pangocairo.context_set_resolution(column_layout.get_context(),
+ 96.*dpi/UTILS.PT_PER_INCH)
pangocairo.context_set_resolution(label_layout.get_context(),
96.*dpi/UTILS.PT_PER_INCH)
pangocairo.context_set_resolution(header_layout.get_context(),
@@ -79,26 +84,41 @@ class MultiPageStreetIndexRenderer:
margin = label_em
- max_drawing_width = 0
+ # find largest label and location
+ max_label_drawing_width = 0.0
+ max_location_drawing_width = 0.0
for category in self.index_categories:
for street in category.items:
- w = street.min_drawing_width(label_layout, label_em)
- if w > max_drawing_width:
- max_drawing_width = w
+ w = street.label_drawing_width(label_layout)
+ if w > max_label_drawing_width:
+ max_label_drawing_width = w
+
+ w = street.location_drawing_width(label_layout)
+ if w > max_location_drawing_width:
+ max_location_drawing_width = w
# No street to render, bail out
- if max_drawing_width == 0:
+ if max_label_drawing_width == 0.0:
return
- columns_count = int(self.rendering_area_w / max_drawing_width)
+ # Find best number of columns
+ max_drawing_width = \
+ max_label_drawing_width + max_location_drawing_width + 2 * margin
+
+ columns_count = int(math.ceil(self.rendering_area_w /
max_drawing_width))
+ # following test should not be needed. No time to prove it. ;-)
if columns_count == 0:
columns_count = 1
- # We have three columns
+ # We have now have several columns
column_width = self.rendering_area_w / columns_count
- label_layout.set_width(int(UTILS.convert_pt_to_dots(
+ column_layout.set_width(int(UTILS.convert_pt_to_dots(
(column_width - margin) * pango.SCALE, dpi)))
+ label_layout.set_width(int(UTILS.convert_pt_to_dots(
+ (column_width - margin - max_location_drawing_width
+ - 2 * label_em)
+ * pango.SCALE, dpi)))
header_layout.set_width(int(UTILS.convert_pt_to_dots(
(column_width - margin) * pango.SCALE, dpi)))
@@ -106,7 +126,8 @@ class MultiPageStreetIndexRenderer:
orig_offset_x = offset_x = margin/2.
orig_delta_x = delta_x = column_width
else:
- orig_offset_x = offset_x = self.rendering_area_w - column_width +
margin/2.
+ orig_offset_x = offset_x = \
+ self.rendering_area_w - column_width + margin/2.
orig_delta_x = delta_x = - column_width
actual_n_cols = 0
@@ -138,7 +159,8 @@ class MultiPageStreetIndexRenderer:
offset_y += header_fheight
for street in category.items:
- if ( offset_y + label_fheight + margin/2.
+ label_height = street.label_drawing_height(label_layout)
+ if ( offset_y + label_height + margin/2.
> self.rendering_area_h ):
offset_y = margin/2.
offset_x += delta_x
@@ -151,16 +173,20 @@ class MultiPageStreetIndexRenderer:
delta_x = orig_delta_x
self.surface.show_page()
- street.draw(self._i18n.isrtl(), self.ctx, pc, label_layout,
+ street.draw(self._i18n.isrtl(), self.ctx, pc, column_layout,
UTILS.convert_pt_to_dots(label_fascent, dpi),
UTILS.convert_pt_to_dots(label_fheight, dpi),
UTILS.convert_pt_to_dots(self.rendering_area_x
+ offset_x, dpi),
UTILS.convert_pt_to_dots(self.rendering_area_y
+ offset_y
- + label_fascent, dpi))
+ + label_fascent, dpi),
+ label_layout,
+ UTILS.convert_pt_to_dots(label_height, dpi),
+
UTILS.convert_pt_to_dots(max_location_drawing_width,
+ dpi))
- offset_y += label_fheight
+ offset_y += label_height
self.ctx.restore()
@@ -170,6 +196,7 @@ if __name__ == '__main__':
import random
import string
import commons
+ import coords
width = 72*21./2.54
height = 72*29.7/2.54
@@ -178,7 +205,7 @@ if __name__ == '__main__':
random.seed(42)
- def rnd_str(max_len, letters = string.letters):
+ def rnd_str(max_len, letters = string.letters + ' ' * 4):
return ''.join(random.choice(letters)
for i in xrange(random.randint(1, max_len)))
@@ -193,7 +220,7 @@ if __name__ == '__main__':
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'Schools', 'Public buildings']:
items = []
- for label, location_str in [(rnd_str(20).capitalize(),
+ for label, location_str in [(rnd_str(40).capitalize(),
'%s%d-%s%d' \
% (rnd_str(2,
string.ascii_uppercase),
@@ -216,5 +243,10 @@ if __name__ == '__main__':
mpsir = MultiPageStreetIndexRenderer(i18nMock(False), ctxtmp, surface,
streets, rendering_area)
mpsir.render()
+ surface.show_page()
+
+ mpsir = MultiPageStreetIndexRenderer(i18nMock(True), ctxtmp, surface,
+ streets, rendering_area)
+ mpsir.render()
surface.finish()
--
1.7.5.4