Commit be55b276 authored by sumpfralle's avatar sumpfralle

implemented font preview

added export of the rendered text as SVG


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@829 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 4378fad7
...@@ -6947,10 +6947,12 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -6947,10 +6947,12 @@ Please read the description of the Server Mode (linked below) to understand the
<object class="GtkLabel" id="FontDialogProperties"> <object class="GtkLabel" id="FontDialogProperties">
<property name="visible">True</property> <property name="visible">True</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Font selection:&lt;/b&gt;</property> <property name="label" translatable="yes">&lt;b&gt;Font properties:&lt;/b&gt;</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
...@@ -6960,15 +6962,86 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -6960,15 +6962,86 @@ Please read the description of the Server Mode (linked below) to understand the
<child> <child>
<placeholder/> <placeholder/>
</child> </child>
<child>
<object class="GtkTable" id="table6">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<property name="column_spacing">3</property>
<property name="homogeneous">True</property>
<child> <child>
<object class="GtkHScale" id="FontSideShift"> <object class="GtkHScale" id="FontSideShift">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Skew the text to the left or right side. The value is given in percent based on the height of the text.</property> <property name="update_policy">delayed</property>
<property name="adjustment">FontSideSkewValue</property> <property name="adjustment">FontSideSkewValue</property>
<property name="digits">0</property> <property name="digits">0</property>
<property name="value_pos">bottom</property> <property name="value_pos">bottom</property>
</object> </object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="FontSideSkewLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Horiz. skew</property>
</object>
</child>
<child>
<object class="GtkLabel" id="FontLineSpacingLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Line spacing</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkHScale" id="FontLineSpacing">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="update_policy">delayed</property>
<property name="adjustment">FontLineSpacingValue</property>
<property name="digits">2</property>
<property name="value_pos">bottom</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="FontCharacterSpacingLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Pitch</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
</packing>
</child>
<child>
<object class="GtkHScale" id="FontCharacterSpacing">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="update_policy">delayed</property>
<property name="adjustment">FontCharacterSpacingValue</property>
<property name="digits">2</property>
<property name="value_pos">bottom</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
<packing> <packing>
<property name="pack_type">end</property> <property name="pack_type">end</property>
<property name="position">1</property> <property name="position">1</property>
...@@ -6976,18 +7049,62 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -6976,18 +7049,62 @@ Please read the description of the Server Mode (linked below) to understand the
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">False</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkHSeparator" id="hseparator5"> <object class="GtkHBox" id="hbox33">
<property name="visible">True</property> <property name="visible">True</property>
<property name="spacing">2</property>
<child>
<object class="GtkLabel" id="FontAuthorLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Font author:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="FontAuthorText">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">FontAuthor</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">2</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkLabel" id="FontDedicationQCAD">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Thanks to the &lt;a href="http://qcad.org"&gt;QCAD developers&lt;/a&gt; for these single-line fonts!</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator5">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="FontDialogInputLabel"> <object class="GtkLabel" id="FontDialogInputLabel">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -6996,7 +7113,9 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -6996,7 +7113,9 @@ Please read the description of the Server Mode (linked below) to understand the
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
<packing> <packing>
<property name="position">3</property> <property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -7007,6 +7126,7 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7007,6 +7126,7 @@ Please read the description of the Server Mode (linked below) to understand the
<object class="GtkTextView" id="FontDialogInput"> <object class="GtkTextView" id="FontDialogInput">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="border_width">3</property> <property name="border_width">3</property>
<property name="wrap_mode">word</property> <property name="wrap_mode">word</property>
<property name="buffer">FontDialogInputBuffer</property> <property name="buffer">FontDialogInputBuffer</property>
...@@ -7015,7 +7135,9 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7015,7 +7135,9 @@ Please read the description of the Server Mode (linked below) to understand the
</child> </child>
</object> </object>
<packing> <packing>
<property name="position">4</property> <property name="expand">False</property>
<property name="fill">False</property>
<property name="position">6</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -7024,7 +7146,8 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7024,7 +7146,8 @@ Please read the description of the Server Mode (linked below) to understand the
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">5</property> <property name="fill">False</property>
<property name="position">7</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -7035,13 +7158,16 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7035,13 +7158,16 @@ Please read the description of the Server Mode (linked below) to understand the
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
<packing> <packing>
<property name="position">6</property> <property name="expand">False</property>
<property name="fill">False</property>
<property name="position">8</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkViewport" id="FontDialogPreviewViewPort"> <object class="GtkViewport" id="FontDialogPreviewViewPort">
<property name="height_request">120</property> <property name="height_request">120</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="border_width">3</property>
<property name="resize_mode">queue</property> <property name="resize_mode">queue</property>
<property name="shadow_type">etched-in</property> <property name="shadow_type">etched-in</property>
<child> <child>
...@@ -7051,7 +7177,7 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7051,7 +7177,7 @@ Please read the description of the Server Mode (linked below) to understand the
</child> </child>
</object> </object>
<packing> <packing>
<property name="position">7</property> <property name="position">9</property>
</packing> </packing>
</child> </child>
<child internal-child="action_area"> <child internal-child="action_area">
...@@ -7074,11 +7200,10 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7074,11 +7200,10 @@ Please read the description of the Server Mode (linked below) to understand the
</child> </child>
<child> <child>
<object class="GtkButton" id="FontDialogSave"> <object class="GtkButton" id="FontDialogSave">
<property name="label">gtk-save-as</property> <property name="label">Save as SVG</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<property name="use_stock">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
...@@ -7104,7 +7229,7 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7104,7 +7229,7 @@ Please read the description of the Server Mode (linked below) to understand the
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="pack_type">end</property> <property name="pack_type">end</property>
<property name="position">8</property> <property name="position">10</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -7129,4 +7254,16 @@ Please read the description of the Server Mode (linked below) to understand the ...@@ -7129,4 +7254,16 @@ Please read the description of the Server Mode (linked below) to understand the
<object class="GtkAction" id="ExtrasMenu"> <object class="GtkAction" id="ExtrasMenu">
<property name="label">E_xtras</property> <property name="label">E_xtras</property>
</object> </object>
<object class="GtkAdjustment" id="FontCharacterSpacingValue">
<property name="value">1</property>
<property name="lower">-1</property>
<property name="upper">5</property>
<property name="step_increment">0.10000000000000001</property>
</object>
<object class="GtkAdjustment" id="FontLineSpacingValue">
<property name="value">1</property>
<property name="lower">-1</property>
<property name="upper">5</property>
<property name="step_increment">0.10000000000000001</property>
</object>
</interface> </interface>
...@@ -166,6 +166,7 @@ def get_font_files(): ...@@ -166,6 +166,7 @@ def get_font_files():
filename = os.path.join(font_dir, fname) filename = os.path.join(font_dir, fname)
if filename.lower().endswith(".cxf") and os.path.isfile(filename): if filename.lower().endswith(".cxf") and os.path.isfile(filename):
result.append(filename) result.append(filename)
result.sort()
return result return result
def load_fonts(callback=None): def load_fonts(callback=None):
...@@ -176,7 +177,8 @@ def load_fonts(callback=None): ...@@ -176,7 +177,8 @@ def load_fonts(callback=None):
else: else:
progress_counter = None progress_counter = None
for font_file in all_font_files: for font_file in all_font_files:
charset = pycam.Importers.CXFImporter.import_font(font_file) charset = pycam.Importers.CXFImporter.import_font(font_file,
callback=progress_counter)
if (not progress_counter is None) and progress_counter.increment(): if (not progress_counter is None) and progress_counter.increment():
break break
if not charset is None: if not charset is None:
...@@ -213,7 +215,7 @@ class ProjectGui: ...@@ -213,7 +215,7 @@ class ProjectGui:
self.gui = gtk.Builder() self.gui = gtk.Builder()
gtk_build_file = get_data_file_location(GTKBUILD_FILE) gtk_build_file = get_data_file_location(GTKBUILD_FILE)
if gtk_build_file is None: if gtk_build_file is None:
sys.exit(1) gtk.main_quit()
self.gui.add_from_file(gtk_build_file) self.gui.add_from_file(gtk_build_file)
self.window = self.gui.get_object("ProjectWindow") self.window = self.gui.get_object("ProjectWindow")
# increase the initial width of the window (due to hidden elements) # increase the initial width of the window (due to hidden elements)
...@@ -329,6 +331,20 @@ class ProjectGui: ...@@ -329,6 +331,20 @@ class ProjectGui:
self.import_from_font_dialog) self.import_from_font_dialog)
self.gui.get_object("FontDialogSave").connect("clicked", self.gui.get_object("FontDialogSave").connect("clicked",
self.export_from_font_dialog) self.export_from_font_dialog)
self.gui.get_object("FontDialogInputBuffer").connect("changed",
self.update_font_dialog_preview)
self.gui.get_object("FontDialogPreview").connect("configure_event",
self.update_font_dialog_preview)
self.gui.get_object("FontDialogPreview").connect("expose_event",
self.update_font_dialog_preview)
for objname in ("FontSideSkewValue", "FontCharacterSpacingValue",
"FontLineSpacingValue"):
obj = self.gui.get_object(objname)
# set default value before connecting the change-handler
if objname != "FontSideSkewValue":
obj.set_value(1.0)
obj.connect("value-changed",
self.update_font_dialog_preview)
self._font_dialog_window_visible = False self._font_dialog_window_visible = False
self._font_dialog_window_position = None self._font_dialog_window_position = None
self._fonts = None self._fonts = None
...@@ -780,10 +796,11 @@ class ProjectGui: ...@@ -780,10 +796,11 @@ class ProjectGui:
self.preferences_window.add_accel_group(self._accel_group) self.preferences_window.add_accel_group(self._accel_group)
self.log_window.add_accel_group(self._accel_group) self.log_window.add_accel_group(self._accel_group)
self.process_pool_window.add_accel_group(self._accel_group) self.process_pool_window.add_accel_group(self._accel_group)
self.font_dialog_window.add_accel_group(self._accel_group)
# load menu data # load menu data
gtk_menu_file = get_data_file_location(GTKMENU_FILE) gtk_menu_file = get_data_file_location(GTKMENU_FILE)
if gtk_menu_file is None: if gtk_menu_file is None:
sys.exit(1) gtk.main_quit()
uimanager.add_ui_from_file(gtk_menu_file) uimanager.add_ui_from_file(gtk_menu_file)
# make the actions defined in the GTKBUILD file available in the menu # make the actions defined in the GTKBUILD file available in the menu
actiongroup = gtk.ActionGroup("menubar") actiongroup = gtk.ActionGroup("menubar")
...@@ -1428,8 +1445,8 @@ class ProjectGui: ...@@ -1428,8 +1445,8 @@ class ProjectGui:
obj.set_value(default_value) obj.set_value(default_value)
self.gui.get_object("ExportEMCToolDefinition").set_sensitive(len(self.tool_list) > 0) self.gui.get_object("ExportEMCToolDefinition").set_sensitive(len(self.tool_list) > 0)
@progress_activity_guard
@gui_activity_guard @gui_activity_guard
@progress_activity_guard
def toggle_font_dialog_window(self, widget=None, event=None, state=None): def toggle_font_dialog_window(self, widget=None, event=None, state=None):
# only "delete-event" uses four arguments # only "delete-event" uses four arguments
# TODO: unify all these "toggle" functions for different windows into one single function (including storing the position) # TODO: unify all these "toggle" functions for different windows into one single function (including storing the position)
...@@ -1454,6 +1471,8 @@ class ProjectGui: ...@@ -1454,6 +1471,8 @@ class ProjectGui:
else: else:
# TODO: show some warning - no fonts found # TODO: show some warning - no fonts found
pass pass
font_selector.connect("changed",
self.update_font_dialog_preview)
font_selector.show() font_selector.show()
self.font_selector = font_selector self.font_selector = font_selector
if self._font_dialog_window_position: if self._font_dialog_window_position:
...@@ -1468,20 +1487,66 @@ class ProjectGui: ...@@ -1468,20 +1487,66 @@ class ProjectGui:
# don't close the window - just hide it (for "delete-event") # don't close the window - just hide it (for "delete-event")
return True return True
@gui_activity_guard def get_font_dialog_text_rendered(self):
def import_from_font_dialog(self, widget=None):
text_buffer = self.gui.get_object("FontDialogInput").get_buffer() text_buffer = self.gui.get_object("FontDialogInput").get_buffer()
text = text_buffer.get_text(text_buffer.get_start_iter(), text = text_buffer.get_text(text_buffer.get_start_iter(),
text_buffer.get_end_iter()) text_buffer.get_end_iter())
if text:
skew = self.gui.get_object("FontSideSkewValue").get_value()
line_space = self.gui.get_object("FontLineSpacingValue").get_value()
pitch = self.gui.get_object("FontCharacterSpacingValue").get_value()
font_name = self.font_selector.get_active_text() font_name = self.font_selector.get_active_text()
new_model = self._fonts[font_name].render(text) return self._fonts[font_name].render(text, skew=skew,
self.load_model(new_model) line_spacing=line_space, pitch=pitch)
self.append_to_queue(self.toggle_font_dialog_window) else:
# empty text
return None
@gui_activity_guard @gui_activity_guard
def export_from_font_dialog(self, widget=None): def import_from_font_dialog(self, widget=None):
self.load_model(self.get_font_dialog_text_rendered())
self.append_to_queue(self.toggle_font_dialog_window) self.append_to_queue(self.toggle_font_dialog_window)
def export_from_font_dialog(self, widget=None):
text_model = self.get_font_dialog_text_rendered()
if text_model and (not text_model.maxx is None):
self.save_model(model=text_model)
@gui_activity_guard
def update_font_dialog_preview(self, widget=None, event=None):
if self._fonts is None:
return
font_name = self.font_selector.get_active_text()
font = self._fonts[font_name]
self.gui.get_object("FontAuthorText").set_label(
"\n".join(font.get_authors()))
preview_widget = self.gui.get_object("FontDialogPreview")
final_drawing_area = preview_widget.window
text_model = self.get_font_dialog_text_rendered()
# carefully check if there are lines in the rendered text
if text_model and (not text_model.maxx is None):
x, y, width, height = preview_widget.get_allocation()
x_fac = width / (text_model.maxx - text_model.minx)
y_fac = height / (text_model.maxy - text_model.miny)
model_base_x = text_model.minx
model_base_y = text_model.miny
factor = min(x_fac, y_fac)
drawing_area = gtk.gdk.Pixmap(final_drawing_area, width, height)
# always clean the background
drawing_area.draw_rectangle(preview_widget.get_style().white_gc, True, 0, 0, width, height)
gc = drawing_area.new_gc()
get_virtual_x = lambda x: int((x - model_base_x) * factor)
get_virtual_y = lambda y: height - int((y - model_base_y) * factor)
for polygon in text_model.get_polygons():
draw_points = []
for point in polygon.get_points():
x = get_virtual_x(point.x)
y = get_virtual_y(point.y)
draw_points.append((x, y))
drawing_area.draw_lines(gc, draw_points)
final_gc = final_drawing_area.new_gc()
final_drawing_area.draw_drawable(final_gc, drawing_area, 0, 0, 0, 0, -1, -1)
@gui_activity_guard @gui_activity_guard
def toggle_about_window(self, widget=None, event=None, state=None): def toggle_about_window(self, widget=None, event=None, state=None):
# only "delete-event" uses four arguments # only "delete-event" uses four arguments
...@@ -1994,11 +2059,12 @@ class ProjectGui: ...@@ -1994,11 +2059,12 @@ class ProjectGui:
return filename return filename
@gui_activity_guard @gui_activity_guard
def save_model(self, widget=None, filename=None): def save_model(self, widget=None, filename=None, model=None):
# only triangle models may be saved if model is None:
if not self.model.is_export_supported(): model = self.model
if not model.is_export_supported():
log.warn(("Saving this type of model (%s) is currently not " \ log.warn(("Saving this type of model (%s) is currently not " \
+ "implemented!") % str(type(self.model))) + "implemented!") % str(type(model)))
return return
# get the filename # get the filename
if callable(filename): if callable(filename):
...@@ -2015,7 +2081,7 @@ class ProjectGui: ...@@ -2015,7 +2081,7 @@ class ProjectGui:
return return
try: try:
file_in = open(filename, "w") file_in = open(filename, "w")
self.model.export(comment=self.get_meta_data()).write(file_in) model.export(comment=self.get_meta_data()).write(file_in)
file_in.close() file_in.close()
except IOError, err_msg: except IOError, err_msg:
log.error("Failed to save model file: %s" % err_msg) log.error("Failed to save model file: %s" % err_msg)
...@@ -2768,7 +2834,10 @@ class ProjectGui: ...@@ -2768,7 +2834,10 @@ class ProjectGui:
or (self._last_gtk_events_time + 1 < current_time): or (self._last_gtk_events_time + 1 < current_time):
while gtk.events_pending(): while gtk.events_pending():
gtk.main_iteration() gtk.main_iteration()
if not percent is None: if percent:
# We don't store the timining if percent=0 or percent=None.
# This is especially nice for the snappines during font
# initialization.
self._last_gtk_events_time = current_time self._last_gtk_events_time = current_time
# return if the user requested a break # return if the user requested a break
return self._progress_cancel_requested return self._progress_cancel_requested
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment