# barcode.scr: Script to generate barcodes in Xic # Release: 6/22/04 # Fixed for current Logo call: 8/12/06 # (c) Whiteley Research Incorporated 2004 # # This script uses the GNU barcode program to generate a renderable # barcode. It was developed using barcode-0.98, available from # http://www.gnu.org/software/barcode/barcode.html. The barcode # executable must be installed on your system for this script to work. # # The barcode program generates PostScript output containing the # layout. This script will parse the generated PostScript and extract # the geometrical information. By default, it generates CODE128-B # barcodes. The user is encouraged to hack this script in order to # use other options of the barcode program. # Operation: The user is prompted for the string to render as a bar # code, and the height in microns of the bars. The barcode is # generated internally and "attached" to the mouse poiner, and will # be placed using the current layer where the user clicks, possibly # multiple times. Presssing Esc will terminate the operation. ######################################################################## BarcodeExe = "barcode" # The name of or path to the barcode program. A full path is needed # if the program is not in the shell search path. BarcodeArgs = "" # Arguments to pass to the barcode program. # Function: get4nums # Return four numbers in a[0-3] found in str. The numbers are # space-separated tokens in str. This can be called again with str=0 # to extract four more numbers from the same string. Returns 1 if # successful. # function get4nums(a, str) cc = 0 while (cc < 4) if (cc == 0) s = Strtok(str, " ") else s = Strtok(0, " ") end if (s == 0) return 0 end a[cc] = ToReal(s) cc++ end return 1 endfunc # Function: get_bcode # This calls the barcode program and obtains the result. # bcpath: String giving path to barcode program, can be just "barcode" # if the program is in the shell search path. # bcargs: String giving additional arguments to barcode program. # string: String to convert to bar code. # bheight: Real number height in microns of the longest bars. # ary: A large array for holding bar geometry returned. We don't # reallocate here, so it must be predefined to be large enough. # Each bar has four array entries: # 0: left # 1: bottom # 2: right # 3: top # txloc: An array of size 3 or larger containing returned text placement # information for the label. # 0: x-position, center justified # 1: y-position, top justified # 2: label width # # The return value is the number of bars (one-fourth the number of array # entries used), or 0 if there was an error. # function get_bcode(bcpath, bcargs, string, bheight, ary, txloc) // Open the barcode process cmd = bcpath + " " + bcargs + " -b " + "\"" + string + "\"" hproc = Popen(cmd, "r") if (hproc == 0) // Popen doesn't fail on missing executable! Print(cmd, "failed") return 0 end // Read the lines of PostScript emitted by the barcode program, // and grab the good stuff n = 0 ready = 0 while (1) str = ReadLine(256, hproc) if (str == 0) break end if (str[0] == '%') // PostScript comment, ignore continue end if (str[0] == '[') // The data of interest are about to start ready = 1 continue end if (str[0] == ']') // No more interesting data break end if (ready) // Read line of data, may contain 4 or 8 real numbers // First convert delimiters to spaces cc = 0 while (str[cc] != 0) if (str[cc] == '[' | str[cc] == ']') str[cc] = ' ' end cc = cc + 1 end // Get first block of four numbers if (!get4nums(ary+n, str)) break end n = n + 4 // Try to get second block, may not exist if (!get4nums(ary+n, 0)) break end n = n + 4 end end // Close process Close(hproc) if (n == 0) return 0 end // Process the numbers we've gathered to be more convenient. We // put the origin at the lower-left corner of the rectangle // collection, and scale according to the height given. The // entries for each rectangle will be in order l,b,r,t. dx = 0 dy = 0 cc = 0 sc = bheight/ary[0] while (cc < n) l = ary[cc+1] - ary[cc+3]/2 b = ary[cc+2] r = ary[cc+1] + ary[cc+3]/2 t = b + ary[cc] if (cc == 0) dx = l dy = b end ary[cc] = sc*(l - dx) ary[cc+1] = sc*(b - dy) ary[cc+2] = sc*(r - dx) ary[cc+3] = sc*(t - dy) cc = cc + 4 end // Figure out where to put the text label txloc[0] = (ary[0] + ary[n-2])/2 txloc[1] = 5*sc txloc[2] = (ary[n-2] - ary[0])*0.5 n = n/4 return n endfunc a[4000] // the box array, this should be plenty big tloc[3] // the label placement parameters str = AskString("Enter string to code: ", "") if (str == 0 | str[0] == 0) ShowPrompt("Null string, exiting") Exit() end bht = AskReal("Enter bar height in microns: ", "75") n = get_bcode(BarcodeExe, BarcodeArgs, str, bht, a, tloc) if (n == 0) Print("get_bcode failed") Message(\ "I could not execute the barcode program. The GNU barcode\n\ program (from www.gnu.org/software/barcode/barcode.html)\n\ must be installed for this script to work.") Exit() end n = n*4 // Ghost-draw the bars attached to the mouse pointer cc = 0 while (cc < n) PushGhostBox(a[cc], a[cc+1], a[cc+2], a[cc+3]) cc = cc + 4 end // Loop, placing the barcode and label where the user clicks. Pressing // the Esc key terminates the loop. // ShowPrompt("Click to place barcode, press Esc to exit.") UseTransform(1, 0, 0) while (1) // show ghost ShowGhost(8) // wait for mouse button press pt[2] if (!Point(pt)) // Esc pressed or abort signal received, we're done break end // stop showing ghost ShowGhost(0) // set current transform to use press location UseTransform(1, pt[0], pt[1]) // don't do interactive DRC drc = DRCstate(0) // create the rectangles on the current layer cc = 0 while (cc < n) Box(a[cc], a[cc+1], a[cc+2], a[cc+3]) cc = cc + 4 end // now create the text label, use Manhattan font Justify(1, 2) ltmp = Get("LogoManhattan") Set("LogoManhattan", "") Logo(str, pt[0] + tloc[0], pt[1] + tloc[1], tloc[2]) Set("LogoManhattan", ltmp) Justify(0, 0) // commit and redraw changes Commit() // revert interactive DRC DRCstate(drc) end ShowPrompt("Barcode script exited.") // End of script