mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Make icon generation script faster and more flexible
This commit is contained in:
committed by
Bjorn Winckler
parent
48fc2be299
commit
c7323339d9
+315
-189
@@ -104,45 +104,200 @@ BACKGROUND = '/System/Library/CoreServices/CoreTypes.bundle/' + \
|
||||
APPICON = 'vim-noshadow-512.png'
|
||||
#APPICON = 'vim-noshadow-no-v-512.png'
|
||||
|
||||
class Surface(object):
|
||||
"""Represents a simple bitmapped image."""
|
||||
|
||||
def __init__(self, *p, **kw):
|
||||
if not 'premultiplyAlpha' in kw:
|
||||
kw['premultiplyAlpha'] = True
|
||||
if len(p) == 1 and isinstance(p[0], NSBitmapImageRep):
|
||||
self.bitmapRep = p[0]
|
||||
elif len(p) == 2 and isinstance(p[0], int) and isinstance(p[1], int):
|
||||
format = NSAlphaFirstBitmapFormat
|
||||
if not kw['premultiplyAlpha']:
|
||||
format += NSAlphaNonpremultipliedBitmapFormat
|
||||
self.bitmapRep = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(
|
||||
None, p[0], p[1], 8, 4, True, False, NSDeviceRGBColorSpace,
|
||||
format, 0, 0)
|
||||
|
||||
if not hasattr(self, 'bitmapRep') or not self.bitmapRep:
|
||||
raise Exception('Failed to create surface: ' + str(p))
|
||||
|
||||
def size(self):
|
||||
return map(int, self.bitmapRep.size()) # cocoa returns floats. cocoa ftw
|
||||
|
||||
def data(self):
|
||||
"""Returns data in ARGB order (on intel, at least)."""
|
||||
r = self.bitmapRep
|
||||
if r.bitmapFormat() != (NSAlphaNonpremultipliedBitmapFormat |
|
||||
NSAlphaFirstBitmapFormat) or \
|
||||
r.bitsPerPixel() != 32 or \
|
||||
r.isPlanar() or \
|
||||
r.samplesPerPixel() != 4:
|
||||
raise Exception("Unsupported image format")
|
||||
return self.bitmapRep.bitmapData()
|
||||
|
||||
def save(self, filename):
|
||||
"""Saves image as png file."""
|
||||
self.bitmapRep.representationUsingType_properties_(NSPNGFileType, None) \
|
||||
.writeToFile_atomically_(filename, True)
|
||||
|
||||
def draw(self):
|
||||
self.bitmapRep.draw()
|
||||
|
||||
def context(self):
|
||||
# Note: Cocoa only supports contexts with premultiplied alpha
|
||||
return NSGraphicsContext.graphicsContextWithBitmapImageRep_(self.bitmapRep)
|
||||
|
||||
def copy(self):
|
||||
return Surface(self.bitmapRep.copy())
|
||||
|
||||
|
||||
class Image(object):
|
||||
"""Represents an image that can consist of several Surfaces."""
|
||||
|
||||
def __init__(self, param):
|
||||
if isinstance(param, str):
|
||||
self.image = NSImage.alloc().initWithContentsOfFile_(param)
|
||||
elif isinstance(param, Surface):
|
||||
self.image = NSImage.alloc().initWithSize_( param.size() )
|
||||
self.image.addRepresentation_(param.bitmapRep)
|
||||
|
||||
if not self.image:
|
||||
raise Exception('Failed to load image: ' + str(filename))
|
||||
|
||||
def surfaceOfSize(self, w, h):
|
||||
"""Returns an ARGB, non-premultiplied surface of size w*h or throws."""
|
||||
r = None
|
||||
for rep in self.image.representations():
|
||||
if map(int, rep.size()) == [w, h]:
|
||||
r = rep
|
||||
break
|
||||
if not r:
|
||||
raise Exception('Unsupported size %dx%d', w, h)
|
||||
return Surface(r)
|
||||
|
||||
def blend(self):
|
||||
self.compositeInRect( ((0, 0), self.image.size()) )
|
||||
|
||||
def compositeInRect(self, r, mode=NSCompositeSourceOver):
|
||||
self.image.drawInRect_fromRect_operation_fraction_(r, NSZeroRect,
|
||||
mode, 1.0)
|
||||
|
||||
|
||||
class Context(object):
|
||||
# Tiger has only Python2.3, so we can't use __enter__ / __exit__ for this :-(
|
||||
|
||||
def __init__(self, surface):
|
||||
NSGraphicsContext.saveGraphicsState()
|
||||
c = surface.context()
|
||||
c.setShouldAntialias_(True);
|
||||
c.setImageInterpolation_(NSImageInterpolationHigh);
|
||||
NSGraphicsContext.setCurrentContext_(c)
|
||||
|
||||
def done(self):
|
||||
NSGraphicsContext.restoreGraphicsState()
|
||||
|
||||
|
||||
class SplittableBackground(object):
|
||||
|
||||
def __init__(self, unsplitted, shouldSplit=True):
|
||||
self.unsplitted = unsplitted
|
||||
self.shouldSplit = shouldSplit
|
||||
self.ground = {}
|
||||
self.shadow = {}
|
||||
|
||||
def rawGroundAtSize(self, s):
|
||||
return self.unsplitted.surfaceOfSize(s, s)
|
||||
|
||||
def groundAtSize(self, s):
|
||||
if not self.shouldSplit:
|
||||
return self.rawGroundAtSize(s)
|
||||
self._performSplit(s)
|
||||
return self.ground[s]
|
||||
|
||||
def shadowAtSize(self, s):
|
||||
if not self.shouldSplit:
|
||||
return None
|
||||
self._performSplit(s)
|
||||
return self.shadow[s]
|
||||
|
||||
def _performSplit(self, s):
|
||||
if s in self.ground:
|
||||
assert s in self.shadow
|
||||
return
|
||||
assert s not in self.shadow
|
||||
ground, shadow = splitGenericDocumentIcon(self.unsplitted, s)
|
||||
self.ground[s] = ground
|
||||
self.shadow[s] = shadow
|
||||
|
||||
|
||||
class BackgroundRenderer(object):
|
||||
|
||||
def __init__(self, bg, icon=None):
|
||||
self.bgRenderer = bg
|
||||
self.icon = icon
|
||||
self.cache = {}
|
||||
|
||||
def drawIcon(self, s):
|
||||
if not self.icon:
|
||||
return
|
||||
# found by flow program, better than anything i came up with manually before
|
||||
# (except for the 16x16 variant :-( )
|
||||
transforms = {
|
||||
512: [ 0.7049, 0.5653, -4.2432, 0.5656],
|
||||
256: [ 0.5690, 0.5658, -1.9331, 0.5656],
|
||||
128: [ 1.1461, 0.5684, -0.8482, 0.5681],
|
||||
|
||||
32: [-0.2682, 0.5895, -2.2130, 0.5701], # intensity
|
||||
#32: [-0.2731, 0.5898, -2.2262, 0.5729], # rgb (no rmse difference)
|
||||
|
||||
#16: [-0.3033, 0.4909, -1.3235, 0.4790], # program, intensity
|
||||
#16: [-0.3087, 0.4920, -1.2990, 0.4750], # program, rgb mode
|
||||
16: [ 0.0000, 0.5000, -1.0000, 0.5000], # manually, better
|
||||
}
|
||||
|
||||
assert s in [16, 32, 128, 256, 512]
|
||||
a = transforms[s]
|
||||
|
||||
# convert from `flow` coords to cocoa
|
||||
a[2] = -a[2] # mirror y
|
||||
|
||||
w, h = s*a[1], s*a[3]
|
||||
self.icon.compositeInRect( (((s-w)/2 + a[0], (s-h)/2 + a[2]), (w, h)) )
|
||||
|
||||
def drawAtSize(self, s):
|
||||
self.bgRenderer.groundAtSize(s).draw()
|
||||
self.drawIcon(s)
|
||||
if self.bgRenderer.shouldSplit:
|
||||
# shadow needs to be composited, so it needs to be in an image
|
||||
Image(self.bgRenderer.shadowAtSize(s)).blend()
|
||||
|
||||
def backgroundAtSize(self, s):
|
||||
if not s in self.cache:
|
||||
result = Surface(s, s)
|
||||
context = Context(result)
|
||||
self.drawAtSize(s)
|
||||
context.done()
|
||||
self.cache[s] = result
|
||||
return self.cache[s]
|
||||
|
||||
|
||||
def splitGenericDocumentIcon(img, s):
|
||||
"""Takes the generic document icon and splits it into a background and a
|
||||
shadow layer. For the 32x32 and 16x16 variants, the white pixels of the page
|
||||
curl are hardcoded into the otherwise transparent shadow layer."""
|
||||
|
||||
r = None
|
||||
for rep in img.representations():
|
||||
if map(int, rep.size()) == [s, s]:
|
||||
r = rep
|
||||
break
|
||||
|
||||
if not r:
|
||||
raise Exception('Unsupported size %d', s)
|
||||
|
||||
# XXX: This is a bit slow in python, perhaps do this in C
|
||||
|
||||
if r.bitmapFormat() != (NSAlphaNonpremultipliedBitmapFormat |
|
||||
NSAlphaFirstBitmapFormat) or \
|
||||
r.bitsPerPixel() != 32 or \
|
||||
r.isPlanar() or \
|
||||
r.samplesPerPixel() != 4:
|
||||
raise Exception("Unsupported image format")
|
||||
|
||||
w, h = map(int, r.size()) # cocoa returns floats. cocoa ftw.
|
||||
w, h = s, s
|
||||
r = img.surfaceOfSize(w, h)
|
||||
bps = 4*w
|
||||
data = r.bitmapData()
|
||||
data = r.data()
|
||||
|
||||
# These do not have alpha first!
|
||||
ground = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(
|
||||
None, w, h, 8, 4, True, False, NSDeviceRGBColorSpace,
|
||||
NSAlphaNonpremultipliedBitmapFormat, 0, 0)
|
||||
ground = Surface(w, h, premultiplyAlpha=False)
|
||||
shadow = Surface(w, h, premultiplyAlpha=False)
|
||||
|
||||
shadow = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(
|
||||
None, w, h, 8, 4, True, False, NSDeviceRGBColorSpace,
|
||||
NSAlphaNonpremultipliedBitmapFormat, 0, 0)
|
||||
|
||||
grounddata = ground.bitmapData()
|
||||
shadowdata = shadow.bitmapData()
|
||||
grounddata = ground.data()
|
||||
shadowdata = shadow.data()
|
||||
|
||||
for y in xrange(h):
|
||||
for x in xrange(w):
|
||||
@@ -150,10 +305,10 @@ def splitGenericDocumentIcon(img, s):
|
||||
ia, ir, ig, ib = data[idx:idx + 4]
|
||||
if ia != chr(255):
|
||||
# buffer objects don't support slice assignment :-(
|
||||
grounddata[idx] = ir
|
||||
grounddata[idx + 1] = ig
|
||||
grounddata[idx + 2] = ib
|
||||
grounddata[idx + 3] = ia
|
||||
grounddata[idx] = ia
|
||||
grounddata[idx + 1] = ir
|
||||
grounddata[idx + 2] = ig
|
||||
grounddata[idx + 3] = ib
|
||||
shadowdata[idx] = chr(0)
|
||||
shadowdata[idx + 1] = chr(0)
|
||||
shadowdata[idx + 2] = chr(0)
|
||||
@@ -165,15 +320,13 @@ def splitGenericDocumentIcon(img, s):
|
||||
grounddata[idx + 1] = chr(255)
|
||||
grounddata[idx + 2] = chr(255)
|
||||
grounddata[idx + 3] = chr(255)
|
||||
shadowdata[idx] = chr(0)
|
||||
shadowdata[idx] = chr(255 - ord(ir))
|
||||
shadowdata[idx + 1] = chr(0)
|
||||
shadowdata[idx + 2] = chr(0)
|
||||
shadowdata[idx + 3] = chr(255 - ord(ir))
|
||||
|
||||
shadowdata[idx + 3] = chr(0)
|
||||
|
||||
# Special-case 16x16 and 32x32 cases: Make some pixels on the fold white.
|
||||
# Ideally, I could make the fold whiteish in all variants, but I can't.
|
||||
|
||||
whitePix = { 16: [(10, 2), (10, 3), (11, 3), (10, 4), (11, 4), (12, 4)],
|
||||
32: [(21, 4), (21, 5), (22, 5), (21, 6), (22, 6), (23, 6)]}
|
||||
if (w, h) in [(16, 16), (32, 32)]:
|
||||
@@ -187,137 +340,124 @@ def splitGenericDocumentIcon(img, s):
|
||||
return ground, shadow
|
||||
|
||||
|
||||
def drawText(text, s):
|
||||
"""Draws text `s` into the current context of size `s`."""
|
||||
class TextRenderer(object):
|
||||
|
||||
# This looks not exactly like the font on Preview.app's document icons,
|
||||
# but I believe that's because Preview's icons are drawn by Photoshop,
|
||||
# and Adobe's font rendering is different from Apple's.
|
||||
fontname = 'LucidaGrande-Bold'
|
||||
def __init__(self):
|
||||
self.cache = {}
|
||||
|
||||
# Prepare text format
|
||||
style = NSMutableParagraphStyle.new()
|
||||
style.setParagraphStyle_(NSParagraphStyle.defaultParagraphStyle())
|
||||
style.setAlignment_(NSCenterTextAlignment)
|
||||
# http://developer.apple.com/documentation/Cocoa/Conceptual/AttributedStrings/Articles/standardAttributes.html#//apple_ref/doc/uid/TP40004903
|
||||
attribs = {
|
||||
NSParagraphStyleAttributeName: style,
|
||||
NSForegroundColorAttributeName: NSColor.colorWithDeviceWhite_alpha_(
|
||||
0.34, 1)
|
||||
}
|
||||
if s == 512:
|
||||
attribs[NSFontAttributeName] = NSFont.fontWithName_size_(fontname, 72.0)
|
||||
attribs[NSKernAttributeName] = -1.0 # tighten font a bit
|
||||
elif s == 256:
|
||||
attribs[NSFontAttributeName] = NSFont.fontWithName_size_(fontname, 36.0)
|
||||
attribs[NSKernAttributeName] = -1.0 # tighten font a bit
|
||||
elif s == 128:
|
||||
attribs[NSFontAttributeName] = NSFont.fontWithName_size_(fontname, 18.0)
|
||||
elif s == 32:
|
||||
#attribs[NSFontAttributeName] = NSFont.fontWithName_size_(
|
||||
#'LucidaSans-Demi', 7.0)
|
||||
attribs[NSKernAttributeName] = -0.25 # tighten font a bit
|
||||
if NSFontAttributeName not in attribs:
|
||||
attribs[NSFontAttributeName] = NSFont.fontWithName_size_(fontname, 7.0)
|
||||
elif s == 16:
|
||||
attribs[NSFontAttributeName] = NSFont.fontWithName_size_(fontname, 3.0)
|
||||
def attribsAtSize(self, s):
|
||||
if s not in self.cache:
|
||||
self.cache[s] = self._attribsAtSize(s)
|
||||
return self.cache[s]
|
||||
|
||||
if not attribs[NSFontAttributeName]:
|
||||
print 'Failed to load font', fontname
|
||||
sys.exit(1)
|
||||
def centeredStyle(self):
|
||||
style = NSMutableParagraphStyle.new()
|
||||
style.setParagraphStyle_(NSParagraphStyle.defaultParagraphStyle())
|
||||
style.setAlignment_(NSCenterTextAlignment)
|
||||
return style
|
||||
|
||||
textRects = {
|
||||
512: ((0, 7), (512, 119)),
|
||||
128: ((0, 6), (128, 26.5)),
|
||||
256: ((0, 7), (256, 57)),
|
||||
}
|
||||
def _attribsAtSize(self, s):
|
||||
# This looks not exactly like the font on Preview.app's document icons,
|
||||
# but I believe that's because Preview's icons are drawn by Photoshop,
|
||||
# and Adobe's font rendering is different from Apple's.
|
||||
fontname = 'LucidaGrande-Bold'
|
||||
|
||||
if s in [128, 256, 512]:
|
||||
text.drawInRect_withAttributes_(textRects[s], attribs)
|
||||
elif s == 32:
|
||||
#text.drawInRect_withAttributes_( ((1, 1), (31, 9)), attribs)
|
||||
# Prepare text format
|
||||
fontsizes = { 512: 72.0, 256: 36.0, 128: 18.0, 32: 7.0, 16: 3.0 }
|
||||
# http://developer.apple.com/documentation/Cocoa/Conceptual/AttributedStrings/Articles/standardAttributes.html#//apple_ref/doc/uid/TP40004903
|
||||
attribs = {
|
||||
NSParagraphStyleAttributeName: self.centeredStyle(),
|
||||
NSForegroundColorAttributeName: NSColor.colorWithDeviceWhite_alpha_(
|
||||
0.34, 1),
|
||||
NSFontAttributeName: NSFont.fontWithName_size_(fontname, fontsizes[s])
|
||||
}
|
||||
|
||||
# Try to align text on pixel boundary:
|
||||
ts = text.sizeWithAttributes_(attribs)
|
||||
attribs[NSParagraphStyleAttributeName] = \
|
||||
NSParagraphStyle.defaultParagraphStyle()
|
||||
text.drawAtPoint_withAttributes_( (math.floor((32.0-ts[0])/2) + 0.5, 1.5),
|
||||
attribs)
|
||||
# tighten font a bit for some sizes
|
||||
if s in [256, 512]:
|
||||
attribs[NSKernAttributeName] = -1.0
|
||||
elif s == 32:
|
||||
attribs[NSKernAttributeName] = -0.25
|
||||
|
||||
# for demibold roman:
|
||||
#text.drawInRect_withAttributes_( ((0, 1), (31, 11)), attribs)
|
||||
elif s == 16:
|
||||
text.drawInRect_withAttributes_( ((1, 1), (15, 5)), attribs)
|
||||
if not attribs[NSFontAttributeName]:
|
||||
raise Exception('Failed to load font %s' % fontname)
|
||||
return attribs
|
||||
|
||||
def drawTextAtSize(self, text, s):
|
||||
"""Draws text `s` into the current context of size `s`."""
|
||||
|
||||
textRects = {
|
||||
512: ((0, 7), (512, 119)),
|
||||
128: ((0, 6), (128, 26.5)),
|
||||
256: ((0, 7), (256, 57)),
|
||||
16: ((1, 1), (15, 5)),
|
||||
#32: ((1, 1), (31, 9))
|
||||
}
|
||||
|
||||
attribs = self.attribsAtSize(s)
|
||||
text = NSString.stringWithString_(text)
|
||||
if s in [16, 128, 256, 512]:
|
||||
text.drawInRect_withAttributes_(textRects[s], attribs)
|
||||
elif s == 32:
|
||||
# Try to align text on pixel boundary:
|
||||
attribs = attribs.copy()
|
||||
attribs[NSParagraphStyleAttributeName] = \
|
||||
NSParagraphStyle.defaultParagraphStyle()
|
||||
ts = text.sizeWithAttributes_(attribs)
|
||||
text.drawAtPoint_withAttributes_( (math.floor((32.0-ts[0])/2) + 0.5, 1.5),
|
||||
attribs)
|
||||
|
||||
|
||||
def createIcon(outname, text, ground, icon, shadow=None, s=512,
|
||||
shorttext=None):
|
||||
class OfficeTextRenderer(TextRenderer):
|
||||
"""Uses Office's LucidaSans font for 32x32.
|
||||
|
||||
output = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(
|
||||
None, s, s, 8, 4, True, False, NSDeviceRGBColorSpace, 0, 0, 0)
|
||||
This font looks much better for certain strings (e.g. "PDF") but much worse
|
||||
for most others (e.g. "VIM", "JAVA") -- and office fonts are usually not
|
||||
installed. Hence, this class is better not used.
|
||||
"""
|
||||
|
||||
# Draw!
|
||||
NSGraphicsContext.saveGraphicsState();
|
||||
context = NSGraphicsContext. graphicsContextWithBitmapImageRep_(output);
|
||||
context.setShouldAntialias_(True);
|
||||
context.setImageInterpolation_(NSImageInterpolationHigh);
|
||||
NSGraphicsContext.setCurrentContext_(context);
|
||||
def _attribsAtSize(self, s):
|
||||
self.useOfficeFont = False
|
||||
attribs = TextRenderer._attribsAtSize(self, s)
|
||||
if s == 32:
|
||||
font = NSFont.fontWithName_size_('LucidaSans-Demi', 7.0)
|
||||
if font:
|
||||
attribs[NSFontAttributeName] = font
|
||||
attribs[NSKernAttributeName] = 0
|
||||
self.useOfficeFont = True
|
||||
return attribs
|
||||
|
||||
def drawTextAtSize(self, text, s):
|
||||
attribs = self.attribsAtSize(s)
|
||||
if not self.useOfficeFont or s != 32:
|
||||
TextRenderer.drawTextAtSize(self, text, s)
|
||||
return
|
||||
text = NSString.stringWithString_(text)
|
||||
text.drawInRect_withAttributes_( ((0, 1), (31, 11)), attribs)
|
||||
|
||||
|
||||
# luckily, cocoa simply copies the 128x128 version over for s = 128
|
||||
# and does no resampling.
|
||||
ground.draw()
|
||||
#bg.drawInRect_fromRect_operation_fraction_(
|
||||
#((0, 0), (s, s)),
|
||||
#NSZeroRect, NSCompositeCopy, 1.0)
|
||||
def createIcon(outname, s, bg, textRenderer, text, shorttext=None):
|
||||
|
||||
# found by flow program, better than anything i came up with manually before
|
||||
# (except for the 16x16 variant :-( )
|
||||
transforms = {
|
||||
512: [ 0.7049, 0.5653, -4.2432, 0.5656],
|
||||
256: [ 0.5690, 0.5658, -1.9331, 0.5656],
|
||||
128: [ 1.1461, 0.5684, -0.8482, 0.5681],
|
||||
# Fill in background
|
||||
output = bg.backgroundAtSize(s).copy()
|
||||
|
||||
32: [-0.2682, 0.5895, -2.2130, 0.5701], # intensity
|
||||
#32: [-0.2731, 0.5898, -2.2262, 0.5729], # rgb (no rmse difference)
|
||||
|
||||
#16: [-0.3033, 0.4909, -1.3235, 0.4790], # program, intensity
|
||||
#16: [-0.3087, 0.4920, -1.2990, 0.4750], # program, rgb mode
|
||||
16: [ 0.0000, 0.5000, -1.0000, 0.5000], # manually, better
|
||||
}
|
||||
|
||||
if s in [16, 32, 128, 256, 512]:
|
||||
a = transforms[s]
|
||||
|
||||
# convert from `flow` coords to cocoa
|
||||
a[2] = -a[2] # mirror y
|
||||
|
||||
w, h = s*a[1], s*a[3]
|
||||
icon.drawInRect_fromRect_operation_fraction_(
|
||||
(((s-w)/2 + a[0], (s-h)/2 + a[2]), (w, h)),
|
||||
NSZeroRect, NSCompositeSourceOver, 1.0)
|
||||
|
||||
|
||||
# Overlay shadow.
|
||||
# shadow needs to be composited, so it needs to be in an nsimage
|
||||
shadowImg = NSImage.alloc().initWithSize_( (s, s) )
|
||||
shadowImg.addRepresentation_(shadow)
|
||||
shadowImg.drawInRect_fromRect_operation_fraction_(
|
||||
((0, 0), (s, s)),
|
||||
NSZeroRect, NSCompositeSourceOver, 1.0)
|
||||
|
||||
|
||||
# draw text on top of shadow
|
||||
# Draw text on top of shadow
|
||||
context = Context(output)
|
||||
if s in [16, 32] and shorttext:
|
||||
text = shorttext
|
||||
drawText(text, s)
|
||||
|
||||
|
||||
NSGraphicsContext.restoreGraphicsState();
|
||||
textRenderer.drawTextAtSize(text, s)
|
||||
context.done()
|
||||
|
||||
# Save
|
||||
png = output.representationUsingType_properties_(NSPNGFileType, None)
|
||||
png.writeToFile_atomically_(outname, True)
|
||||
output.save(outname)
|
||||
|
||||
|
||||
def createLinks(icons, target):
|
||||
assert len(icons) > 0
|
||||
for name in icons:
|
||||
icnsName = '%s.icns' % name
|
||||
if os.access(icnsName, os.F_OK):
|
||||
os.remove(icnsName)
|
||||
os.symlink(target, icnsName)
|
||||
|
||||
|
||||
TMPFILE = 'make_icons_tmp_%d.png'
|
||||
@@ -333,31 +473,24 @@ def main():
|
||||
print "PyObjC not found, only using a stock icon for document icons."
|
||||
import shutil
|
||||
shutil.copyfile(BACKGROUND, '%s.icns' % GENERIC_ICON_NAME)
|
||||
for name in vimIcons:
|
||||
if name == GENERIC_ICON_NAME: continue
|
||||
icnsName = '%s.icns' % name
|
||||
if os.access(icnsName, os.F_OK):
|
||||
os.remove(icnsName)
|
||||
os.symlink('%s.icns' % GENERIC_ICON_NAME, icnsName)
|
||||
createLinks([name for name in vimIcons if name != GENERIC_ICON_NAME],
|
||||
'%s.icns' % GENERIC_ICON_NAME)
|
||||
return
|
||||
# Make us not crash
|
||||
# http://www.cocoabuilder.com/archive/message/cocoa/2008/8/6/214964
|
||||
NSApplicationLoad()
|
||||
|
||||
textRenderer = TextRenderer()
|
||||
#textRenderer = OfficeTextRenderer()
|
||||
|
||||
# Prepare input images
|
||||
bg = NSImage.alloc().initWithContentsOfFile_(BACKGROUND)
|
||||
if not bg:
|
||||
print 'Failed to load', bgname
|
||||
sys.exit(1)
|
||||
bgIcon = Image(BACKGROUND)
|
||||
|
||||
grounds, shadows = zip(*[splitGenericDocumentIcon(bg, s) for s in sizes])
|
||||
grounds = dict(zip(sizes, grounds))
|
||||
shadows = dict(zip(sizes, shadows))
|
||||
#bg = SplittableBackground(bgIcon, shouldSplit=False)
|
||||
bg = SplittableBackground(bgIcon, shouldSplit=True)
|
||||
|
||||
icon = NSImage.alloc().initWithContentsOfFile_(appIcon)
|
||||
if not icon:
|
||||
print 'Failed to load', appIcon
|
||||
sys.exit(1)
|
||||
icon = Image(appIcon)
|
||||
bgRenderer = BackgroundRenderer(bg, icon)
|
||||
|
||||
if not os.access(makeIcns, os.X_OK):
|
||||
print 'Cannot find makeicns at %s', makeIcns
|
||||
@@ -370,33 +503,26 @@ def main():
|
||||
print name
|
||||
icnsName = '%s.icns' % name
|
||||
|
||||
for s in sizes:
|
||||
st = shorttext.get(name)
|
||||
if st: st = NSString.stringWithString_(st)
|
||||
createIcon(TMPFILE % s, NSString.stringWithString_(text),
|
||||
grounds[s], icon, shadows[s], s=s, shorttext=st)
|
||||
if size == SMALL:
|
||||
currSizes = [128, 32, 16]
|
||||
args = '-128 %s -32 %s -16 %s' % (
|
||||
TMPFILE % 128, TMPFILE % 32, TMPFILE % 16)
|
||||
elif size == LARGE:
|
||||
currSizes = [512, 128, 32, 16]
|
||||
args = '-512 %s -128 %s -32 %s -16 %s' % (
|
||||
TMPFILE % 512, TMPFILE % 128, TMPFILE % 32, TMPFILE % 16)
|
||||
|
||||
if size == LARGE:
|
||||
os.system('%s -512 %s -128 %s -32 %s -16 %s -out %s' % (makeIcns,
|
||||
TMPFILE % 512, TMPFILE % 128, TMPFILE % 32, TMPFILE % 16, icnsName))
|
||||
elif size == SMALL:
|
||||
os.system('%s -128 %s -32 %s -16 %s -out %s' % (makeIcns,
|
||||
TMPFILE % 128, TMPFILE % 32, TMPFILE % 16, icnsName))
|
||||
st = shorttext.get(name)
|
||||
for s in currSizes:
|
||||
createIcon(TMPFILE % s, s, bgRenderer, textRenderer, text, shorttext=st)
|
||||
|
||||
os.system('%s %s -out %s' % (makeIcns, args, icnsName))
|
||||
|
||||
del text, size, name, t
|
||||
|
||||
# ...create links later (to make sure the link targets exist)
|
||||
for name, t in vimIcons.iteritems():
|
||||
text, size = t
|
||||
if size != LINK: continue
|
||||
print 'symlinking', name
|
||||
icnsName = '%s.icns' % name
|
||||
|
||||
# remove old version of icns
|
||||
if os.access(icnsName, os.F_OK):
|
||||
os.remove(icnsName)
|
||||
os.symlink('%s.icns' % GENERIC_ICON_NAME, icnsName)
|
||||
|
||||
createLinks([name for (name, t) in vimIcons.items() if t[1] == LINK],
|
||||
'%s.icns' % GENERIC_ICON_NAME)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user