Updated 2011-01-09 00:36:31 by LWS

Keith Vetter 2007-09-17 : A while ago I needed text angled 90 degrees down for labels on a graph. Initially I used the code from Quick Photo Rotation, but then I decided to cache the results, thereby essentially creating my own rotated font.

It works by combining gif images of individual letters creating an image with the requested text at a 90 degree rotation. Not very flexible, but fits my needs.
 ##+##########################################################################
 #
 # rotatedFont.tcl -- simple vertical font 
 # by Keith Vetter
 #
 
 package require Tk
 
 namespace eval ::RotatedFont {
    variable ALPHA                              ;# Rotated text
    array set ALPHA {
        32 R0lGODlhDwADAJEAANnZ2f///////////yH5BAEAAAAALAAAAAAPAAMAAAIGhI+py00FADs=
        33 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIPhI95EUdxCH4EUHyCj3kFADs=
        34 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIWhI+pF0EhfLSIyMyUDIkJHy0iMvOQAgA7
        35 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIfhBNhYWZmAIlN8DEsICiEHxEWd2dIbIKPYQFBIXzMKwA7
        36 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIdhI+JEUYx4UNchFEIm+JjEOywiAuCDxFhQSF8TCwAOw==
        37 R0lGODlhDwAPAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAA8AAAI5hI+pEEEJ4SPFJ/gXGGgUgOITfAiLCArhXwQiHoXwMSMSKQ5AEHyg+ABB8OMg7o7iE3yMiEBEhAwpADs=
        38 R0lGODlhDwALAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAsAAAIxhI+JEUHwESg2wceIi6AQPoRRfIIfEBFHIXyIsDAK4UcEBFBC+BAWgWgkAATBR4jMAgA7
        39 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAINhI+pF0EhfLSIyMxDCgA7
        40 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIShBmf4BvFN4IfcRdBMOLuIAguADs=
        41 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIRDOFjYAQaJYRP8Y3gG8Un+AUAOw==
        42 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIWhI+pF5sUhODjRUQQfAwIRDQSwsfMAgA7
        43 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIWhA+BiEYhfMTIBIofBB8hMpFC+IiRVgA7
        44 R0lGODlhDwADAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAMAAAIMhI8JAUEhfLSIyKQCADs=
        45 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIMhB13d0YhfMTIzERSADs=
        46 R0lGODlhDwADAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAMAAAIKhI95EapAEsLHAgA7
        47 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAINhBMEHzMiMpPEhI8ZVwA7
        48 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIchEHxg+ADxT+CH3cQdxTCh0Cj+EfwgeIHwcfEAgA7
        49 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIVhI95oUAhfIp/BJ/iH8EPgo+py0kFADs=
        50 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIihGMGYWZGEsKOO4igAAARBD8C4oJC+BFGsQl+xEUEwcfEAgA7
        51 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIhhBNmYWZGEsKOO4ijABEEPyzCgkL4QPGN4ENEWFAIHxMLADs=
        52 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIbhB1xdwcUhOCjhUUQfKP4RvCB4h/Bt0BERCQFADs=
        53 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIjhBMWZmZGEoAZwYe4CKCE8OMiICiEDwERQUgIvkXEBcHHvAIAOw==
        54 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIghEGxCf5R/CD4FhgRBB8CA4JC+BQfIAg+REQchfAxrwAAOw==
        55 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIchH8RiGiUEH7EWQTBt4iwoBA+QkQEwceLyMwjBQA7
        56 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIghBEREEEhfKD4R/DjIiwIfljEBcGn+EfwISIsKISPiQUAOw==
        57 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIfhGMQEUHwIYziE/wIiAMK4UNEYBB8o/hB8I9iE3xMLAA7
        58 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIOhI95EUYJ4V+ERRB8TC0AOw==
        59 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIRhI8JAUEBIgi+RYQFhfAxtQAAOw==
        60 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIbhA+BiEBBCD5aQGQCCQBB8DEuEIFC2HF3dwekADs=
        61 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIZhB8Qd3cUhOCjBUSmkSAEHy0gMo0EIfiYWgA7
        62 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIZhBFncXcUAILgY1wgHgUh+GgBkXkkhI+pUAA7
        63 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIbhI+pF0HwIQIjKIQfARFHIXyk2AQfISIyE5ECADs=
        64 R0lGODlhDwAMAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAwAAAJEhI95FJ/gW6AFGgWICACgAAABQLEBIAAIAQQABAUIAAggIAAQABQAAoBiA0AAEAIIAAgKEAAAQUDMIMyMAlBsgm+BeAUAOw==
        65 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAImhEPwESMi00iAiCD4aGERBB8DIoJC+AEUm+AbxSb4GIGIQCF8hAIAOw==
        66 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAInhGNmEGZG4h/Bp/hH8OPi4o4CQABAEPy4CAuCT/GP4ENEWFAIHxMLADs=
        67 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIjhI+ZFJvgH8UPgg8RCEEh/LiDuKMQPgRaoFEI3wIjguBjXgEAOw==
        68 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIkhGNmEGZG4h/Bp/hH8OMO4o5C+BBoEQQ74g4ofhD8o9gEHzMLADs=
        69 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIghGNmEGZG4h/Bp/hH8OPi4o4CRARAEPy4g7ijhLAjrgAAOw==
        70 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIchGNmEGZG4h/Bp/hH8OPi4u5IDAiCjxiZRwkACgA7
        71 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAInhI+ZFJvgH8UPgg8RCEEh/LiDuKMAAQAQBD8i4oLgW0RYUEL4F4gFADs=
        72 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIlhGNmEGZG4h/Bp/hH8OPi4u4ACeFjXFwQfIp/BJ/iH8GPO4ijAgA7
        73 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIRhGNmEGZG4h/Bp/hH8OMO4qgAOw==
        74 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIahBFxd0cx4aNFJlIIHwKN4h/BB4pvBB8xrgAAOw==
        75 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIohGNmEGZG4h/Bp/hH8OPi4u5ITPgXEGEUhOBHxEFQCD/iLu4ohA9xBQA7
        76 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIdhGNmEGZG4h/Bp/hH8OMO4o5C+IgRmUdxCD6mWgEAOw==
        77 R0lGODlhDwALAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAsAAAIthGNmEGZG4h/Bj7OIIPhH8Qk+xSf4FxGIeCQm/AuECArhU/wj+BT/CH7cQRwVADs=
        78 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIihGNmEGZG4h/Bj7uIuzskJnyMCMSjmPAxIjAIPsU/go8YVwA7
        79 R0lGODlhDwAKAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAoAAAInhI+ZFJvgH8UPgg8RCEEh/LiDuKMQPgRaBMGOuAOKHwT/KDbBx8wCADs=
        80 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIghGNmEGZG4h/Bp/hH8OPi4u4ACQBB8JFiE3yEiMhMRAoAOw==
        81 R0lGODlhDwAKAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAoAAAIqhI+ZFJvgH8UPgg8RCEEBACKC4ENcRFAIH+LCgkLYERdH8YPgH8Um+JhZADs=
        82 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIphGNmEGZG4h/Bp/hH8OPi4u5IAoAg+BARcRTCjwig2AQ/DiKC4EMgXgEAOw==
        83 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIlhI95EUFAIszMKABERBD8uAgLgh8WcUHwKTZAEHyLCAtKCB/zCgA7
        84 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIehI8RiGgUwo87iDuKfwSf4h/BjzuIuzuGhPDxIq4AADs=
        85 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIdhI8QaRTfCD7FP4IfdxB3FMJHjLQg+EDxjeAjxhUAOw==
        86 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIlhI8QmUcJ4SNERBD8i4gACuFTbIKPEYGIRxIABMFHiIgg+HgRVwA7
        87 R0lGODlhDwANAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAA0AAAI0hI8QmUYx4R/FJ/gUn+BfRCBQCP8iLhCPxCH4R/EJPsUGgCD4EXF3dyQBQBB8hIgIgo8YVwA7
        88 R0lGODlhDwAJAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAkAAAIthGNmEGZGEsKOuIugABARBD8sIIIQwr+IQAQKEhAE/yLighDCjziLIPhxB3FUADs=
        89 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIhhI8QmUcJ4cdBRFAIn+IHBMGn2AQfAyOAQvh4EZlIAaAAADs=
        90 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIohEPwESMwKCH8iIgLCuEHRMRRCD8uIoBC+HEQERTCjziLIPgRcRYEFwA7
        91 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIPhI9J8dEAINMIHDMzC4ILADs=
        92 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIPhI8RiEYx4V9EIB6F8BEKADs=
        93 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIODOFjHMVHA4BMI/AxrwAAOw==
        94 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIYhA+BiEcJ4WNGZlIIHy8yjRLCR4vMTCMFADs=
        95 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIUDOEjRiZSCB8xMpFC+IiRiRTCRywAOw==
        96 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIKhI+pGasUwsfEAgA7
        97 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIYhBEWdwcUwwj+BYQFwT+KT/CPYhN8DMQrADs=
        98 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIXhBn/CD5QfCP4cRB3R/EJPkZEICJChhQAOw==
        99 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIYhBERcXdA4hP8CwxEoAAQQfAxLAIREQKkADs=
        100 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIYhBERcXdA4hP8CwwLgk/xj+BT/CP4cXdWADs=
        101 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIZhBERcXdA4hP8CwsIgn9hEUHwMSACEREypAA7
        102 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIThGMWZmZA4hvBB4p/BD8OwoLgAgA7
        103 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIlRBIBEQQfAiKA4hD8gAgIAmJmAUFBIoLgB0RYUEL4EIEQBB9TCwA7
        104 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIahGNmEGZG4h/Bp/hH8DEQjeIT/KP4BP8C8QoAOw==
        105 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIShGMWZmZA4oMRfIoPRvDj7qwAADs=
        106 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIRDOFDoFH8AwMAAuMbGMHHvAIAOw==
        107 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIihGNmEGZG4h/Bp/hH8MPi7g5IHIJ/EWFB8C/iAhFICB+hAAA7
        108 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIRhGNmEGZG4h/Bp/hH8OPurAAAOw==
        109 R0lGODlhDwAKAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAoAAAIjhGMWZmZA4hP8o/gEHy8yKT7BP4pP8PEik+IT/KP4BP8C8QoAOw==
        110 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIahGMWZmZA4hP8o/gEHy8yKT7BP4pP8C8QrwAAOw==
        111 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIXhBERcXdA4hP8CwxEoPgEHyMiEBEhQwoAOw==
        112 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIXjH8En+IfwQ+LgyD4R/EJPkZEICJChhQAOw==
        113 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIahBERcXdA4hP8sDgIgk/xjeADxT+CH3d3RgUAOw==
        114 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIXhGMWZmZA4hP8o/gE/+ICEY+E8PEiEqgAOw==
        115 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIchBMQYWZmSICIIPgXEAEUwr+IsCD4GAERBB9TCwA7
        116 R0lGODlhDwAEAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAQAAAIQhG+BCBSf4B/FN4IPgYFGBQA7
        117 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIYhG+BaBSb4B/FJ/gXiGgUn+AfxSf4F4hXADs=
        118 R0lGODlhDwAFAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAUAAAIShB0RcXcUn+BfBCIexSH4iJFQADs=
        119 R0lGODlhDwAIAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAgAAAIdhB8Rd0fxCf5FBCIeiQn/KD7Bv4hAxCMx4SNGQgEAOw==
        120 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIbhGMWZmZAEoARfISICIJ/FJvgY0RYEPwLDDQqADs=
        121 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIYTAg/7uKMYsKHCKDYBP8iAhGPxISPGAkFADs=
        122 R0lGODlhDwAGAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAYAAAIahGMQYWYGSAwIgn8Un+BfWEQQ/Iu4QESEACkAOw==
        123 R0lGODlhDwAFAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAUAAAIUhI+poUex4QIACIwNABdAQAg+xhUAOw==
        124 R0lGODlhDwADAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAMAAAIJhI9J8dEIPuYVADs=
        125 R0lGODlhDwAFAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAUAAAIUDOFjHMUGgAsgABQbLgg+BiIiHikAOw==
        126 R0lGODlhDwAHAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAPAAcAAAIVhB1xd2cUwkeMzKMQPmJkIiWEj6lWADs=
    }
 }
 proc ::RotatedFont::CreateRotateTextImage {txt} {
    variable ALPHA                              ;# Alphabet images
 
    set ltxt {}
    set h 0
    foreach ch [split $txt ""] {                ;# Pass1: create chars, get size
        scan $ch %c ch
        if {! [info exists ALPHA($ch)]} { set ch 63 }
        lappend ltxt $ch
 
        set iname "::img::rot::$ch"
        if {[lsearch [image names] $iname] == -1} {
            image create photo $iname -data $ALPHA($ch)
        }
        incr h [image height $iname]
    }
    set img [image create photo -width 21 -height $h]
 
    set y 0
    foreach ch $ltxt {
        $img copy ::img::rot::$ch -to 0 $y
        incr y [image height ::img::rot::$ch]
    }
 
    return $img
 }
 
 # Demo code
 pack [canvas .c]
 set x 100
 foreach word {"Now is the" "time for all" "good men" "to come to the aid" "of their country"} {
    set img [::RotatedFont::CreateRotateTextImage $word]
    .c create image [incr x -13] 10 -image $img -anchor nw
 }
 return

Also see "Rotate text and images using img extension", "Rotate text on a canvas", "Vector Font"...

KBK 2008-11-03 I was sufficiently intrigued with this idea to do it directly in the canvas, creating 'line' items for the rotated text. There's a demonstrator in the Half Bakery at http://wiki.tcl.tk/_repo/hershey/