Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Curved text with CFImage

Community Beginner ,
Oct 14, 2008 Oct 14, 2008
Hello,

Does anyone know if you can do curved text in CFImage? I know there's ImageDrawText, but I'm not sure if it can do curves.

Thanks,

Peter
670
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 14, 2008 Oct 14, 2008
peterswan wrote:
> Does anyone know if you can do curved text in CFImage?

I could be wrong, but I would be surprised if it supports curves. If not, you might look into using svg and Batik. You could use Inkscape to create the svg and then use the output to generate an image in CF.

http://rickosborne.org/blog/index.php/2008/01/28/generating-scalable-stretchy-and-smart-graphics-wit...
http://rickosborne.org/blog/index.php/category/programming/coldfusion/page/3/
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 15, 2008 Oct 15, 2008
There's ImageRotateDrawingAxis() function in CF8. With skill (and probably a ton of work and testing), this might be used to implement a curved text functionality. However, such hand written routine would have to know the font used, know how wide each letter of the font is - and do the math based on that, write one letter at a time, etc.

So I'd say it's possible, and it would be actually fun to prove it, but it might not be worth the trouble...
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 15, 2008 Oct 15, 2008
Fernis wrote:
> So I'd say it's possible, and it would be actually fun to prove it, but it might not be worth the trouble...

Yes, it is possible with java. So there may well be a combination of CF functions you could use to achieve this. However, the svg route (or something similar) may be quicker. You can easily create curved text with Inkscape, making it simpler to implement IMO.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 20, 2008 Oct 20, 2008
LATEST
Here's what I came up with but the text appears jagged with smaller fonts. I think it's because the arc falls in between two coordinates sometimes, making it impossible to land on the correct pixel each time. Or maybe there's another reason? Thanks to cfsearching who came up with the font measurement technique. I might end up going with some third party tool.

Here it is:

<cfset img = ImageNew("", 400, 400)>

<cfset Text2Write = "FRED SMITH FOR PRESIDENT">

<!--- 1 for upper curve, 0 for lower curve --->
<cfset isUpper = 1>

<cfset textFont = "arial">
<cfset textStyle = "bold">
<cfset textSize = "20">
<cfset ImageSetDrawingColor(img,"WHITE")>
<cfset ImageSetAntialiasing(img,"on")>

<cfset attr = { font="#textFont#", style="#textStyle#", size="#textSize#" }>

<!--- get the width of the string --->
<cfscript>
Font = CreateObject("java", "java.awt.Font");
text = {string = "#Text2Write#" };
text.prop = { font="#textFont#", style="#textStyle#", javaStyle= BitOr(Font.BOLD, Font.ITALIC), size="#textSize#" };

arguments.style = "#textStyle#";
switch (arguments.style) {
case "bold":
text.prop.style = font.BOLD;
break;
case "italic":
text.prop.style = font.ITALIC;
break;
case "bolditalic":
text.prop.style = BitOr( Font.BOLD, Font.ITALIC);
break;
case "plain":
text.prop.style = Font.PLAIN;
break;
default:
text.prop.style = Font.PLAIN;
break;
}

graphics = ImageGetBufferedImage( img ).getGraphics();
currentFont = Font.init( javacast("string", text.prop.font), javacast("int", text.prop.javaStyle), javacast("int", text.prop.size));
fontMetrics = graphics.getFontMetrics( currentFont );
fontBounds = fontMetrics.getStringBounds( javacast("string", text.string), graphics );
textString.width = fontBounds.getWidth();
graphics.dispose();
</cfscript>

<cfset radius = 110>
<cfset centerX = 200>
<cfset centerY = 200>

<!--- for some reason 270 is the top of the circle --->
<cfif isUpper is 1>
<cfset angle = 270>
<cfelse>
<cfset angle = 90>
</cfif>


<!--- character spacing --->
<cfset angleIncrement = .54>

<cfif isUpper is 1>
<cfset angle = angle - ((textString.width / 2) * angleIncrement)>
<cfelse>
<cfset angle = angle + ((textString.width / 2) * angleIncrement)>
</cfif>

<cfloop from="1" to="#len(Text2Write)#" index="idx">

<cfset singleChar = mid(Text2Write, idx, 1)>

<!--- get the width of the char --->
<cfscript>
Font = CreateObject("java", "java.awt.Font");
text = { x = 50, y = 100, string = "#singleChar#" };
text.prop = { font="#textFont#", style="#textStyle#", javaStyle= BitOr(Font.BOLD, Font.ITALIC), size="#textSize#" };
arguments.style = "#textStyle#";
switch (arguments.style) {
case "bold":
text.prop.style = font.BOLD;
break;
case "italic":
text.prop.style = font.ITALIC;
break;
case "bolditalic":
text.prop.style = BitOr( Font.BOLD, Font.ITALIC);
break;
case "plain":
text.prop.style = Font.PLAIN;
break;
default:
text.prop.style = Font.PLAIN;
break;
}

graphics = ImageGetBufferedImage( img ).getGraphics();
currentFont = Font.init( javacast("string", text.prop.font), javacast("int", text.prop.javaStyle), javacast("int", text.prop.size));
fontMetrics = graphics.getFontMetrics( currentFont );
fontBounds = fontMetrics.getStringBounds( javacast("string", text.string), graphics );
charItem.width = fontBounds.getWidth();
graphics.dispose();
</cfscript>


<!--- get coordinates for the char --->
<cfset theta = pi() * (angle / 180.0)>

<cfset circleX = round(centerX + radius * cos(theta))>
<cfset circleY = round(centerY + radius * sin(theta))>

<cfif isUpper is 1>
<cfset rotateAngle = angle + 90>
<cfelse>
<cfset rotateAngle = angle - 90>
</cfif>

<!--- rotate the char --->
<cfset ImageRotateDrawingAxis(img, rotateAngle, circlex, circley)>

<cfset ImageDrawText(img, "#singleChar#", circlex, circley, attr)>

<!--- reset rotation --->
<cfset ImageRotateDrawingAxis(img, -(rotateAngle), circlex, circley)>

<cfif isUpper is 1>
<cfset angle = angle + (angleIncrement * charItem.width)>
<cfelse>
<cfset angle = angle - (angleIncrement * charItem.width)>
</cfif>


</cfloop>

<cfimage action="writeToBrowser" source="#img#">
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources