Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Setting text on multiple layers issue
#1
Hellois.
I'm on a mission to make an 'text atlass or sprite' ish plugin which will make the number of input characters to the power of two; combination 'sprite image'.
At the moment the code can generate one image atlass with n combinations. As a image has a limited combination spaces it will later add images as needed to make all the combinations over multiple images. But first i must understand how to set text which i hope someone would help out with.

What im struggling with is applying text. Im not able to set text on multiple layers. No matter what i do it seems like the ..WriteToCanvas() funciton only sets text to the original background layer. I'm unable to make a new layer and apply text to it. 

The function ..SetAndAnchorText() is where you would modify the code to help me out if possible, or give me some good pointer as i'm been struggling for a few days to many. Confused

Starting point:
The code works and can produce an image so you can see what i mean by atlass/sprite. Create a new 256x256 RGB_Image and run the plugin to se results. Then make a new same image and add the letter i to the end of .."Text for atlass" of the plugin. The expected result should be a whole image with text combinations in stride of two and the second should be roughly half the image with text. At the moment the code creates and error instead.

Code:
#!/usr/bin/env python

from gimpfu import *
from math import *
from time import sleep

def WriteToCanvas(image, drawable, x, y, text):
   return pdb.gimp_text_fontname(
   image,         # IMAGE      image      The image
   drawable,      # DRAWABLE   drawable   The affected drawable: (-1 for a new text layer)
   x,             # FLOAT      x          The x coordinate for the left of the text bounding box
   y,             # FLOAT      y          The y coordinate for the top of the text bounding box
   text,          # STRING     text       The text to generate
   -1,            # INT32      border     The size of the border: -1 <= border
   False,         # INT32      antialias  Antialiasing (TRUE or FALSE)
   26,            # FLOAT      size       The size of text in either pixels or points
   0,             # INT32      size_type  The units of specified size: PIXELS (0) or POINTS (1)
   'Monospace')   # STRING     fontname   The fontname (conforming to the X Logical Font Description Conventions)

# returns stride of 3 for characters that use kerning
def FindKerning(src):
   kerning = []
   idx1 = idx2 = 0
   while ~idx1:
       idx1 = SearchSrc(src, '(', idx2)
       idx2 = SearchSrc(src, ')', idx1)
       if idx1 < idx2 and abs(idx1-idx2) != 1:
           kerning += [src[idx1-1]] + src[idx1+1:idx2].split(',')
           src = src.replace(src[idx1:idx2+1], '', 1)
           idx1 = idx2 = 0
   return kerning + [src]

# return index for for instance of ..test in ..src at interval ..stride
def SearchSrc(src, test, after=0, stride=0):
   x = 0
   if not ~after:
       return -1
   if stride <= 0:
       stride = 1
   if after > 0:
       x += after
   while x < len(src):
       if src[x] == test:
           return x
       x += stride
   return -1

# ab(-1,0)cdef(-1,0)ghijk(-1,0)lmnop(-1,0)qr(-1,0)stuvwxyz01(-1,0)23456789!"#%&/()=?\*<>-_,.:;~@${}
def SetAndAnchorText(image, drawable, text, newLayer):
   # sleep(3)
   pdb.gimp_message(str('Ono line: \n')+str(text))
   textLayer = WriteToCanvas(image, drawable, 0, 0, text)
   # image.add_layer(textLayer, len(image.layers))
   layer = pdb.gimp_image_merge_visible_layers(image, 1)
   drawable.visible = False
   if newLayer:
       newLayer = gimp.Layer(image, "Background", image.width, image.height, RGB_IMAGE, 100, 3)
       image.add_layer(newLayer, 0)
       image.active_layer = image.layers[0]
       # pdb.gimp_drawable_edit_bucket_fill(newLayer, 1, 1, 1)
       # newLayer.update(0, 0, drawable.width, drawable.height)

# pdb.gimp_drawable_get_name(item)
def textAtlas(image, drawable, NotUsed, text_var, boolean_var, colorText, colorBackground, radio_var):
   # ab(-1,0)cde(2,-4)fg(3,1)h
   pdb.gimp_message(str('~~~~~~~~~~~~~~~~~~~~'))
   kerningParams = FindKerning(text_var)  # stride of 3 for chars that use kerning
   text_var = kerningParams[-1] # will always be plain ..text_var
   del kerningParams[-1] # remove ..text_var
   # pdb.gimp_message(str('text_var: ')+str(text_var))
   # pdb.gimp_message(str('kerning: ')+str(kerningParams))
   # return
   pdb.gimp_context_set_foreground(colorText)
   pdb.gimp_context_set_background(colorBackground)
   rowNumber = drawable.width/32
   gridNumber = rowNumber * (drawable.height/32)
   number = int(pow(len(text_var), 2))
   length = len(text_var)
   gimp.progress_init('The growing bar')

   count = 0
   wholeText = ''
   tempText = ''
   for char1 in text_var:
       for char2 in text_var:
           wholeText += char1+char2
           tempText += char1+char2
           count += 1
           if count == gridNumber:
               SetAndAnchorText(image, drawable, tempText, not text_var[-1] == char1 == char2)
               # apply, merge and adjust for kerning here
               tempText = ''
               count = 0
           if not count%rowNumber and count:
               tempText += '\n'
   if count:
       SetAndAnchorText(image, drawable, tempText, False)


   pdb.gimp_message(str('Done'))

# abcdefghijklmnopqrstuvwxyz
# ab(-1,0)cdef(-1,0)ghijk(-1,0)lmnop(-1,0)qr(-1,0)stuvwxyz01(-1,0)23456789
# ab(-1,0)cdef(-1,0)ghijk(-1,0)lmnop(-1,0)qr(-1,0)stuvwxyz01(-1,0)23456789!"#%&/()=?\*<>-_,.:;~@${}

register(
   "python-fu-textAtlas",
   "Make text paired utf-8'ish atlas",
   "Generate an grid with n pared two character, number and/or symbol into an atlas/sprite",
   "Drop Woodland", "https://github.com/TeaWave", "2021",
   "Make text atlas...",
   "", # type of image it works on (*, RGB, RGB*, RGBA, GRAY etc...)
   [
       (PF_IMAGE, "image", "takes current image", None),
       (PF_DRAWABLE, "drawable", "Input layer", None),
       (PF_INT8, "NotUsed", "Colors", 8),
       (PF_TEXT, "text_var", "Text for atlas", "ab(-1,0)cde(2,-4)fg(3,1)h"),
       (PF_BOOL,   "boolean_var", "boolean name", True),
       (PF_COLOR, "colorText", "Text color", (0.541, 0.831, 0.235, 1.0)),
       (PF_COLOR, "colorBackground", "Background color", (0.298, 0.361, 0.576, 1.0)),
       (PF_RADIO, "radio_var", "radio", "scale",
           (
               ("Scale to fit", "scale"),
               ("Fill to fit", "fill")
           )
       )
   ],
   [],
   textAtlas, menu="<Image>/Extra")  # second item is menu location

main()
Reply
#2
What a mess... no wonder you get lost in your own code with names as descriptive as "drawable" and "layer".

I couldn't completely fathom what you are trying to do but a couple of observations:

1) When you merge layers the merged layers are destroyed and the call returns a new layer which is the result of the merge. So after the merge you can no longer use the references to the initial layers (as you do in drawable.visible=false). In any case merging all visible layers is often overkill and somehow showing that you don't really know where your layers are. Your normally insert the layer where it needs to be and then merge down. You can also wonder if you need to do all that merging or if you aren't doing it too early, so you cannot check what your script dit after it crashed.

2) there are two ways to use gimp_text_fontname(): with a target drawable or without one. When you use a target drawable, the returned value from the call is a floating selection, and the proper way to handle it is to anchor it in the target drawable by calling gimp_floating_sel_anchor(floatingSel). No need to merge layers or else in that case, and an important difference with the merge is that your target layer remains the same.
Reply
#3
Input is greatly appreciated, so thanks Smile
I have gone through a few way to marge the text to an layer with partial success, but they have all always only added the text to one layer no matter what i did.
And as you mentioned "targeted drawable" i have notices that some or more of the layers name are in bold letters which im assume to be the target layer/s.
How do i set/get/unset target layer?
Reply
#4
(11-13-2021, 07:23 PM)FloppaDisk Wrote: Input is greatly appreciated, so thanks Smile
I have gone through a few way to marge the text to an layer with partial success, but they have all always only added the text to one layer no matter what i did.
And as you mentioned "targeted drawable" i have notices that some or more of the layers name are in bold letters which im assume to be the target layer/s.
How do i set/get/unset target layer?

Name in bold in the Layers list only indicates a layer without an alpha channel.

To add text to a layer directly:

Code:
textLayer = pdb.gimp_text_fontname(image, targetLayer, x, y, text, border, antialias, size, size_type, fontname)
pdb.gimp_floating_sel_anchor(textLayer)
# targetLayer still exists at this point
Reply


Forum Jump: