Page 1 of 1

Script to change all font sizes

PostPosted: Wed Feb 22, 2012 11:18 pm
by bwernick
Hi Folks, I'm new to this forum and would appreciate some help.

How do I write a script to change the font sizes of ALL text in a vector layer?

Re: Script to change all font sizes

PostPosted: Thu Feb 23, 2012 5:33 pm
by teknisyan
What version of PSP are you using? Language use for PSP Scripts is Python though PSP API's are not available publicly, if you want to code your own scripts. You can however create a script on PSP by using the RECORDING feature of PSP.

Here's the code of a script that I recorded on PSP where you will change the font size of a text on a vector layer.
Code: Select all
from PSPApp import *

def ScriptProperties():
    return {
        'Author': u'',
        'Copyright': u'',
        'Description': u'',
        'Host': u'PaintShop Photo Pro',
        'Host Version': u'13.00 Alpha 00000000.0000000000.00'
        }

def Do(Environment):
    # EnableOptimizedScriptUndo
    App.Do( Environment, 'EnableOptimizedScriptUndo', {
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default,
                'AutoActionMode': App.Constants.AutoActionMode.Match,
                'Version': ((13,0,0),1)
                }
            })

    # Text
    App.Do( Environment, 'TextEx', {
            'Visibility': True,
            'CreateAs': App.Constants.CreateAs.Vector,
            'Start': (150,220),
            'TextFlow': App.Constants.TextFlow.HorizontalDown,
            'TextType': App.Constants.TextType.TextBase,
            'Matrix': [
                1,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                1
            ],
            'AutoKern': True,
            'Kerning': 0,
            'Tracking': 0,
            'Leading': 0,
            'Font': u'Waltograph',
            'PointSize': 19,
            'Italic': False,
            'Bold': False,
            'Underline': False,
            'Strikethru': False,
            'AntialiasStyle': App.Constants.AntialiasEx.Sharp,
            'WarpText': True,
            'SetText': App.Constants.Justify.Center,
            'Fill': {
                'Color': (81,132,210),
                'Pattern': None,
                'Gradient': None,
                'Texture': None,
                'Art': None
                },
            'Stroke': {
                'Color': (64,64,64),
                'Pattern': None,
                'Gradient': None,
                'Texture': None,
                'Art': None
                },
            'LineWidth': 2,
            'LineStyle': {
                'Name': u'',
                'FirstCap': (u'Butt',0.25,0.25),
                'LastCap': (u'Butt',0.25,0.25),
                'FirstSegCap': (u'',0.25,0.25),
                'LastSegCap': (u'',0.25,0.25),
                'UseSegmentCaps': False,
                'Segments': None
                },
            'Join': App.Constants.JointStyle.Miter,
            'MiterLimit': 10,
            'Characters': u'Test',
            'Strings': None,
            'TextTarget': (0,0,[1],True),
            'PathTarget': None,
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default,
                'AutoActionMode': App.Constants.AutoActionMode.Match,
                'Version': ((13,0,0),1)
                }
            })



To know more about the Script recording on PSP, you can visit http://pnoy.me/mG for more information on recording and saving a script on PSP X3, which is virtually the same process if you are using PSP X4.

Re: Script to change all font sizes

PostPosted: Sun Apr 15, 2012 2:01 pm
by bwernick
Hi

I'm using version X2 but I don't think that the version has any bearing on the question.

I can set record macro, manually select a text item and edit the size. Then view the recorded macro but this doesn't help to solve my problem.


What I want to do in the Python script is to search for all text to change attributes like font-size, color...

So the question is, how to find all text in a pspImage?

Re: Script to change all font sizes

PostPosted: Sun Apr 15, 2012 3:45 pm
by LeviFiction
That's not altogether accurate Abiel. Corel published the APIs up through version X1. You just have to know where to look to download them.

Version number actually has a little to do with it as some commands or methods change between versions every so slightly. Though most of the base is the same so you're good with x2.

To get you started I recommend downloading the "Scripting for Script Authors" PDF guide which gives a good demonstration of moving through the layers of an image. The "Vector Merge Selected" script also gives a good example of how to tell if the currently selected vector is text, preset shape, or path.

And the API download shows you all of the commands and the parameters which really really helps.

I personally cannot tell you how to do this as I've never gone into a vector layer but all of the resources exist to help you figure it out. Or maybe one of our better scripters will be able to give you some information.

You can download them from here:

ftp://ftp.corel.com/pub/documentation/PSP/

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 8:55 am
by bwernick
Thank you Levi, the downloads are very useful.

Now I am getting somewhere. The following script loops through the selected items and changes the font size.

Code: Select all
from PSPApp import *

def ScriptProperties():
  return {
    'Author': u'Bruce Wernick',
    'Copyright': u'TechniSolve Software',
    'Description': u'Change selected font sizes',
    'Host': u'Paint Shop Pro Photo',
    'Host Version': u'12.01'}

def Do(Environment):
  # EnableOptimizedScriptUndo
  App.Do( Environment, 'EnableOptimizedScriptUndo', {
    'GeneralSettings': {
    'ExecutionMode': App.Constants.ExecutionMode.Default,
    'AutoActionMode': App.Constants.AutoActionMode.Match,
    'Version': ((12,0,1),1) } })

  # Clear script output window
  App.Do( Environment, 'ScriptWndClear')

  # get list of selected vector objects
  SelectedText = App.Do( Environment, 'ReturnVectorObjectProperties' )
 
  if SelectedText['ListOfObjects'] == None:
    print 'No text selected...'
    return

  # Ask user for font size
  UserSize = App.Do( Environment, 'GetNumber', {
    'DefaultValue': 18,
    'MinValue': 6,
    'MaxValue': 90,
    'DialogTitle': 'Font Size',
    'GetInteger': App.Constants.Boolean.true,
    'LogarithmicSlider': App.Constants.Boolean.false,
    'Prompt': 'Enter font point size (6 to 90)',
    'GeneralSettings': {'ExecutionMode': App.Constants.ExecutionMode.Interactive}})
 
  if UserSize['OKButton']:
 
    # loop through selected text list
    for item in SelectedText['ListOfObjects']:
     
      # read the text data
      txt = item['TextExData']
     
      # only text data allowed
      if txt == None:
        continue
       
      # change the font point size
      txt['PointSize'] = UserSize['EnteredNumber']
      txt['Fill']['Color'] = (255, 0, 0) ## for example
      ##...
      txt['TextTarget'] = item['Path']  #Set text path to object we're changing

      # update the text
      App.Do( Environment, 'TextEx', txt )
   
  print 'Done...'


I include my demo to help people who are struggling with a similar problem.

[Code updated from suggestion of Levi].

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 2:11 pm
by Cassel
ONe thing to remembe when working with text is that as soon as the point got added as a font size unit, this has caused major headaches in scripting. If you want a size 48 pixels, it might think 48 points which is totally different. Unfortunately, whether it decides to use the point or the pixel as a unit is often totally random. It is a real nightmare for scripting with the Text command.

There is no real solution to it (yet). Just wanted to warn you in case you get unexpected results, it is not your fault!

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 2:21 pm
by LeviFiction
Well, no good solution anyway. Cassel and I once worked out some code that would create a new text object, determine its size, and perform the necessary calculations to determine if PSP is currently in Point or Pixel mode. I don't remember where that one is anymore though. I would have to do some digging, but until then let me try to answer your question.

Question: What does "txt['TextTarget'] = (0,0, [i], True)" mean/do?

Well it's a navigation path to the object you're trying to reach with the TextEx command.

(0,0,[i],True)

The first option in the tuple moves up or down the level hierarchy (so if you wanted out of a group you'd move out using this one), the second moves up or down the current hierarchy, the third is a list that tells you where to move within the children of the currently selected layer group, and True means it has to match exactly. And so what your code is doing is it's selecting the first child in the current group and then moving up 1 child for each currently selected object.

No trouble if you have only text in the current vector layer and have them all selected but it messes up when you have three objects selected but the third child is not a text object or if you selected from the top down instead of from the bottom up. Or if you have children from multiple groups selected.

So, this requires that you know exactly where the text should be. If the text object already exists it'll change the values for that object. If it does not exist in that location it will create a new text object at that point.

Since this is relative to the first selected object. So what you need to do is grab the navigation path for each selected object. This is provided in the dictionary under the key 'Path.' So instead of iterating "i" and selecting the child from there just use the path that PSP has already figured out for you.

Code: Select all
txt['TextTarget'] = item['Path']

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 4:03 pm
by bwernick
OK, I see what you mean.

I removed the index and it does loop through the selected text.
But, it creates a copy.!!

Code: Select all
    # loop through selected text list
    for item in SelectedText['ListOfObjects']:

      txt = item['TextExData']
   
      # only text data allowed
      if txt == None:
        continue
       
      # change the font point size
      txt['PointSize'] = UserSize['EnteredNumber']
      txt['Fill']['Color'] = (255, 0, 0)
      #... and whatever else you want to change

      # update the text
      App.Do( Environment, 'TextEx', txt )


How do you replace the existing text?

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 4:09 pm
by bwernick
Cassel wrote:If you want a size 48 pixels, it might think 48 points which is totally different...
There is no real solution to it (yet). Just wanted to warn you in case you get unexpected results


Thanks for pointing this out. :) I did notice in the editor that you could set points or pixels and figured out.

Re: Script to change all font sizes

PostPosted: Mon Apr 16, 2012 4:17 pm
by LeviFiction
Haha, guess you miss understood but I already told you how.

The txt['TextTarget'] holds a path to the current object. By default this is set to None. If you don't set this value it just makes a new text object. If you want it to change a current object you need to set this value like you were.

But you have to make sure it's pointing to the right object.

Each vector object returned by "ReturnVectorObjectProperties" includes a path variable already. So what you need to do is set the txt['TextTarget'] value equal to this returned path. It's saved in the 'Path' key of the item object. So if you do say

print item['Path']

it'll print something like (0,1,[1],False).

Now I already gave you this code.
Code: Select all
txt['TargetText'] = item['Path']

Here you can see how it's used

Code: Select all
    # loop through selected text list
    for item in SelectedText['ListOfObjects']:

      txt = item['TextExData']
   
      # only text data allowed
      if txt == None:
        continue
       
      # change the font point size
      txt['PointSize'] = UserSize['EnteredNumber']
      txt['Fill']['Color'] = (255, 0, 0)
      txt['TextTarget'] = item['Path']  #Set text path to object we're changing
      #... and whatever else you want to change

      # update the text
      App.Do( Environment, 'TextEx', txt )

Re: Script to change all font sizes

PostPosted: Tue Apr 17, 2012 7:09 am
by bwernick
Wow, it took me a long time to get my head around that one.

Thank you very much for your help, I doubt that I would have worked this out from the script writers guide alone. If you ask me, the script writers guide could do with a few more samples in vector processing.

I will correct my earlier listing...