@frederik ah, that is super helpful!
How did I miss this great feature?
Thanks again
Posts made by jo
-
RE: Help with code & combining idea
-
RE: Help with code & combining idea
@frederik
Sad that the forum will be discontinued, so thanks a lot for keeping it up for so long and leaving it in read only mode.I will still try to post one more question, since I am frequently wondering how to do that in a clever way.
Like in the example above I usually try to have all the settings (like the definition of the page dimensions) in one place and before doing any drawing.
But I can only get the width if there is already a page (or it will be the default 1000).
How could I get the dimenations of eg an A3 page without callingnewPage('A3')
?Again thanks for drawbot and the forum. See you on discord!
-
RE: Help with code & combining idea
aah, untested last minute changes. I changed the variable names to something more reasonable but forgot one instance.
cell_h
should belabel_h
.PW, PH = 842, 1190 # A3 page width and height page_margin = 40 # the margin for the whole page amount = 50 # how many labels to draw in total per_page = 10 # how many labels per page gap = 10 # the gap between the labels # the next line calculates the heigth for the label label_h = (PH - ((per_page-1)*gap) - 2 * page_margin ) / per_page for i in range(amount): if i % per_page == 0: newPage(PW, PH) y = PH - page_margin - label_h rect(page_margin, y, width() - 2*page_margin, label_h) y -= label_h + gap
-
RE: Help with code & combining idea
you could new make an A3 page with
newPage('A3')
and then draw several of the textboxes on that page. basically take thenewPage
out of the loop and instead change the position of each new label.PW, PH = 842, 1190 # A3 page width and height page_margin = 40 # the margin for the whole page amount = 50 # how many labels to draw in total per_page = 10 # how many labels per page gap = 10 # the gap between the labels # the next line calculates the heigth for the label label_h = (PH - ((per_page-1)*gap) - 2 * page_margin ) / per_page for i in range(amount): if i % per_page == 0: newPage(PW, PH) y = PH - page_margin - cell_h rect(page_margin, y, width() - 2*page_margin, label_h) y -= label_h + gap
-
RE: Defining lineHeight and first baseline: status?
thanks for clarifying.
one thing that made me wonder when reading the unconventional UPM of 550: might this be related to this bug: https://github.com/typemytype/drawbot/issues/555#issuecomment-1948050444.as @monomonnik suggests I also tried a simpler script with Mutator Sans and I think this does what you expect?
txt = 'lestextessociologiques'.upper() fnt = 'MutatorSans.ttf' fnt_s = 24 lh = 32 lh_shift = -3 rows = 11 newPage('A4') txt_l = len(txt) fstr = FormattedString(fontSize = fnt_s, font = fnt) for r_i in range(rows): for t_i in range(txt_l): fstr.append(txt[(t_i + r_i)%txt_l], font = fnt, fontSize = fnt_s, lineHeight = lh, fontVariations={'wght': 1000/rows * r_i, 'wdth': 1000/txt_l*t_i}) fstr.append('\n') lh += lh_shift if r_i < rows/2 else -lh_shift text(fstr, (20, height() - 100))
otherwise just using a
text()
for each line might me a way?txt = 'lestextessociologiques'.upper() fnt = '/Users/jo/Desktop/MutatorSans.ttf' fnt_s = 24 lh = 50 lh_shift = -3 rows = 11 newPage('A4') txt_l = len(txt) y = height() - 100 for r_i in range(rows): fstr = FormattedString(fontSize = fnt_s, font = fnt) for t_i in range(txt_l): fstr.append(txt[(t_i + r_i)%txt_l], font = fnt, fontSize = fnt_s, fontVariations={'wght': 1000/rows * r_i, 'wdth': 1000/txt_l*t_i}) text(fstr, (10, y)) lh += lh_shift if r_i < rows/2 else -lh_shift y -= lh
-
RE: Defining lineHeight and first baseline: status?
not sure I understand your question correctly.
my assumption is you want to specify a position for the first baseline and have the textbox draw the text so the first line is at that given position no matter the lineheight or font size?
the following script should do that. I tested a few fonts, fontSizes and lineHeights.# ----------------------------------- # S E T T I N G S fnt = 'Helvetica' fnt_s = 16 # the fontsize lh = fnt_s * 1.6 # the lineheight txt = 'Testing the position of the baseline and the setting of the line height in drawBot. '*30 tbx_x = 100 # x position of the textbox frst_bl_y = 657 # the exact position of the first baseline within the textbox tbx_w = 350 # textbox width tbx_h = 400 # textbox heigth # -------------- # F U N C T I O N S def calc_baseline_offset(fnt, fnt_s, lh): '''calculates the position of the first baseline of a placeholder textbox and returns the distance from the top edge of the textbox''' fstr = FormattedString('Hm', font = fnt, fontSize = fnt_s, lineHeight = lh) temp_first_baseline = textBoxBaselines(fstr, (0, 0, fnt_s * 3, fnt_s * lh))[0][1] return temp_first_baseline - (fnt_s * lh) # ----------------------------------- # D R A W I N G S newPage('A4') fstr = FormattedString(txt, font = fnt, fontSize = fnt_s, lineHeight = lh) rect(tbx_x - 20, frst_bl_y, tbx_w + 40, -1) # drawing the first baseline y_shift = calc_baseline_offset(fnt, fnt_s, lh) tbx_y = frst_bl_y - tbx_h - y_shift # the y position for the textbox so that the first baseline stays at the given value fill(1, 0, 0, .1) rect(tbx_x, tbx_y, tbx_w, tbx_h) textBox(fstr, (tbx_x, tbx_y, tbx_w, tbx_h)) # drawing all the baselines for x, y in textBoxBaselines(fstr, (tbx_x, tbx_y, tbx_w, tbx_h)): rect(tbx_x, y, tbx_w, -1)
-
RE: QRCodeGenerator(size, message)
I ran into the same issue a few weeks ago and @frederik actually posted another solution in the other QR code thread:
going through the pixels and checking the lightness/brightness:
https://forum.drawbot.com/topic/397/qr-code-with-type?_=1681732270808Using a module has the nice advantage of checking the size of the QR code after generating it.
-
RE: trim box in pdfs
@monomonnik thanks, yes that is how i 'solved' it but when doing that with several files it gets a bit tedious. not a big deal but maybe it is can be easily stored during the export in drawbot.
-
trim box in pdfs
hello,
Whenever I place a pdf in InDesign I get the error message:
'Cannot crop to trim box. Either the trim box is not defined, or is empty'.Is there a way to include a trimbox in the pdfs saved from Drawbot or is this InDesign related?
thanks j -
RE: when to apply paragraphBottomSpacing
oké
I had some small hope but thanks for testing and clarifying!not very elegant but kind of working:
txt = 'Some Text\nwith new lines\rIs a return\na new line\ror a new paragraph?' paras = [[l + '\n' for l in p.split('\n')] for p in txt.split('\r')] newPage(150, 150) fstr = FormattedString() for para in paras: for l in para: extra_space = 5 if l == para[-1] else 0 fstr.append(l, paragraphBottomSpacing = extra_space) text(fstr, (20, 110))
-
when to apply paragraphBottomSpacing
I tried to use
paragraphBottomSpacing
and was hoping that drawbot would interpret\n
as still the same paragraph and only apply the extra white space once I use a\r
.So there should only be extra white space after the line 'with new lines' but not after the other newlines.
txt = 'Some Text\nwith new lines\rIs a return\na new line\ror a new paragraph?' fstr = FormattedString(txt, paragraphBottomSpacing=3) newPage(150, 150) text(fstr, (20, 110))
hope that makes sense, thanks
-
RE: Help combining ideas
you instantiate the
BezierPath
outside the loop and then draw the text in every round of the loop. just put thebp = BezierPath()
inside the loop. -
RE: Help combining ideas
hi, I think the
BezierPath
text does not accept variable font settings. You can first draw the text into aFormattedString()
and then add that to theBezierPath
.bp = BezierPath() fstr = FormattedString("JUICY", font='Skia-Regular', fontSize=80, fontVariations = {'wght' : curr_value}) bp.text(fstr, (10, 10))
hope that helps!
-
RE: Local modules don’t update
reload
is python 2
afaik in python 3.4 and newer you are supposed to use:import importlib importlib.reload(module)
good luck!
-
RE: Change the value of a bool with (arrow) keys
this should work already.
when you select the bool (
True
orFalse
) and then press the Cmd + arrow keys the value should change. -
RE: Tutorial Request:Randomize Each Character Color in text
you will need to use a loop to iterate over your list of characters and append them to a formattedString.
first initiate the
formattedString
:f_str = FormattedString(font = myFont, fontSize = pointSize)
then iterate over your list:
for ch in wordText:
select a random color inside the loop and append the character to the
formattedString
ch_col = random.choice(colors) f_str.append(ch, fill = ch_col)
finally draw your
textBox
with theformattedString
textBox(f_str, box, align="left")
so the last four lines of your code should be:
f_str = FormattedString(font = myFont, fontSize = pointSize) for ch in wordText: ch_col = random.choice(colors) f_str.append(ch, fill = ch_col) textBox(f_str, box, align="left")
good luck!
-
RE: Chess board in one loop
@monomonnik
yes and no.
in the chessboard examples it does not really matter if you go by columns or by rows.
but yes the first returned value is the quotienti//n
orint(i/n)
and the second returned value is the remainder (modulo)i % n
. -
RE: Chess board in one loop
@monomonnik
perfect place to usedivmod
.
this:x = i % 8 y = int(i/8)
could be written like:
x, y = divmod(i, 8)
it will return the quotient (x) and the remainder (y).
-
RE: Random values inside the axes of a variable font
I am not quite sure what exactly you are asking but the get a random integer value inside a range you could use
randint(min_value, max_value)
. This works for integers. To get a random value between 100 and 900 you would userandint(100, 900)
.
If you have a smaller range and want fractions as well you could usemin_value + random() * (max_value - min_value)
eg100 + (900-100) * random()
I hope that helps, good luck! -
binary counting with a 7 segment LCD
here is some code to draw a 7 segment LCD and use the segments to count up to 127 (2**7-1).
class digit(object): """a digit of the lcd display""" def __init__(self, pos, size, seg_l, seg_h): self.pos = pos self.size = size self.seg_l = seg_l self.seg_h = seg_h def draw_segment(self, indx, l, h): seg_poss = [ ( 0, self.size), ( self.size/2, self.size/2), ( self.size/2, -self.size/2), ( 0, -self.size), (-self.size/2, -self.size/2), (-self.size/2, self.size/2), ( 0, 0), ] x = self.pos[0] + seg_poss[indx][0] y = self.pos[1] + seg_poss[indx][1] if indx in [1, 2, 4, 5]: polygon( (x, y + l/2), (x - h/2, y + l/2 - h/2), (x - h/2, y - l/2 + h/2), (x, y - l/2), (x + h/2, y - l/2 + h/2), (x + h/2, y + l/2 - h/2),) else: polygon( (x + l/2, y), (x + l/2 - h/2, y + h/2), (x - l/2 + h/2, y + h/2), (x - l/2, y), (x - l/2 + h/2, y - h/2), (x + l/2 - h/2, y - h/2),) def draw(self, num): for s in range(7): if (num & (1<<s)): self.draw_segment(s, self.seg_l, self.seg_h) # --------------------------- int_to_bin = { 0 : 63, 1 : 6, 2 : 91, 3 : 79, 4 : 102, 5 : 109, 6 : 125, 7 : 7, 8 : 127, 9 : 111, } # --------------------------- PW, PH = 500, 500 d = digit((0, 0), PW/3, 150, 30) d_int = digit((PW*.5, -PH*.4), 16, 14, 4) for n in range(128): assert (0 <= n < 128), "Values should be higher than -1 and smaller than 128!" newPage(PW, PH) fill(.2) rect(0, 0, PW, PH) translate(PW/2, PH/2) skew(2) fill(0, 1, 0) d.seg_h = n+4 d.draw(n) with savedState(): for i in reversed(str(n)): translate(-30) d_int.draw(int_to_bin[int(i)])
should make animations like this: