diff --git a/btn4ws.py b/btn4ws.py index 777da30..d07e9ec 100644 --- a/btn4ws.py +++ b/btn4ws.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- # This is the main file of btn4ws. # # Copyright (c) 1999-2007 Jan Dittberner @@ -30,7 +30,9 @@ port of the older gimp-perl version to python. (c) 2007 Jan Dittberner """ import os, urllib, logging, sys -from gimpfu import * +import gimp, gimpplugin +from gimpenums import * +pdb = gimp.pdb btn4ws_version = "0.7.0" @@ -143,33 +145,8 @@ class text_to_name_mapper: return os.path.join(dirname, fname) return fname -def python_btn4ws(filename, outdir, font, strcolor, transparency, bgcolor, - glow, glowcolor, usepattern, pattern, buttoncolor, - roundradius, padding, glowsize, bevelwidth, nova, - novasparkles, novaradius, novacolor, writexcf, makeinactive, - makeactive, makepressed, makejscript): - """ - This function controls the creation of the buttons and is - registered as gimp plugin. - """ - # import used gimp pdb functions - createtext = gimp.pdb['gimp_text_fontname'] - selectionlayeralpha = gimp.pdb['gimp_selection_layer_alpha'] - selectionfeather = gimp.pdb['gimp_selection_feather'] - bucketfill = gimp.pdb['gimp_edit_bucket_fill'] - selectionall = gimp.pdb['gimp_selection_all'] - editclear = gimp.pdb['gimp_edit_clear'] - rectselect = gimp.pdb['gimp_rect_select'] - ellipseselect = gimp.pdb['gimp_ellipse_select'] - selectionshrink = gimp.pdb['gimp_selection_shrink'] - selectionnone = gimp.pdb['gimp_selection_none'] - fill = gimp.pdb['gimp_edit_fill'] - bumpmap = gimp.pdb['plug_in_bump_map'] - novaplugin = gimp.pdb['plug_in_nova'] - xcfsave = gimp.pdb['gimp_xcf_save'] - pngsave = gimp.pdb['file_png_save'] - dupimage = gimp.pdb['gimp_image_duplicate'] - +class btn4wsplugin(gimpplugin.plugin): + """This is the btn4ws gimp plugin.""" def parsefont(font): """ Parses a font into its fontname and size parts. @@ -195,7 +172,7 @@ def python_btn4ws(filename, outdir, font, strcolor, transparency, bgcolor, Gets the maximum width and height of texts in strings array with the given font. """ - getextents = gimp.pdb['gimp_text_get_extents_fontname'] + getextents = pdb['gimp_text_get_extents_fontname'] maxx = 0 maxy = 0 for extents in [getextents(string, fontsize, 1, fontname) @@ -294,218 +271,258 @@ def python_btn4ws(filename, outdir, font, strcolor, transparency, bgcolor, False, False, False, False, True) gimp.delete(imgcopy) - try: - if not os.path.isfile(filename): - logging.error("%s is not a file.", filename) + def btn4ws(self, runmode, filename = None, outdir = None, font = None, + strcolor = None, transparency = None, bgcolor = None, + glow = False, glowcolor = None, usepattern = False, + pattern = None, buttoncolor = None, roundradius = None, + padding = None, glowsize = None, bevelwidth = None, + nova = False, novasparkles = None, novaradius = None, + novacolor = None, writexcf = False, makeinactive = True, + makeactive = True, makepressed = True, makejscript = True): + """ + This function controls the creation of the buttons and is + registered as gimp plugin. + """ + # import used gimp pdb functions + createtext = pdb['gimp_text_fontname'] + selectionlayeralpha = pdb['gimp_selection_layer_alpha'] + selectionfeather = pdb['gimp_selection_feather'] + bucketfill = pdb['gimp_edit_bucket_fill'] + selectionall = pdb['gimp_selection_all'] + editclear = pdb['gimp_edit_clear'] + rectselect = pdb['gimp_rect_select'] + ellipseselect = pdb['gimp_ellipse_select'] + selectionshrink = pdb['gimp_selection_shrink'] + selectionnone = pdb['gimp_selection_none'] + fill = pdb['gimp_edit_fill'] + bumpmap = pdb['plug_in_bump_map'] + novaplugin = pdb['plug_in_nova'] + xcfsave = pdb['gimp_xcf_save'] + pngsave = pdb['file_png_save'] + dupimage = pdb['gimp_image_duplicate'] + + try: + if not os.path.isfile(filename): + logging.error("%s is not a file.", filename) + return + if not outdir: + outdir = os.path.dirname(filename) + if not os.path.isdir(outdir): + logging.error("%s is not a directory.", outdir) + return + except OSError, e: + logging.error(e) return - if not outdir: - outdir = os.path.dirname(filename) - if not os.path.isdir(outdir): - logging.error("%s is not a directory.", outdir) - return - except OSError, e: - logging.error(e) - return - gimp.progress_init() - stringfile = open(filename) - strings = [line.strip() - for line in stringfile.readlines() - if toprocess(line)] - stringfile.close() - t2nm = text_to_name_mapper(strings) - (fontname, fontsize) = parsefont(font) - (maxx, maxy) = getmaxextents(strings, fontsize, fontname) - logging.debug("fontname: %s, fontsize: %d, maxx: %d, maxy: %d", - fontname, int(fontsize), maxx, maxy) - width = maxx + (padding*4) - height = maxy + (padding*4) - logging.debug("width: %d, height: %d", width, height) + gimp.progress_init() + stringfile = open(filename) + strings = [line.strip() + for line in stringfile.readlines() + if toprocess(line)] + stringfile.close() + t2nm = text_to_name_mapper(strings) + (fontname, fontsize) = parsefont(font) + (maxx, maxy) = getmaxextents(strings, fontsize, fontname) + logging.debug("fontname: %s, fontsize: %d, maxx: %d, maxy: %d", + fontname, int(fontsize), maxx, maxy) + width = maxx + (padding*4) + height = maxy + (padding*4) + logging.debug("width: %d, height: %d", width, height) + + if roundradius > height/2: + roundradius = height/2 - 1 + if roundradius > width/2: + roundradius = width/2 - 1 + logging.debug("roundradius: %d", roundradius) - if roundradius > height/2: - roundradius = height/2 - 1 - if roundradius > width/2: - roundradius = width/2 - 1 - logging.debug("roundradius: %d", roundradius) - - for text in strings: - image = gimp.Image(width, height, RGB) - image.disable_undo() - gimp.set_foreground(strcolor) - textlayer = createtext(image, None, padding*2, padding*2, text, 0, 1, - fontsize, 1, fontname) - # center the text - textlayer.set_offsets((image.width - textlayer.width)/2 - 1, - (image.height - textlayer.height)/2 - 1) - textlayer.lock_alpha = True - textlayer.name = text - if glow: - texteffect = textlayer.copy(True) - image.add_layer(texteffect, len(image.layers)) - offs = texteffect.offsets - texteffect.resize(image.width, image.height, offs[0], offs[1]) - texteffect.lock_alpha = False - image.active_layer = texteffect - selectionlayeralpha(texteffect) - selectionfeather(image, glowsize) - gimp.set_foreground(glowcolor) - bucketfill(texteffect, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, True, - 0, 0) - btnlayer0 = gimp.Layer(image, "Background", width, height, RGBA_IMAGE, - 100, NORMAL_MODE) - image.add_layer(btnlayer0, len(image.layers)) - selectionall(image) - editclear(btnlayer0) - offs = btnlayer0.offsets - rectselect(image, offs[0] + roundradius, offs[1], - btnlayer0.width - roundradius*2, btnlayer0.height, - CHANNEL_OP_REPLACE, 0, 0) - rectselect(image, offs[0], offs[1] + roundradius, - btnlayer0.width, btnlayer0.height - roundradius*2, - CHANNEL_OP_ADD, 0, 0) - ellipseselect(image, offs[0], offs[1], - roundradius*2, roundradius*2, - CHANNEL_OP_ADD, False, 0, 0) - ellipseselect(image, offs[0] + btnlayer0.width - roundradius*2, - offs[1], - roundradius*2, roundradius*2, - CHANNEL_OP_ADD, False, 0, 0) - ellipseselect(image, offs[0], - offs[1] + btnlayer0.height - roundradius*2, - roundradius*2, roundradius*2, - CHANNEL_OP_ADD, False, 0, 0) - ellipseselect(image, offs[0] + btnlayer0.width - roundradius*2, - offs[1] + btnlayer0.height - roundradius*2, - roundradius*2, roundradius*2, - CHANNEL_OP_ADD, False, 0, 0) - selectionshrink(image, 1) - selectionfeather(image, 2) - if usepattern: - gimp.pdb['gimp_context_set_pattern'](pattern) - bucketfill(btnlayer0, PATTERN_BUCKET_FILL, NORMAL_MODE, 100, 0, - True, 0, 0) - else: - gimp.set_background(buttoncolor) - bucketfill(btnlayer0, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, True, - 0, 0) - selectionnone(image) - selectionlayeralpha(btnlayer0) - selectionfeather(image, 2) - bumplayer = gimp.Layer(image, "Bumpmap", width, height, RGBA_IMAGE, - 100, NORMAL_MODE) - gimp.set_background(0, 0, 0) - image.add_layer(bumplayer, 0) - fill(bumplayer, BACKGROUND_FILL) - for index in range(1, bevelwidth -1): - greyness = index*255/bevelwidth; - gimp.set_background(greyness, greyness, greyness) + for text in strings: + image = gimp.Image(width, height, RGB) + image.disable_undo() + gimp.set_foreground(strcolor) + textlayer = createtext(image, None, padding*2, padding*2, text, + 0, 1, fontsize, 1, fontname) + # center the text + textlayer.set_offsets((image.width - textlayer.width)/2 - 1, + (image.height - textlayer.height)/2 - 1) + textlayer.lock_alpha = True + textlayer.name = text + if glow: + texteffect = textlayer.copy(True) + image.add_layer(texteffect, len(image.layers)) + offs = texteffect.offsets + texteffect.resize(image.width, image.height, offs[0], offs[1]) + texteffect.lock_alpha = False + image.active_layer = texteffect + selectionlayeralpha(texteffect) + selectionfeather(image, glowsize) + gimp.set_foreground(glowcolor) + bucketfill(texteffect, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, + True, 0, 0) + btnlayer0 = gimp.Layer(image, "Background", width, height, + RGBA_IMAGE, 100, NORMAL_MODE) + image.add_layer(btnlayer0, len(image.layers)) + selectionall(image) + editclear(btnlayer0) + offs = btnlayer0.offsets + rectselect(image, offs[0] + roundradius, offs[1], + btnlayer0.width - roundradius*2, btnlayer0.height, + CHANNEL_OP_REPLACE, 0, 0) + rectselect(image, offs[0], offs[1] + roundradius, + btnlayer0.width, btnlayer0.height - roundradius*2, + CHANNEL_OP_ADD, 0, 0) + ellipseselect(image, offs[0], offs[1], + roundradius*2, roundradius*2, + CHANNEL_OP_ADD, False, 0, 0) + ellipseselect(image, offs[0] + btnlayer0.width - roundradius*2, + offs[1], + roundradius*2, roundradius*2, + CHANNEL_OP_ADD, False, 0, 0) + ellipseselect(image, offs[0], + offs[1] + btnlayer0.height - roundradius*2, + roundradius*2, roundradius*2, + CHANNEL_OP_ADD, False, 0, 0) + ellipseselect(image, offs[0] + btnlayer0.width - roundradius*2, + offs[1] + btnlayer0.height - roundradius*2, + roundradius*2, roundradius*2, + CHANNEL_OP_ADD, False, 0, 0) + selectionshrink(image, 1) + selectionfeather(image, 2) + if usepattern: + pdb['gimp_context_set_pattern'](pattern) + bucketfill(btnlayer0, PATTERN_BUCKET_FILL, NORMAL_MODE, 100, 0, + True, 0, 0) + else: + gimp.set_background(buttoncolor) + bucketfill(btnlayer0, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, + True, 0, 0) + selectionnone(image) + selectionlayeralpha(btnlayer0) + selectionfeather(image, 2) + bumplayer = gimp.Layer(image, "Bumpmap", width, height, RGBA_IMAGE, + 100, NORMAL_MODE) + gimp.set_background(0, 0, 0) + image.add_layer(bumplayer, 0) + fill(bumplayer, BACKGROUND_FILL) + for index in range(1, bevelwidth -1): + greyness = index*255/bevelwidth; + gimp.set_background(greyness, greyness, greyness) + bucketfill(bumplayer, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, + False, 0, 0) + selectionshrink(image, 1) + gimp.set_background(255, 255, 255) bucketfill(bumplayer, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, False, 0, 0) - selectionshrink(image, 1) - gimp.set_background(255, 255, 255) - bucketfill(bumplayer, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, False, 0, 0) - selectionnone(image) - btnlayer1 = btnlayer0.copy(True) - btnlayer2 = btnlayer0.copy(True) - image.add_layer(btnlayer1, len(image.layers)) - image.add_layer(btnlayer2, len(image.layers)) - bumpmap(image, btnlayer1, bumplayer, 125, 45, 3, 0, 0, 0, 0, 0, 0, 1) - bumpmap(image, btnlayer2, bumplayer, 125, 45, 3, 0, 0, 0, 0, 0, 1, 1) - image.remove_layer(bumplayer) - #gimp.delete(bumplayer) - if nova: - novalayer = gimp.Layer(image, "Nova", width, height, RGBA_IMAGE, - 75, NORMAL_MODE) - image.add_layer(novalayer, 0) - selectionall(image) - image.active_layer = novalayer - editclear(novalayer) selectionnone(image) - novaplugin(image, novalayer, width/4, height/4, - novacolor, novaradius, novasparkles, 0) - blackboard = gimp.Layer(image, "Blackboard", width, height, RGBA_IMAGE, - 100, NORMAL_MODE) - image.add_layer(blackboard, len(image.layers)) - selectionall(image) - if transparency: - blackboard.preserve_trans = True - editclear(blackboard) - else: - gimp.set_background(bgcolor) - bucketfill(blackboard, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, False, - 0, 0) - selectionnone(image) - if writexcf: - fname = t2nm.asfilename(text, 'xcf', dirname = outdir) - xcfsave(0, image, textlayer, fname, fname) - if makepressed: - btnlayer0.visible = False - btnlayer1.visible = False - btnlayer2.visible = True - if nova: novalayer.visible = True - saveaspng(t2nm.asfilename(text, 'png', 'p_', outdir), image) - if makeactive: - btnlayer0.visible = False - btnlayer1.visible = True - btnlayer2.visible = False - if nova: novalayer.visible = True - saveaspng(t2nm.asfilename(text, 'png', 'a_', outdir), image) - if makeinactive: - btnlayer0.visible = True - btnlayer1.visible = False - btnlayer2.visible = False - if nova: novalayer.visible = False - saveaspng(t2nm.asfilename(text, 'png', 'i_', outdir), image) - image.enable_undo() - #gimp.Display(image) - gimp.progress_update((strings.index(text)+1)/len(strings)) - gimp.delete(image) - if makejscript: - writejs(outdir, strings) - writecss(outdir) - writehtml(outdir, strings) - #gimp.displays_flush() + btnlayer1 = btnlayer0.copy(True) + btnlayer2 = btnlayer0.copy(True) + image.add_layer(btnlayer1, len(image.layers)) + image.add_layer(btnlayer2, len(image.layers)) + bumpmap(image, btnlayer1, bumplayer, 125, 45, 3, 0, 0, 0, 0, 0, + 0, 1) + bumpmap(image, btnlayer2, bumplayer, 125, 45, 3, 0, 0, 0, 0, 0, + 1, 1) + image.remove_layer(bumplayer) + #gimp.delete(bumplayer) + if nova: + novalayer = gimp.Layer(image, "Nova", width, height, + RGBA_IMAGE, 75, NORMAL_MODE) + image.add_layer(novalayer, 0) + selectionall(image) + image.active_layer = novalayer + editclear(novalayer) + selectionnone(image) + novaplugin(image, novalayer, width/4, height/4, + novacolor, novaradius, novasparkles, 0) + blackboard = gimp.Layer(image, "Blackboard", width, height, + RGBA_IMAGE, 100, NORMAL_MODE) + image.add_layer(blackboard, len(image.layers)) + selectionall(image) + if transparency: + blackboard.preserve_trans = True + editclear(blackboard) + else: + gimp.set_background(bgcolor) + bucketfill(blackboard, BG_BUCKET_FILL, NORMAL_MODE, 100, 0, + False, 0, 0) + selectionnone(image) + if writexcf: + fname = t2nm.asfilename(text, 'xcf', dirname = outdir) + xcfsave(0, image, textlayer, fname, fname) + if makepressed: + btnlayer0.visible = False + btnlayer1.visible = False + btnlayer2.visible = True + if nova: novalayer.visible = True + saveaspng(t2nm.asfilename(text, 'png', 'p_', outdir), image) + if makeactive: + btnlayer0.visible = False + btnlayer1.visible = True + btnlayer2.visible = False + if nova: novalayer.visible = True + saveaspng(t2nm.asfilename(text, 'png', 'a_', outdir), image) + if makeinactive: + btnlayer0.visible = True + btnlayer1.visible = False + btnlayer2.visible = False + if nova: novalayer.visible = False + saveaspng(t2nm.asfilename(text, 'png', 'i_', outdir), image) + image.enable_undo() + #gimp.Display(image) + gimp.progress_update((strings.index(text)+1)/len(strings)) + gimp.delete(image) + if makejscript: + writejs(outdir, strings) + writecss(outdir) + writehtml(outdir, strings) + #gimp.displays_flush() -register( - "python_fu_btn4ws", "Buttons for website", - """Creates buttons for a website. Which have the same size, - layout, effects on it. It's possible to create JavaScript code, - CSS and XHTML examples for MouseOver effects also.""", - "Jan Dittberner", - "Jan Dittberner ", - "%s, %s" % (btn4ws_version, - "$Date$"), - "/Xtns/Render/Buttons for website ...", - "", - [(PF_FILE, "string_filename", "File containing the strings", ""), - (PF_FILE, "output_directory", "Directory for the output files", ""), - (PF_FONT, "font", "Font for the strings", "Sans 18"), - (PF_COLOR, "string_color", "Color of the strings", (255, 255, 0)), - (PF_TOGGLE, "transparent_background", - """Keep the background transparent (This doesn't work in MS - Internet Explorer <= 6.0)""", 0), - (PF_COLOR, "background_color", "Color of the background", (7, 135, 255)), - (PF_TOGGLE, "apply_glow", "Enable glow effect", 1), - (PF_COLOR, "glow_color", "Color of the Glow effect", (255, 180, 0)), - (PF_TOGGLE, "use_pattern", "Use a pattern for the button", 1), - (PF_PATTERN, "button_pattern", "Fill pattern of the button", "Rain"), - (PF_COLOR, "button_color", - "Button color (if you don't use a pattern)", (0, 0, 255)), - (PF_INT32, "round_radius", "Radius of the round corners", 20), - (PF_INT32, "padding", "Space around the text", 3), - (PF_INT32, "glow_size", "Size of the Glow effect", 10), - (PF_INT32, "bevel_width", "Width of the bevel", 5), - (PF_TOGGLE, "apply_nova", "Nova or not Nova?", 1), - (PF_INT32, "nova_sparkles", "Sparkles of the Nova", 5), - (PF_INT32, "nova_radius", "Radius of the Nova", 2), - (PF_COLOR, "nova_color", "Color of the Nova effect", (255, 238, 0)), - (PF_TOGGLE, "write_xcf", "Write a GIMP xcf file", 0), - (PF_TOGGLE, "create_inactive", "Create Inactive Button", 1), - (PF_TOGGLE, "create_active", "Create Active Button", 1), - (PF_TOGGLE, "create_pressed", "Create Pressed Button", 1), - (PF_TOGGLE, "create_jscript", "Create JavaScript, HTML and CSS", 1) - ], - [], - python_btn4ws) + def start(self): + gimp.main(self.init, self.quit, self.query, self._run) -main() + def init(self): + logging.debug("init") + + def quit(self): + logging.debug("quit") + + def query(self): + logging.debug("query") + gimp.install_procedure( + "btn4ws", + "Buttons for website", """Creates buttons for a website. Which have the same size, layout, effects on it. It's possible to create JavaScript code, CSS and XHTML examples for MouseOver effects also.""", + "Jan Dittberner", + "Jan Dittberner ", + "%s, %s" % (btn4ws_version, + "$Date$"), + "/Xtns/Render/Buttons for website ...", + "", PLUGIN, + [(PDB_INT32, "run_mode", "Run mode"), + (PDB_STRING, "string_filename", "File containing the strings"), + (PDB_STRING, "output_directory", "Directory for the output files"), + (PDB_STRING, "font", "Font for the strings"), # "Sans 18"), + (PDB_COLOR, "string_color", "Color of the strings"), #, (255, 255, 0)), + (PDB_INT8, "transparent_background", "Keep the background transparent (This doesn't work in MS Internet Explorer <= 6.0)"), #, 0), + (PDB_COLOR, "background_color", "Color of the background"), #, (7, 135, 255)), + (PDB_INT8, "apply_glow", "Enable glow effect"), #, 1), + (PDB_COLOR, "glow_color", "Color of the Glow effect"), #, (255, 180, 0)), + (PDB_INT8, "use_pattern", "Use a pattern for the button"), #, 1), + (PDB_STRING, "button_pattern", "Fill pattern of the button"), #, "Rain"), + (PDB_COLOR, "button_color", "Button color (if you don't use a pattern)"), #, (0, 0, 255)), + (PDB_INT32, "round_radius", "Radius of the round corners"), #, 20), + (PDB_INT32, "padding", "Space around the text"), #, 3), + (PDB_INT32, "glow_size", "Size of the Glow effect"), #, 10), + (PDB_INT32, "bevel_width", "Width of the bevel"), #, 5), + (PDB_INT8, "apply_nova", "Nova or not Nova?"), #, 1), + (PDB_INT32, "nova_sparkles", "Sparkles of the Nova"), #, 5), + (PDB_INT32, "nova_radius", "Radius of the Nova"), #, 2), + (PDB_COLOR, "nova_color", "Color of the Nova effect"), #, (255, 238, 0)), + (PDB_INT8, "write_xcf", "Write a GIMP xcf file"), #, 0), + (PDB_INT8, "create_inactive", "Create Inactive Button"), #, 1), + (PDB_INT8, "create_active", "Create Active Button"), #, 1), + (PDB_INT8, "create_pressed", "Create Pressed Button"), #, 1), + (PDB_INT8, "create_jscript", "Create JavaScript, HTML and CSS"), #, 1) + ], + []) + +if __name__ == '__main__': + btn4wsplugin().start()