kopia lustrzana https://github.com/EmbroidePy/pyembroidery
575 wiersze
20 KiB
Python
575 wiersze
20 KiB
Python
import pyembroidery
|
|
from pyembroidery import (
|
|
CONTINGENCY_SEQUIN_UTILIZE,
|
|
decode_embroidery_command,
|
|
STITCH,
|
|
COLOR_CHANGE,
|
|
NEEDLE_SET,
|
|
TRIM,
|
|
JUMP,
|
|
SEQUIN_MODE,
|
|
SEQUIN_EJECT,
|
|
STOP,
|
|
SLOW,
|
|
FAST,
|
|
END,
|
|
get_common_name_dictionary,
|
|
COMMAND_MASK,
|
|
)
|
|
from pyembroidery.WriteHelper import write_string_utf8
|
|
|
|
WRITES_SPEEDS = True
|
|
SEQUIN_CONTINGENCY = CONTINGENCY_SEQUIN_UTILIZE
|
|
|
|
|
|
def write(pattern, f, settings=None):
|
|
writer = GenericWriter(pattern, f, settings)
|
|
writer.write()
|
|
|
|
|
|
class GenericWriter:
|
|
"""
|
|
Generic Writer will write generic data fit to a formatted set of strings.
|
|
|
|
Blocks are established by the first segment.
|
|
Colors are established by the first segment or the first segment after a color change or by a needle_set.
|
|
Documents are established by the first segment, or the first segment after an end.
|
|
|
|
Segment is the default for any-command. Specific commands override segment.
|
|
|
|
stitch is the default stitch.
|
|
stitch_first overrides stitch for the first stitch in a block.
|
|
stitch_last overrides stitch for the last stitch in a block.
|
|
|
|
trims and jumps occurring before a color change belong to the previous color.
|
|
trims and jumps occurring after a color change belong to the next color.
|
|
|
|
Missing segments are treated as if they never existed. Value properties will differ if segments are excluded.
|
|
"""
|
|
|
|
def __init__(self, pattern, f, settings):
|
|
self.pattern = pattern
|
|
self.f = f
|
|
self.settings = settings
|
|
self.metadata_entry = settings.get("metadata_entry", None)
|
|
self.thread_entry = settings.get("thread_entry", None)
|
|
self.pattern_start = settings.get("pattern_start", None)
|
|
self.pattern_end = settings.get("pattern_end", None)
|
|
self.document_start = settings.get("document_start", None)
|
|
self.document_end = settings.get("document_end", None)
|
|
self.color_start = settings.get("color_start", None)
|
|
self.color_end = settings.get("color_end", None)
|
|
self.color_join = settings.get("color_join", None)
|
|
self.block_start = settings.get("block_start", None)
|
|
self.block_end = settings.get("block_end", None)
|
|
self.block_join = settings.get("block_join", None)
|
|
self.segment_start = settings.get("segment_start", None)
|
|
self.segment = settings.get("segment", None)
|
|
self.segment_end = settings.get("segment_end", None)
|
|
self.segment_join = settings.get("segment_join", None)
|
|
self.stitch_first = settings.get("stitch_first", None)
|
|
self.stitch_last = settings.get("stitch_last", None)
|
|
self.stitch = settings.get("stitch", None)
|
|
self.stop = settings.get("stop", None)
|
|
self.jump = settings.get("jump", None)
|
|
self.trim = settings.get("trim", None)
|
|
self.needle_set = settings.get("needle_set", None)
|
|
self.color_change = settings.get("color_change", None)
|
|
self.sequin = settings.get("sequin", None)
|
|
self.sequin_mode = settings.get("sequin_mode", None)
|
|
self.slow = settings.get("slow", None)
|
|
self.fast = settings.get("fast", None)
|
|
self.end = settings.get("end", None)
|
|
|
|
self.format_dictionary = {}
|
|
self.pattern_established = False
|
|
self.document_established = False
|
|
self.color_established = False
|
|
self.block_established = False
|
|
self.document_index = -1
|
|
self.thread = None
|
|
self.thread_index = -1
|
|
self.stitch_index = -1
|
|
self.color_index = -1
|
|
self.block_index = -1
|
|
self.dx = 0
|
|
self.dy = 0
|
|
self.xx = 0
|
|
self.yy = 0
|
|
self.last_x = 0
|
|
self.last_y = 0
|
|
self.z = 0.0
|
|
self.z_increment = settings.get("stitch_z_travel", 10.0)
|
|
self.command_index = 0
|
|
|
|
self.current_stitch = None
|
|
self.x = None
|
|
self.y = None
|
|
self.command = None
|
|
self.cmd = None
|
|
self.thread = None
|
|
self.needle = None
|
|
self.order = None
|
|
self.cmd_str = None
|
|
|
|
self.block_closing = False
|
|
self.color_closing = False
|
|
self.document_closing = False
|
|
|
|
self.block_opening = False
|
|
self.color_opening = False
|
|
self.document_opening = False
|
|
|
|
def write_opens(self):
|
|
if self.document_opening:
|
|
self.document_opening = False
|
|
if self.document_start is not None:
|
|
write_string_utf8(self.f, self.document_start.format_map(self.format_dictionary))
|
|
if self.color_opening:
|
|
self.color_opening = False
|
|
if self.color_join is not None and self.color_index != 0:
|
|
write_string_utf8(self.f, self.color_join.format_map(self.format_dictionary))
|
|
if self.color_start is not None:
|
|
write_string_utf8(self.f, self.color_start.format_map(self.format_dictionary))
|
|
if self.block_opening:
|
|
self.block_opening = False
|
|
if self.block_join is not None and self.block_index != 0:
|
|
write_string_utf8(self.f, self.block_join.format_map(self.format_dictionary))
|
|
if self.block_start is not None:
|
|
write_string_utf8(self.f, self.block_start.format_map(self.format_dictionary))
|
|
|
|
def write_closes(self):
|
|
if self.block_closing:
|
|
self.block_closing = False
|
|
if self.block_end is not None:
|
|
write_string_utf8(self.f, self.block_end.format_map(self.format_dictionary))
|
|
if self.color_closing:
|
|
self.color_closing = False
|
|
if self.color_end is not None:
|
|
write_string_utf8(self.f, self.color_end.format_map(self.format_dictionary))
|
|
if self.document_closing:
|
|
self.document_closing = False
|
|
if self.document_end is not None:
|
|
write_string_utf8(self.f, self.document_end.format_map(self.format_dictionary))
|
|
|
|
def get_write_segment(self, cmd):
|
|
# SEQUIN_MODE
|
|
if cmd == SEQUIN_MODE and self.sequin_mode is not None:
|
|
return self.sequin_mode
|
|
|
|
# SEQUIN
|
|
if cmd == SEQUIN_EJECT and self.sequin is not None:
|
|
return self.sequin
|
|
|
|
# STITCH
|
|
if cmd == STITCH and self.stitch is not None:
|
|
return self.stitch
|
|
|
|
# TRIM
|
|
if cmd == TRIM and self.trim is not None:
|
|
return self.trim
|
|
|
|
# JUMP
|
|
if cmd == JUMP and self.jump is not None:
|
|
return self.jump
|
|
|
|
# COLOR CHANGE
|
|
if cmd == COLOR_CHANGE and self.color_change is not None:
|
|
return self.color_change
|
|
|
|
# NEEDLE SET
|
|
if cmd == NEEDLE_SET and self.needle_set is not None:
|
|
return self.needle_set
|
|
|
|
# STOP COMMAND
|
|
if cmd == STOP and self.stop is not None:
|
|
return self.stop
|
|
|
|
# SLOW COMMAND
|
|
if cmd == SLOW and self.slow is not None:
|
|
return self.slow
|
|
|
|
# FAST COMMAND
|
|
if cmd == FAST and self.fast is not None:
|
|
return self.fast
|
|
|
|
# END COMMAND
|
|
if cmd == END and self.end is not None:
|
|
return self.end
|
|
|
|
# GENERIC SEGMENT
|
|
return self.segment
|
|
|
|
def set_document_statistics(self):
|
|
pattern = self.pattern
|
|
self.format_dictionary.update(pattern.extras)
|
|
|
|
bounds = pattern.bounds() # convert to mm.
|
|
width = bounds[2] - bounds[0]
|
|
height = bounds[3] - bounds[1]
|
|
|
|
stitch_counts = {}
|
|
for s in pattern.stitches:
|
|
command = s[2] & COMMAND_MASK
|
|
if command in stitch_counts:
|
|
stitch_counts[command] += 1
|
|
else:
|
|
stitch_counts[command] = 1
|
|
|
|
names = get_common_name_dictionary()
|
|
for name in names:
|
|
value = names[name].lower()
|
|
self.format_dictionary[value + "_count"] = stitch_counts.get(name,0)
|
|
self.format_dictionary.update(
|
|
{
|
|
"stitch_total": pattern.count_stitches(),
|
|
"thread_total": pattern.count_threads(),
|
|
"extents_left": bounds[0],
|
|
"extends_top": bounds[1],
|
|
"extends_right": bounds[2],
|
|
"extends_bottom": bounds[3],
|
|
"extends_width": width,
|
|
"extends_height": height,
|
|
"extents_left_mm": bounds[0] / 10.0,
|
|
"extends_top_mm": bounds[1] / 10.0,
|
|
"extends_right_mm": bounds[2] / 10.0,
|
|
"extends_bottom_mm": bounds[3] / 10.0,
|
|
"extends_width_mm": width / 10.0,
|
|
"extends_height_mm": height / 10.0,
|
|
}
|
|
)
|
|
|
|
def update_positions(self, x, y, cmd):
|
|
self.dx = x - self.last_x
|
|
self.dy = y - self.last_y
|
|
idx = int(round(x - self.xx))
|
|
idy = int(round(y - self.yy))
|
|
self.xx += idx
|
|
self.yy += idy
|
|
self.format_dictionary.update(
|
|
{
|
|
"x": x,
|
|
"y": y,
|
|
"z": self.z,
|
|
"_x": -x,
|
|
"_y": -y,
|
|
"dx": self.dx,
|
|
"dy": self.dy,
|
|
"idx": idx,
|
|
"idy": idy,
|
|
"_idx": -idx,
|
|
"_idy": -idy,
|
|
"ix": self.xx,
|
|
"iy": self.yy,
|
|
"_ix": -self.xx,
|
|
"_iy": -self.yy,
|
|
"last_x": self.last_x,
|
|
"last_y": self.last_y,
|
|
"_last_x": -self.last_x,
|
|
"_last_y": -self.last_y,
|
|
}
|
|
)
|
|
if cmd == STITCH:
|
|
self.z += self.z_increment
|
|
self.last_x = x
|
|
self.last_y = y
|
|
|
|
def update_command(self):
|
|
try:
|
|
self.current_stitch = self.pattern.stitches[self.command_index]
|
|
|
|
self.x, self.y, self.command = self.current_stitch
|
|
self.cmd, self.thread, self.needle, self.order = decode_embroidery_command(
|
|
self.command
|
|
)
|
|
self.cmd_str = pyembroidery.get_common_name_dictionary()[self.cmd]
|
|
except IndexError:
|
|
self.current_stitch = None
|
|
self.x = None
|
|
self.y = None
|
|
self.command = None
|
|
self.cmd = None
|
|
self.thread = None
|
|
self.needle = None
|
|
self.order = None
|
|
self.cmd_str = None
|
|
self.format_dictionary.update(
|
|
{
|
|
"index": self.command_index,
|
|
"command": self.command,
|
|
"cmd_str": self.cmd_str,
|
|
"cmd": self.cmd,
|
|
"cmd_thread": self.thread,
|
|
"cmd_needle": self.needle,
|
|
"cmd_order": self.order,
|
|
}
|
|
)
|
|
|
|
def open_pattern(self):
|
|
if not self.pattern_established:
|
|
self.pattern_established = True
|
|
if self.pattern_start is not None:
|
|
write_string_utf8(
|
|
self.f, self.pattern_start.format_map(self.format_dictionary)
|
|
)
|
|
|
|
def open_document(self):
|
|
# DOCUMENT START
|
|
if not self.document_established:
|
|
self.document_established = True
|
|
self.document_index += 1
|
|
self.document_opening = True
|
|
self.color_index = 0
|
|
|
|
self.format_dictionary.update(
|
|
{
|
|
"document_index": self.document_index,
|
|
"document_index1": self.document_index + 1,
|
|
"color_index": self.color_index,
|
|
"color_index1": self.color_index + 1,
|
|
"block_index": self.block_index,
|
|
"block_index1": self.block_index + 1,
|
|
}
|
|
)
|
|
|
|
def open_color(self):
|
|
# COLOR START
|
|
if not self.color_established:
|
|
self.color_established = True
|
|
self.thread_index += 1
|
|
self.color_opening = True
|
|
|
|
self.thread = self.pattern.get_thread_or_filler(self.thread_index)
|
|
self.block_index = 0
|
|
self.color_index += 1
|
|
self.format_dictionary.update(
|
|
{
|
|
"document_index": self.document_index,
|
|
"document_index1": self.document_index + 1,
|
|
"color_index": self.color_index,
|
|
"color_index1": self.color_index + 1,
|
|
"block_index": self.block_index,
|
|
"block_index1": self.block_index + 1,
|
|
}
|
|
)
|
|
|
|
def open_block(self):
|
|
# BLOCK START
|
|
if not self.block_established:
|
|
self.block_established = True
|
|
self.block_index += 1
|
|
self.block_opening = True
|
|
self.format_dictionary.update(
|
|
{
|
|
"document_index": self.document_index,
|
|
"document_index1": self.document_index + 1,
|
|
"color_index": self.color_index,
|
|
"color_index1": self.color_index + 1,
|
|
"block_index": self.block_index,
|
|
"block_index1": self.block_index + 1,
|
|
}
|
|
)
|
|
|
|
def write_segment(self, segment):
|
|
# SEGMENT
|
|
if self.segment_start is not None:
|
|
write_string_utf8(self.f, self.segment_start.format_map(self.format_dictionary))
|
|
|
|
write_string_utf8(self.f, segment.format_map(self.format_dictionary))
|
|
|
|
# SEGMENT JOIN
|
|
if self.segment_join is not None:
|
|
write_string_utf8(self.f, self.segment_join.format_map(self.format_dictionary))
|
|
|
|
# SEGMENT_END
|
|
if self.segment_end is not None:
|
|
write_string_utf8(self.f, self.segment_end.format_map(self.format_dictionary))
|
|
|
|
def close_pattern(self):
|
|
if self.pattern_established:
|
|
self.pattern_established = False
|
|
if self.pattern_end is not None:
|
|
write_string_utf8(
|
|
self.f, self.pattern_end.format_map(self.format_dictionary)
|
|
)
|
|
|
|
def close_document(self):
|
|
# DOCUMENT END
|
|
if self.document_established:
|
|
self.document_established = False
|
|
self.document_closing = True
|
|
|
|
def close_color(self):
|
|
# COLOR END
|
|
if self.color_established:
|
|
self.color_established = False
|
|
self.color_closing = True
|
|
|
|
def close_block(self):
|
|
# BLOCK END
|
|
if self.block_established:
|
|
self.block_established = False
|
|
self.block_closing = True
|
|
|
|
def write(self):
|
|
# DOCUMENT STATISTICS
|
|
self.set_document_statistics()
|
|
|
|
self.open_pattern()
|
|
if self.metadata_entry is not None:
|
|
for i, key in enumerate(self.pattern.extras):
|
|
value = self.pattern.extras[key]
|
|
self.format_dictionary.update({
|
|
"metadata_index": i,
|
|
"metadata_key": str(key),
|
|
"metadata_value": str(value),
|
|
})
|
|
write_string_utf8(
|
|
self.f, self.metadata_entry.format_map(self.format_dictionary)
|
|
)
|
|
|
|
if self.thread_entry is not None:
|
|
for i, thread in enumerate(self.pattern.threadlist):
|
|
self.format_dictionary.update({
|
|
"thread_index": i,
|
|
"thread_color": thread.hex_color(),
|
|
"thread_description": thread.description,
|
|
"thread_brand": thread.brand,
|
|
"thread_catalog_number": thread.catalog_number,
|
|
"thread_chart": thread.chart,
|
|
"thread_details": thread.details,
|
|
"thread_weight": thread.weight,
|
|
"thread_red": thread.get_red(),
|
|
"thread_green": thread.get_green(),
|
|
"thread_blue": thread.get_blue(),
|
|
})
|
|
write_string_utf8(
|
|
self.f, self.thread_entry.format_map(self.format_dictionary)
|
|
)
|
|
for self.command_index in range(0, len(self.pattern.stitches)):
|
|
self.update_command()
|
|
write_segment = self.get_write_segment(self.cmd)
|
|
|
|
# MAIN CODE, there is something to write.
|
|
if write_segment is not None:
|
|
if isinstance(write_segment, dict):
|
|
key, default = write_segment[None]
|
|
key = key.format_map(self.format_dictionary)
|
|
write_segment = write_segment.get(key, default)
|
|
self.update_positions(self.x, self.y, self.cmd)
|
|
if self.cmd == SEQUIN_MODE:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# SEQUIN
|
|
if self.cmd == SEQUIN_EJECT:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# STITCH
|
|
if self.cmd == STITCH:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# TRIM
|
|
if self.cmd == TRIM:
|
|
self.open_document()
|
|
self.open_color()
|
|
|
|
# JUMP
|
|
if self.cmd == JUMP:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# COLOR CHANGE
|
|
if self.cmd == COLOR_CHANGE:
|
|
self.open_document()
|
|
|
|
# NEEDLE SET
|
|
if self.cmd == NEEDLE_SET:
|
|
self.open_document()
|
|
self.open_color()
|
|
|
|
# STOP COMMAND
|
|
if self.cmd == STOP:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# SLOW COMMAND
|
|
if self.cmd == SLOW:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# FAST COMMAND
|
|
if self.cmd == FAST:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
# END COMMAND
|
|
if self.cmd == END:
|
|
self.open_document()
|
|
self.open_color()
|
|
self.open_block()
|
|
|
|
self.write_opens()
|
|
self.write_segment(write_segment)
|
|
|
|
if self.cmd == SEQUIN_MODE:
|
|
pass
|
|
|
|
# SEQUIN
|
|
if self.cmd == SEQUIN_EJECT:
|
|
pass
|
|
|
|
# STITCH
|
|
if self.cmd == STITCH:
|
|
pass
|
|
|
|
# TRIM
|
|
if self.cmd == TRIM:
|
|
self.close_block()
|
|
|
|
# JUMP
|
|
if self.cmd == JUMP:
|
|
pass
|
|
|
|
# COLOR CHANGE
|
|
if self.cmd == COLOR_CHANGE:
|
|
self.close_block()
|
|
self.close_color()
|
|
|
|
# NEEDLE SET
|
|
if self.cmd == NEEDLE_SET:
|
|
pass
|
|
|
|
# STOP COMMAND
|
|
if self.cmd == STOP:
|
|
pass
|
|
|
|
# SLOW COMMAND
|
|
if self.cmd == SLOW:
|
|
pass
|
|
|
|
# FAST COMMAND
|
|
if self.cmd == FAST:
|
|
pass
|
|
|
|
# END COMMAND
|
|
if self.cmd == END:
|
|
self.close_block()
|
|
self.close_color()
|
|
self.close_document()
|
|
self.write_closes()
|
|
|
|
self.close_block()
|
|
self.close_color()
|
|
self.close_document()
|
|
self.close_pattern()
|