Ejemplo n.º 1
0
    def copyMetrics(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            copyOrder = [
                '--' in name for name in (self.edt_lsb.text, self.edt_rsb.text,
                                          self.edt_adv.text)
            ]
            srcGlyphs = [
                str(name).replace('--', '') if len(name) else None
                for name in (self.edt_lsb.text, self.edt_rsb.text,
                             self.edt_adv.text)
            ]

            adjPercents = (self.spb_lsb_percent.value,
                           self.spb_rsb_percent.value,
                           self.spb_adv_percent.value)
            adjUnits = (self.spb_lsb_units.value, self.spb_rsb_units.value,
                        self.spb_adv_units.value)

            glyph.copyMetricsbyName(srcGlyphs, pLayers, copyOrder, adjPercents,
                                    adjUnits)

            glyph.updateObject(
                glyph.fl, 'Copy Metrics | LSB: %s; RSB: %s; ADV:%s.' %
                (srcGlyphs[0], srcGlyphs[1], srcGlyphs[2]))
            glyph.update()

        self.reset_fileds()
Ejemplo n.º 2
0
    def shape_replace(self):
        process_glyphs = getProcessGlyphs(pMode)
        replace_shape_name = self.cmb_fontShapes.currentText

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)
            process_shapes_dict = {}

            for layer in process_layers:
                replace_shape = self.active_font.findShape(
                    replace_shape_name, layer)
                selected_shape = glyph.selectedAtShapes(index=False,
                                                        layer=layer,
                                                        deep=False)[0][0]

                if selected_shape is not None:
                    if replace_shape is not None:
                        process_shapes_dict[layer] = (selected_shape,
                                                      replace_shape,
                                                      selected_shape.transform)
                    else:
                        output(
                            2, app_name,
                            'Glyph: %s\tElement: %s not found @Layer: %s' %
                            (glyph.name, insert_shape_name, layer))

            for layer, shape_triple in process_shapes_dict.items():
                replace_shape.transform = shape_triple[2]  # Apply transform
                glyph.replaceShape(shape_triple[0], shape_triple[1], layer)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Glyph: %s;\tInsert Element:%s @ %s.' %
                (glyph.name, replace_shape_name, '; '.join(process_layers)))
Ejemplo n.º 3
0
    def remove_SmartCorner(self):
        # Finds active preset in glyphs smart corners and removes them
        # - Init
        process_glyphs = getProcessGlyphs(pMode)
        active_preset = self.getPreset()
        if active_preset is None: return

        # - Process
        if len(process_glyphs):
            for work_glyph in process_glyphs:
                if work_glyph is not None:
                    # - Init
                    wLayers = work_glyph._prepareLayers(pLayers)
                    smart_corners, target_corners = [], []

                    # - Get all smart nodes/corners
                    for layer in wLayers:
                        for builder in work_glyph.getBuilders(
                                layer)[filter_name]:
                            smart_corners += builder.getSmartNodes()

                        if len(smart_corners):
                            for node in smart_corners:
                                wNode = eNode(node)

                                if wNode.getSmartAngleRadius() == float(
                                        active_preset[layer]):
                                    wNode.delSmartAngle()

            self.update_glyphs(process_glyphs, True)
            output(
                0, app_name, 'Remove Smart Corner; Glyphs: %s' %
                '; '.join([g.name for g in process_glyphs]))
Ejemplo n.º 4
0
    def adjMetrics(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            wLayers = glyph._prepareLayers(pLayers)

            copyOrder = [False] * 3
            srcGlyphs = [glyph.name] * 3

            adjPercents = (self.spb_lsb_percent.value,
                           self.spb_rsb_percent.value,
                           self.spb_adv_percent.value)
            adjUnits = (self.spb_lsb_units.value, self.spb_rsb_units.value,
                        self.spb_adv_units.value)

            for layer in wLayers:
                glyph.setLSB(
                    glyph.getLSB(layer) * adjPercents[0] / 100 + adjUnits[0],
                    layer)
                glyph.setRSB(
                    glyph.getRSB(layer) * adjPercents[1] / 100 + adjUnits[1],
                    layer)
                glyph.setAdvance(
                    glyph.getAdvance(layer) * adjPercents[2] / 100 +
                    adjUnits[2], layer)

            glyph.updateObject(
                glyph.fl, 'Adjust Metrics @ %s | %s' %
                ('; '.join(wLayers),
                 zip(('LSB', 'RSB', 'ADV'), adjPercents, adjUnits)))
            glyph.update()
Ejemplo n.º 5
0
    def glyph_setBasics(self, mode):
        font = pFont()
        process_glyphs = getProcessGlyphs(pMode)
        processed_glyphs = []

        for n, glyph in enumerate(process_glyphs):
            if mode == 'flag':
                wLayers = glyph._prepareLayers(pLayers)
                for layer in wLayers:
                    glyph.setMark(
                        self.color_codes[self.cmb_select_color.currentText],
                        None)

            if mode == 'name':
                new_name = str(self.edt_glyphName.text)

                if number_token in new_name:
                    token_count = new_name.count(number_token)
                    new_name = new_name.replace('#' * token_count,
                                                '%s') % fromat_number(
                                                    n, token_count)

                if font.hasGlyph(new_name):
                    new_name = '%s.%s' % (new_name, str(n))

                glyph.setName(new_name)

            if mode == 'tags':
                glyph.setTags(str(self.edt_glyphTags.text).split(' '))

            processed_glyphs.append(glyph.name)

        font.updateObject(
            font.fl,
            'Set Glyph(s) %s | %s' % (mode, ', '.join(processed_glyphs)))
Ejemplo n.º 6
0
    def apply_SmartCorner(self, remove=False):
        # NOTE: apply and remove here apply only to soelected nodes.
        if self.builder is not None:
            # - Init
            process_glyphs = getProcessGlyphs(pMode)
            active_preset = self.getPreset()
            if active_preset is None: return

            if remove:  # Build a special preset that deletes
                active_preset = {key: 'DEL' for key in active_preset.keys()}

            # - Process
            if len(process_glyphs):
                for work_glyph in process_glyphs:
                    if work_glyph is not None:
                        self.process_smartCorner(work_glyph, active_preset)

                self.update_glyphs(process_glyphs, True)
                output(
                    0, app_name, 'Smart Corner; Glyphs: %s' %
                    '; '.join([g.name for g in process_glyphs]))

        else:
            warnings.warn(
                'Glyph with Smart corner (shape builder) not specified!',
                GlyphWarning)
Ejemplo n.º 7
0
    def apply_trap(self):
        # - Init
        process_glyphs = getProcessGlyphs(pMode)
        active_preset = self.getPreset()
        if active_preset is None: return

        # - Process
        if len(process_glyphs):
            for glyph in process_glyphs:
                if glyph is not None:
                    wLayers = glyph._prepareLayers(pLayers)

                    for layer in reversed(wLayers):
                        if layer in active_preset.keys():
                            selection = glyph.selectedNodes(layer,
                                                            filterOn=True,
                                                            extend=eNode,
                                                            deep=True)

                            for node in reversed(selection):
                                preset_values = tuple([
                                    float(item.strip())
                                    for item in active_preset[layer].split(',')
                                ])
                                node.cornerTrapInc(*preset_values)

                    glyph.update()
                    glyph.updateObject(
                        glyph.fl, '%s @ %s.' %
                        ('Ink Trap', '; '.join(active_preset.keys())))
Ejemplo n.º 8
0
    def apply_mitre(self, doKnot=False):
        # - Init
        process_glyphs = getProcessGlyphs(pMode)
        active_preset = self.getPreset()
        if active_preset is None: return

        # - Process
        if len(process_glyphs):
            for glyph in process_glyphs:
                if glyph is not None:
                    wLayers = glyph._prepareLayers(pLayers)

                    for layer in reversed(wLayers):
                        if layer in active_preset.keys():
                            selection = glyph.selectedNodes(layer,
                                                            filterOn=True,
                                                            extend=eNode,
                                                            deep=True)

                            for node in reversed(selection):
                                if not doKnot:
                                    node.cornerMitre(
                                        float(active_preset[layer]))
                                else:
                                    node.cornerMitre(
                                        -float(active_preset[layer]), True)

                    action = 'Mitre Corner' if not doKnot else 'Overlap Corner'
                    glyph.update()
                    glyph.updateObject(
                        glyph.fl,
                        '%s @ %s.' % (action, '; '.join(active_preset.keys())))
Ejemplo n.º 9
0
    def glyph_insert(self, asMask=False):
        font = pFont()
        src_glyph_name = self.edt_sourceName.text
        processed_glyphs = []

        if len(src_glyph_name) and font.hasGlyph(src_glyph_name):
            copy_options = self.__getOptions()
            process_glyphs = getProcessGlyphs(pMode)
            src_glyph = font.glyph(src_glyph_name)

            for dst_glyph in process_glyphs:
                for src_layer in src_glyph.layers():
                    src_layer_name = src_layer.name

                    if '#' not in src_layer_name:
                        new_layer = dst_glyph.importLayer(
                            src_glyph, src_layer_name, src_layer_name,
                            copy_options, True, False, True,
                            ('insert', 'mask')[asMask])
                        new_transform, org_transform, rev_transform = self.tr_trans_ctrl.getTransform(
                            new_layer.boundingBox)
                        new_layer.applyTransform(org_transform)
                        new_layer.applyTransform(new_transform)
                        new_layer.applyTransform(rev_transform)

                processed_glyphs.append(dst_glyph.name)

            font.updateObject(
                font.fl, 'Insert Glyph: %s --> %s;' %
                (src_glyph_name, ', '.join(processed_glyphs)))
        else:
            warnings.warn(
                'Glyph not found: %s;' %
                (None, src_glyph_name)[1 if len(src_glyph_name) else 0],
                GlyphWarning)
Ejemplo n.º 10
0
    def shape_autoReorder(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                glyph.reorder_shapes(layer)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Auto Shape Order @ %s.' % '; '.join(process_layers))
Ejemplo n.º 11
0
    def shape_ungroupAll(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                glyph.ungroup_all_shapes(layer)

            glyph.update()
            glyph.updateObject(
                glyph.fl,
                'Ungroup all Shapes @ %s.' % '; '.join(process_layers))
Ejemplo n.º 12
0
    def setMetricEquations(self, clear=False):
        process_glyphs = getProcessGlyphs(pMode)
        modifiers = QtGui.QApplication.keyboardModifiers()

        for glyph in process_glyphs:
            wLayers = glyph._prepareLayers(pLayers)

            for layer in wLayers:
                if not clear:
                    if len(self.edt_lsb.text):
                        eq_set = self.edt_lsb.text

                        if modifiers == QtCore.Qt.ShiftModifier:
                            selection = glyph.selectedNodes(layer,
                                                            extend=eNode)
                            diffX = selection[0].diffTo(selection[-1])[0]
                            eq_set += '%s%s' % ([
                                '-', '+'
                            ][modifiers == QtCore.Qt.ControlModifier],
                                                abs(diffX))

                        glyph.setLSBeq(eq_set, layer)

                    if len(self.edt_rsb.text):
                        eq_set = self.edt_rsb.text

                        if modifiers == QtCore.Qt.AltModifier:
                            selection = glyph.selectedNodes(layer,
                                                            extend=eNode)
                            diffX = selection[0].diffTo(selection[-1])[0]
                            eq_set += '%s%s' % ([
                                '-', '+'
                            ][modifiers == QtCore.Qt.ControlModifier],
                                                abs(diffX))

                        glyph.setRSBeq(eq_set, layer)

                    if len(self.edt_adv.text):
                        eq_set = self.edt_adv.text
                        glyph.setADVeq(eq_set, layer)
                else:
                    glyph.setLSBeq('', layer)
                    glyph.setRSBeq('', layer)
                    glyph.setADVeq('', layer)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Set Metrics Equations @ %s.' % '; '.join(wLayers))

        self.reset_fileds()
Ejemplo n.º 13
0
    def autoMetricEquations(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            wLayers = glyph._prepareLayers(pLayers)
            glyph_stat = []

            for layer in wLayers:
                status = glyph.bindCompMetrics(layer)
                glyph_stat.append(status)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Glyph: %s;\tAuto Metrics Equations @ %s.' %
                (glyph.name, '; '.join('%s: %s' % item
                                       for item in zip(wLayers, glyph_stat))))
Ejemplo n.º 14
0
	def set_sidebearings(self, mode='bth'):
		process_glyphs = getProcessGlyphs(pMode)

		for glyph in process_glyphs:
			wLayers = glyph._prepareLayers(pLayers)

			for layer in wLayers:
				new_lsb, new_rsb = self.active_sampler.getGlyphSB(glyph, layer, self.spb_mul_area.value, not self.chk_area_cache.isChecked(), self.chk_area_draw.isChecked())
				if mode != 'rsb': glyph.setLSB(int(new_lsb), layer)
				if mode != 'lsb': glyph.setRSB(int(new_rsb), layer)
			
			if len(process_glyphs) == 1:
				glyph.updateObject(glyph.fl, 'Set Metrics @ %s.' %'; '.join(wLayers))

		if len(process_glyphs) > 1:
			self.active_font.updateObject(self.active_font.fl, 'Set Metrics for glyphs %s @ %s.' %('; '.join([glyph.name for glyph in process_glyphs]), '; '.join(wLayers)))		
Ejemplo n.º 15
0
    def shape_delete(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)
            process_shapes = {
                layer: glyph.selectedAtShapes(index=False,
                                              layer=layer,
                                              deep=False)[0][0]
                for layer in process_layers
            }

            for layer, shape in process_shapes.items():
                glyph.layer(layer).removeShape(shape)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Remove Element @ %s.' % '; '.join(process_layers))
Ejemplo n.º 16
0
    def shape_setname(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                wShape = pShape(
                    glyph.selectedAtShapes(index=False,
                                           layer=layer,
                                           deep=False)[0][0])
                wShape.setName(self.edt_shapeName.text)

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Set Element Name @ %s.' % '; '.join(process_layers))

        self.reset_fileds()
Ejemplo n.º 17
0
    def shape_resetTransform(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                wShape = pShape(
                    glyph.selectedAtShapes(index=False,
                                           layer=layer,
                                           deep=False)[0][0])
                wShape.reset_transform()

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Reset Element transformation data @ %s.' %
                '; '.join(process_layers))

        self.reset_fileds()
Ejemplo n.º 18
0
    def glyph_duplicate(self):
        copy_options = self.__getOptions()

        # - Init
        font = pFont()
        process_glyphs = getProcessGlyphs(pMode)
        processed_glyphs = []

        for glyph in process_glyphs:
            glyp_name = glyph.name

            for n in range(self.spb_duplicate.value):
                new_name = glyp_name + str(self.edt_glyphsuffix.text)
                token_count = new_name.count(number_token)

                if number_token in new_name:
                    new_name = new_name.replace('#' * token_count,
                                                '%s') % fromat_number(
                                                    n, token_count)

                if font.hasGlyph(new_name):
                    new_name = '%s.%s' % (new_name, str(n))

                new_glyph = font.duplicateGlyph(glyp_name,
                                                new_name,
                                                dst_unicode=None,
                                                options=copy_options)

                for layer in new_glyph.layers():
                    new_transform, org_transform, rev_transform = self.tr_trans_ctrl.getTransform(
                        layer.boundingBox)
                    layer.applyTransform(org_transform)
                    layer.applyTransform(new_transform)
                    layer.applyTransform(rev_transform)

                processed_glyphs.append(new_name)
        '''
		for glyph in process_glyphs:	
			wLayers = glyph._prepareLayers(pLayers)
		'''
        font.updateObject(
            font.fl, 'Duplicate Glyph(s) | %s' % ', '.join(processed_glyphs))
Ejemplo n.º 19
0
    def rebuild(self):
        # - Init
        process_glyphs = getProcessGlyphs(pMode)

        # - Process
        if len(process_glyphs):
            for glyph in process_glyphs:
                if glyph is not None:
                    wLayers = glyph._prepareLayers(pLayers)
                    selection_layers = {
                        layer: glyph.selectedNodes(layer,
                                                   filterOn=True,
                                                   extend=eNode)
                        for layer in wLayers
                    }

                    for layer, selection in selection_layers.items():
                        if len(selection) > 1:
                            node_first = selection[0]
                            node_last = selection[-1]

                            line_in = node_first.getPrevLine(
                            ) if node_first.getPrevOn(
                                False
                            ) not in selection else node_first.getNextLine()
                            line_out = node_last.getNextLine(
                            ) if node_last.getNextOn(
                                False
                            ) not in selection else node_last.getPrevLine()

                            crossing = line_in.intersect_line(line_out, True)

                            node_first.smartReloc(*crossing.tuple)
                            node_first.parent.removeNodesBetween(
                                node_first.fl, node_last.getNextOn())

                    glyph.update()
                    glyph.updateObject(
                        glyph.fl,
                        'Rebuild corner: %s nodes reduced; At layers: %s' %
                        (len(selection), '; '.join(wLayers)))
Ejemplo n.º 20
0
    def table_execute(self):
        process_glyphs = getProcessGlyphs(self.pMode)

        for wGlyph in process_glyphs:
            if self.pMode != 0: self.get_PointArrays(wGlyph)
            process_out = []

            for layerIndex in range(self.tab_masters.rowCount):
                if self.tab_masters.item(layerIndex,
                                         0).checkState() == QtCore.Qt.Checked:
                    process_out.append(
                        self.tab_masters.item(layerIndex, 0).text())
                    self.process_scale(wGlyph,
                                       layerIndex,
                                       anisotropic=self.chk_single.isChecked(),
                                       live_update=False)

            wGlyph.update()
            wGlyph.updateObject(
                wGlyph.fl, '| Delta Machine | Glyph: %s\tLayers procesed: %s' %
                (wGlyph.name, '; '.join(process_out)))
Ejemplo n.º 21
0
    def shape_insert(self):
        process_glyphs = getProcessGlyphs(pMode)
        insert_shape_name = self.cmb_fontShapes.currentText

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                insert_shape = self.active_font.findShape(
                    insert_shape_name, layer)

                if insert_shape is not None:
                    glyph.addShape(insert_shape, layer)
                else:
                    output(
                        2, app_name,
                        'Glyph: %s\tElement: %s not found @Layer: %s' %
                        (glyph.name, insert_shape_name, layer))

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Glyph: %s;\tInsert Element:%s @ %s.' %
                (glyph.name, insert_shape_name, '; '.join(process_layers)))
Ejemplo n.º 22
0
    def moveElement(self, offset_x, offset_y, method):
        # - Init
        glyph = eGlyph()
        font = pFont()

        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            wLayers = glyph._prepareLayers(pLayers)

            for layer in wLayers:
                selected_shapes = glyph.selectedAtShapes(index=False,
                                                         layer=layer,
                                                         deep=False)

                for shape, contour, node in selected_shapes:
                    wShape = pShape(shape)
                    if method == 'Shift':
                        wShape.shift(offset_x, offset_y)

                    elif method == 'Scale':
                        wShape.scale(1. + offset_x / 100.,
                                     1. + offset_y / 100.)

                    elif method == 'Shear':
                        wShape.shear(radians(offset_x), radians(offset_y))

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Element: %s @ %s.' % (method, '; '.join(wLayers)))

        # - Set Undo
        #glyph.updateObject(glyph.activeLayer(), '%s @ %s.' %(method, glyph.activeLayer().name), verbose=False)

        # - Finish it
        glyph.update()
Ejemplo n.º 23
0
    def shape_roundTransform(self):
        process_glyphs = getProcessGlyphs(pMode)

        for glyph in process_glyphs:
            process_layers = glyph._prepareLayers(pLayers)

            for layer in process_layers:
                selected_shapes = glyph.selectedAtShapes(index=False,
                                                         layer=layer,
                                                         deep=False)

                if len(selected_shapes):
                    wShape = eShape(selected_shapes[0][0])
                    wShape.round()
                else:
                    for s in glyph.shapes(layer, extend=eShape):
                        s.round()

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Round Element transformation data @ %s.' %
                '; '.join(process_layers))

        self.reset_fileds()
Ejemplo n.º 24
0
 def table_refresh(self):
     if self.rad_glyph.isChecked(): self.pMode = 0
     if self.rad_window.isChecked(): self.pMode = 1
     if self.rad_selection.isChecked(): self.pMode = 2
     if self.rad_font.isChecked(): self.pMode = 3
     self.data_glyphs = getProcessGlyphs(self.pMode)
Ejemplo n.º 25
0
    def alignShapes(self):
        # - Helpers
        def getShapeBounds(work_shapes):
            tmp_bounds = [shape.bounds() for shape in work_shapes]
            shape_min_X, shape_min_Y, shape_max_X, shape_max_Y = map(
                set, zip(*tmp_bounds))
            return (min(shape_min_X), min(shape_min_Y), max(shape_max_X),
                    max(shape_max_Y))

        def getAlignDict(bounds_tuple):
            align_dict = {
                'L': bounds_tuple[0],
                'R': bounds_tuple[2],
                'C': bounds_tuple[2] / 2,
                'B': bounds_tuple[1],
                'T': bounds_tuple[3],
                'E': bounds_tuple[3] / 2
            }

            return align_dict

        # - Init
        user_mode = self.align_mode[self.cmb_align_mode.currentText]
        user_x = self.align_x[self.cmb_align_x.currentText]
        user_y = self.align_y[self.cmb_align_y.currentText]
        keep_x, keep_y = True, True

        if user_x == 'K':
            keep_x = False
            user_x = 'L'
        if user_y == 'X':
            keep_y = False
            user_y = 'B'

        process_glyphs = getProcessGlyphs(pMode)

        # - Process
        for glyph in process_glyphs:
            selection = glyph.selectedAtShapes(deep=False)
            wLayers = glyph._prepareLayers(pLayers)

            for layerName in wLayers:
                glyph_shapes = glyph.shapes(layerName, extend=eShape)
                work_shapes = [
                    glyph_shapes[index]
                    for index in list(set([item[0] for item in selection]))
                ]

                if user_mode == 'CC':  # Align shapes to shapes
                    if 1 < len(work_shapes) < 3:
                        sh1, sh2 = work_shapes
                        sh1.alignTo(sh2, user_x + user_y, (keep_x, keep_y))

                    elif len(work_shapes) > 2:
                        shape_bounds = getShapeBounds(work_shapes)
                        align_type = getAlignDict(shape_bounds)
                        target = Coord(align_type[user_x], align_type[user_y])

                        for shape in work_shapes:
                            shape.alignTo(target, user_x + user_y,
                                          (keep_x, keep_y))

                elif user_mode == 'RC':  # Align shapes to shapes in reverse order
                    if 1 < len(work_shapes) < 3:
                        sh1, sh2 = work_shapes
                        sh2.alignTo(sh1, user_x + user_y, (keep_x, keep_y))

                    elif len(work_shapes) > 2:
                        shape_bounds = getShapeBounds(work_shapes)
                        align_type = getAlignDict(shape_bounds)
                        target = Coord(align_type[user_x], align_type[user_y])

                        for shape in reversed(work_shapes):
                            shape.alignTo(target, user_x + user_y,
                                          (keep_x, keep_y))

                # !!! To be implemented
                elif user_mode == 'CN':  # Align shape to node
                    pass

                elif user_mode == 'NN':  # Align a node on shape to node on another
                    pass

                else:
                    metrics = pFontMetrics(glyph.package)
                    max_layer_y = max([
                        metrics.getXHeight(layerName),
                        metrics.getCapsHeight(layerName),
                        metrics.getAscender(layerName)
                    ])
                    min_layer_y = min([0, metrics.getDescender(layerName)])
                    layer_bounds = QtCore.QRect(
                        0, 0, glyph.getAdvance(layerName),
                        abs(max_layer_y) + abs(min_layer_y))

                    if user_mode == 'CL':  # Align all shapes in given Layer
                        shape_bounds = (layer_bounds.x(), layer_bounds.y(),
                                        layer_bounds.x() +
                                        layer_bounds.width(),
                                        layer_bounds.y() +
                                        layer_bounds.height())

                    elif user_mode == 'CMX':  # Align all shapes to X height
                        height = metrics.getXHeight(layerName)
                        shape_bounds = (layer_bounds.x(), 0.,
                                        layer_bounds.x() +
                                        layer_bounds.width(), height)

                    elif user_mode == 'CMC':  # Align all shapes to Caps height
                        height = metrics.getCapsHeight(layerName)
                        shape_bounds = (layer_bounds.x(), 0.,
                                        layer_bounds.x() +
                                        layer_bounds.width(), height)

                    elif user_mode == 'CMA':  # Align all shapes to Ascender height
                        height = metrics.getAscender(layerName)
                        shape_bounds = (layer_bounds.x(), 0.,
                                        layer_bounds.x() +
                                        layer_bounds.width(), height)

                    elif user_mode == 'CMD':  # Align all shapes to Ascender height
                        height = metrics.getDescender(layerName)
                        shape_bounds = (layer_bounds.x(), 0.,
                                        layer_bounds.x() +
                                        layer_bounds.width(), height)

                    align_type = getAlignDict(shape_bounds)
                    target = Coord(align_type[user_x], align_type[user_y])

                    for shape in glyph_shapes:
                        shape.alignTo(target, user_x + user_y,
                                      (keep_x, keep_y))

            glyph.update()
            glyph.updateObject(
                glyph.fl, 'Glyph: %s;\tAction: Align Shapes @ %s.' %
                (glyph.name, '; '.join(wLayers)))