How to make text fit inside a paragraph bounding box

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

amanvaidya
Posts: 1
Joined: Thu Jan 04, 2018 10:39 am

How to make text fit inside a paragraph bounding box

Post by amanvaidya »

I have a JSON file like:

Code: Select all

{
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam dui ante, euismod id quam eu. "
}
The text object above contain 15 character. And, I have 6 different Photoshop file (.psd) with completely different template and design.

Each psd file have a paragraph text box of size say

1st => 600px X 600px

2nd => 500px X 500px

3rd => 400px X 400px

...

and so on. They all have different size of bounding box. (They don't have exact square size as mentioned above, in actual they are of sizes like 500px X 120px or 300px X 750px, They are of different sizes)

I am writing a script using JavaScript which take the text object from JSON and change the text content of these paragraph text box.

Code: Select all


// Include the JSON Parser
#include json2js.js

// function to read json
function loadJson(relpath){
var script = new File($.fileName);
var jsonFile = new File(script.path + '/../json/' + relpath);

jsonFile.open( 'r' );
var str = jsonFile.read();
jsonFile.close();

return JSON.parse(str);
}

// Read the JSON
var json = loadJson( 'test.json' );

var docRef = app.activeDocument;
var layerRef = docRef.artLayers.getByName( 'text' );

layerRef.textItem.contents = json.quotes;

var textHeight = layerRef.bounds[3] - layerRef.bounds[1];
var boundHeight = layerRef.textItem.height;

var currentFontSize = layerRef.textItem.size;
currentFontSize = currentFontSize.toString().replace(" pt", "");

if(textHeight > boundHeight) {
fitText(textHeight, boundHeight, currentFontSize, layerRef);
}

//function to fit text inside the box
function fitText(textHeight, boundHeight, currentFontSize, layerRef){
while(textHeight > boundHeight) {
// Decrease Font size to make text fit inside bounding box
currentFontSize--;
layerRef.textItem.size = currentFontSize;
textHeight = layerRef.bounds[3] - layerRef.bounds[1];
}
}
I have set the font-size of text box, so that 15 character can perfectly fit in the box.

But the text object can change to any number of character, say 30, 50 or 70 character. Since, the size of the text box and the font size is fixed in the template,

How can I resize the font-size to automatically fit any number of character within the text box ?

Or, Is there any other approach to do this efficiently ?
User avatar
Kukurykus
Posts: 528
Joined: Mon Jul 25, 2016 12:36 pm

Re: How to make text fit inside a paragraph bounding box

Post by Kukurykus »

To see how it works, create a document, make text area somewhere inside of, and run the script.

If a text is longer than text area it's going to decrease font size every one point untill it's shorter than text area. Then it's going to increase font size every 1/10 point untill it's 1/10 point larger than text areas. Finally it's going to decrease font size again every 1/100 point a pasted text fits perfectly text area.

If a text is shorter than text area it's going to increase font size every one point untill it's longer than text area. Then it's going to decrease font size every 1/10 point untill it's 1/10 point smaller than text areas. Finally it's going to increase font size again every 1/100 point a pasted text fits perfectly text area.

Ps. because it searches for ideal font size (every 1 point, then 1/10 to use 1/100 values) script works slowly, accordingly to text area size and amount of loaded text as well as the fact that all results are based on live graphics changes (not calculated only in memory if there were known behaviour of changed text pixels quantity). It can be speeded up if the script didn't in/decrease font size every 1(/10(0)) value, but for example every 5(/10(0)) value or always a half of last in/decremeant. Anyway now if the current font was 40 and loaded text is twice larger than text area it's going to decrease font every 1 point (39, 38, 37...) till it is one point smaller than text area. Then it's going to increase last full point font size of 1/10 quantity (25.1, 25.2, 25.3...). When a font size is larger again than text area (of 1/10 value this time) it's going to decrease of every 1/100 values (25.69, 25.68, 25.67). When it is 1/100 value less than text area it is going to stop process. It works similarly when new text is smaller than text area. I will increase it of single points, decrease of 1/10 points and increase again of 1/100 points.

This is examplary script you can modify for your needs. To check results with different values change 50 number in 50..mltpl(i) to other.

Code: Select all

ne = (e = '==').replace(e[0], '!'), text = txt = 'Some text, some more text. '

Number.prototype.mltpl = function(v) {while(v < this) txt += text, v++; return txt}
I = !(i = 0), c = (tI = (aD = activeDocument).activeLayer.textItem).contents = 50..mltpl(i)

function comparison() {return eval((a = arguments)[0].length + a[1] + a[2].length)}

eval(evl1 = 'aHS = aD.activeHistoryState, tI.kind = TextType.POINTTEXT')
if (comparison(tI.contents, e, c)) I = 2; eval(evl2 = 'aD.activeHistoryState = aHS')

Number.prototype.fit = function(v) {// I didn't use algorithm to speed up process
do{tI.size -= this, eval(evl1); if (this > .1) i++; c = tI.contents = tI.contents, eval(evl2)}
while(comparison(c, v, txt)); if (i) I = 3 else if(!i && !~~this) I = 4}// do it yourself!

o = veryLongObject = {'1': ne, '-1': e, '.1': ne, '-.01': e, '-.1': e, '.01': ne}
for(j in o) if ((len = j.length) == I) {(+j).fit(o[j]); if (len > 3) {tI.size -= .01; break}}

With implemented ActionManager code for size of font there's 25% faster performance (not in attachment yet):

Code: Select all

function fontSize(v) {
function sTT(v) {return stringIDToTypeID(v)} (ref1 = new ActionReference()).putProperty(sTT('property'), tS = sTT('textStyle'))
ref1.putEnumerated(sTT('textLayer'), sTT('ordinal'), sTT('targetEnum')); (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1);
(dsc2 = new ActionDescriptor()).putInteger(sTT('textOverrideFeatureName'), 808465458), dsc2.putInteger(sTT('typeStyleOperationType'), 3)
dsc2.putUnitDouble(sTT('size'), sTT('pixelsUnit'), v), dsc1.putObject(sTT('to'), tS, dsc2), executeAction(sTT('set'), dsc1, DialogModes.NO);
}

ne = (e = '==').replace(e[0], '!'), text = txt = 'Some text, some more text. '

Number.prototype.mltpl = function(v) {while(v < this) txt += text, v++; return txt}
I = !(i = 0), c = (tI = (aD = activeDocument).activeLayer.textItem).contents = 50..mltpl(i)

function comparison() {return eval((a = arguments)[0].length + a[1] + a[2].length)}

eval(e1 = 'aHS = aD.activeHistoryState, tI.kind = TextType.POINTTEXT')
if (comparison(tI.contents, e, c)) I = 2; eval(e2 = 'aD.activeHistoryState = aHS')

Number.prototype.fit = function(v) {
do{
fontSize(tI.size - this), eval(e1); if (this > .1) i++; c = tI.contents = tI.contents, eval(e2)
}
while(comparison(c, v, txt)); if ( i ) I = 3 else if(!i && !~~this) I = 4
}

o = veryLongObject = {'1': ne, '-1': e, '.1': ne, '-.01': e, '-.1': e, '.01': ne}
for(j in o) if ((len = j.length) == I) {(+j).fit(o[j]); if (len > 3) {fontSize(tI.size - .01); break}}
Attachments
Text Replacement.rar
(788 Bytes) Downloaded 477 times
DhavalKatrodiya
Posts: 2
Joined: Sun Apr 22, 2018 6:09 am

Re: How to make text fit inside a paragraph bounding box

Post by DhavalKatrodiya »

hi i am using photoshop cc2018

& i have the same question : How can I resize the font-size to automatically fit any number of character within the text box ?



i have tried the above scripts, save them as script.jsx, load them to photoshop but non of them actually worked.

so can any body provide me the script that solve this problem!