Skip to content
Snippets Groups Projects
Commit 244ebf43 authored by George Nachman's avatar George Nachman
Browse files

Add support for insets inline images. Add optional paramters insetLeft,...

Add support for insets inline images. Add optional paramters insetLeft, insetRight, insetTop, and insetBottom, which default to zero. The image will be inset within its original space. The insets are clamped to the size of a character cell. Issue 4419.
parent b8a0c705
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -2376,7 +2376,7 @@
A67F57AE1B012BD100B4F135 /* NSWorkspace+iTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWorkspace+iTerm.h"; sourceTree = "<group>"; };
A67F57AF1B012BD100B4F135 /* NSWorkspace+iTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWorkspace+iTerm.m"; sourceTree = "<group>"; };
A67F57B51B01A01800B4F135 /* iTermImageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTermImageInfo.h; sourceTree = "<group>"; };
A67F57B61B01A01800B4F135 /* iTermImageInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iTermImageInfo.m; sourceTree = "<group>"; };
A67F57B61B01A01800B4F135 /* iTermImageInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = iTermImageInfo.m; sourceTree = "<group>"; };
A67F57BC1B01A08800B4F135 /* iTermAnimatedImageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTermAnimatedImageInfo.h; sourceTree = "<group>"; };
A67F57BD1B01A08800B4F135 /* iTermAnimatedImageInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iTermAnimatedImageInfo.m; sourceTree = "<group>"; };
A67F57C41B0930CA00B4F135 /* iTermFileDescriptorServer.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = iTermFileDescriptorServer.c; sourceTree = "<group>"; tabWidth = 4; };
Loading
Loading
Loading
Loading
@@ -1889,6 +1889,7 @@ ITERM_WEAKLY_REFERENCEABLE
[_terminal setBackgroundColor:ALTSEM_DEFAULT
alternateSemantics:YES];
int width = (_screen.width - message.length) / 2;
const NSEdgeInsets zeroInset = { 0 };
if (width > 0) {
[_screen appendImageAtCursorWithName:@"BrokenPipeDivider"
width:width
Loading
Loading
@@ -1896,6 +1897,7 @@ ITERM_WEAKLY_REFERENCEABLE
height:1
units:kVT100TerminalUnitsCells
preserveAspectRatio:NO
inset:zeroInset
image:[NSImage imageNamed:@"BrokenPipeDivider"]
data:nil];
}
Loading
Loading
@@ -1908,6 +1910,7 @@ ITERM_WEAKLY_REFERENCEABLE
height:1
units:kVT100TerminalUnitsCells
preserveAspectRatio:NO
inset:zeroInset
image:[NSImage imageNamed:@"BrokenPipeDivider"]
data:nil];
}
Loading
Loading
Loading
Loading
@@ -6094,9 +6094,7 @@ static double EuclideanDistance(NSPoint p1, NSPoint p2) {
 
- (void)_dragImage:(iTermImageInfo *)imageInfo forEvent:(NSEvent *)theEvent
{
NSSize region = NSMakeSize(_charWidth * imageInfo.size.width,
_lineHeight * imageInfo.size.height);
NSImage *icon = [imageInfo imageEmbeddedInRegionOfSize:region];
NSImage *icon = [imageInfo imageWithCellSize:NSMakeSize(_charWidth, _lineHeight)];
 
NSData *imageData = imageInfo.data;
if (!imageData) {
Loading
Loading
Loading
Loading
@@ -397,8 +397,13 @@ BOOL StringContainsCombiningMark(NSString *s);
// Allocates a new image code and sets in the return value. The image will be
// displayed in the terminal with width x height cells. If preserveAspectRatio
// is set then background-color bars will be added on the edges so the image is
// not distorted.
screen_char_t ImageCharForNewImage(NSString *name, int width, int height, BOOL preserveAspectRatio);
// not distorted. Insets should be specified as a fraction of cell size (all inset values should be
// in [0, 1] and will be multiplied by cell width and height before rendering.).
screen_char_t ImageCharForNewImage(NSString *name,
int width,
int height,
BOOL preserveAspectRatio,
NSEdgeInsets insets);
 
// Sets the row and column number in an image cell. Goes from 0 to width/height
// as specified in the preceding call to ImageCharForNewImage.
Loading
Loading
Loading
Loading
@@ -227,8 +227,11 @@ static void AllocateImageMapsIfNeeded(void) {
}
}
 
screen_char_t ImageCharForNewImage(NSString *name, int width, int height, BOOL preserveAspectRatio)
{
screen_char_t ImageCharForNewImage(NSString *name,
int width,
int height,
BOOL preserveAspectRatio,
NSEdgeInsets inset) {
AllocateImageMapsIfNeeded();
int newKey;
do {
Loading
Loading
@@ -243,6 +246,7 @@ screen_char_t ImageCharForNewImage(NSString *name, int width, int height, BOOL p
imageInfo.filename = name;
imageInfo.preserveAspectRatio = preserveAspectRatio;
imageInfo.size = NSMakeSize(width, height);
imageInfo.inset = inset;
gImages[@(c.code)] = imageInfo;
 
return c;
Loading
Loading
Loading
Loading
@@ -149,6 +149,7 @@ extern int kVT100ScreenMinRows;
height:(int)height
units:(VT100TerminalUnits)heightUnits
preserveAspectRatio:(BOOL)preserveAspectRatio
inset:(NSEdgeInsets)inset
image:(NSImage *)image
data:(NSData *)data; // data is optional and only used by animated GIFs
 
Loading
Loading
Loading
Loading
@@ -160,6 +160,7 @@ static NSString *const kInlineFileHeight = @"height"; // NSNumber
static NSString *const kInlineFileHeightUnits = @"height units"; // NSNumber of VT100TerminalUnits
static NSString *const kInlineFilePreserveAspectRatio = @"preserve aspect ratio"; // NSNumber bool
static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutableString
static NSString *const kInilineFileInset = @"inset"; // NSValue of NSEdgeInsets
 
@synthesize terminal = terminal_;
@synthesize audibleBell = audibleBell_;
Loading
Loading
@@ -3309,7 +3310,8 @@ static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutable
units:(VT100TerminalUnits)widthUnits
height:(int)height
units:(VT100TerminalUnits)heightUnits
preserveAspectRatio:(BOOL)preserveAspectRatio {
preserveAspectRatio:(BOOL)preserveAspectRatio
inset:(NSEdgeInsets)inset {
[inlineFileInfo_ release];
inlineFileInfo_ = [@{ kInlineFileName: name,
kInlineFileWidth: @(width),
Loading
Loading
@@ -3317,7 +3319,8 @@ static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutable
kInlineFileHeight: @(height),
kInlineFileHeightUnits: @(heightUnits),
kInlineFilePreserveAspectRatio: @(preserveAspectRatio),
kInlineFileBase64String: [NSMutableString string] } retain];
kInlineFileBase64String: [NSMutableString string],
kInilineFileInset: [NSValue valueWithEdgeInsets:inset] } retain];
}
 
- (void)appendImageAtCursorWithName:(NSString *)name
Loading
Loading
@@ -3326,6 +3329,7 @@ static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutable
height:(int)height
units:(VT100TerminalUnits)heightUnits
preserveAspectRatio:(BOOL)preserveAspectRatio
inset:(NSEdgeInsets)inset
image:(NSImage *)image
data:(NSData *)data {
if (!image) {
Loading
Loading
@@ -3405,7 +3409,17 @@ static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutable
// TODO: Support scroll regions.
int xOffset = self.cursorX - 1;
int screenWidth = currentGrid_.size.width;
screen_char_t c = ImageCharForNewImage(name, width, height, preserveAspectRatio);
NSEdgeInsets fractionalInset = {
.left = MAX(MIN(inset.left / cellSize.width, 1), 0),
.top = MAX(MIN(inset.top / cellSize.height, 1), 0),
.right = MAX(MIN(inset.right / cellSize.width, 1), 0),
.bottom = MAX(MIN(inset.bottom / cellSize.height, 1), 0)
};
screen_char_t c = ImageCharForNewImage(name,
width,
height,
preserveAspectRatio,
fractionalInset);
for (int y = 0; y < height; y++) {
if (y > 0) {
[self linefeed];
Loading
Loading
@@ -3442,6 +3456,7 @@ static NSString *const kInlineFileBase64String = @"base64 string"; // NSMutable
height:[inlineFileInfo_[kInlineFileHeight] intValue]
units:(VT100TerminalUnits)[inlineFileInfo_[kInlineFileHeightUnits] intValue]
preserveAspectRatio:[inlineFileInfo_[kInlineFilePreserveAspectRatio] boolValue]
inset:[inlineFileInfo_[kInilineFileInset] edgeInsetsValue]
image:image
data:data];
[inlineFileInfo_ release];
Loading
Loading
Loading
Loading
@@ -1984,18 +1984,30 @@ static const int kMaxScreenRows = 4096;
heightUnits = kVT100TerminalUnitsPercentage;
}
 
CGFloat insetTop = [dict[@"insetTop"] doubleValue];
CGFloat insetLeft = [dict[@"insetLeft"] doubleValue];
CGFloat insetBottom = [dict[@"insetBottom"] doubleValue];
CGFloat insetRight = [dict[@"insetRight"] doubleValue];
NSString *name = [dict[@"name"] stringByBase64DecodingStringWithEncoding:NSISOLatin1StringEncoding];
if (!name) {
name = @"Unnamed file";
}
if ([dict[@"inline"] boolValue]) {
NSEdgeInsets inset = {
.top = insetTop,
.left = insetLeft,
.bottom = insetBottom,
.right = insetRight
};
[delegate_ terminalWillReceiveInlineFileNamed:name
ofSize:[dict[@"size"] intValue]
width:width
units:widthUnits
height:height
units:heightUnits
preserveAspectRatio:[dict[@"preserveAspectRatio"] boolValue]];
preserveAspectRatio:[dict[@"preserveAspectRatio"] boolValue]
inset:inset];
} else {
[delegate_ terminalWillReceiveFileNamed:name ofSize:[dict[@"size"] intValue]];
}
Loading
Loading
Loading
Loading
@@ -295,7 +295,8 @@ typedef NS_ENUM(NSInteger, VT100TerminalUnits) {
units:(VT100TerminalUnits)widthUnits
height:(int)height
units:(VT100TerminalUnits)heightUnits
preserveAspectRatio:(BOOL)preserveAspectRatio;
preserveAspectRatio:(BOOL)preserveAspectRatio
inset:(NSEdgeInsets)inset;
 
// Download completed normally
- (void)terminalDidFinishReceivingFile;
Loading
Loading
Loading
Loading
@@ -25,6 +25,9 @@
// Original filename
@property(nonatomic, copy) NSString *filename;
 
// Inset for the image within its area.
@property(nonatomic, assign) NSEdgeInsets inset;
// Image code
@property(nonatomic, readonly) unichar code;
 
Loading
Loading
@@ -50,9 +53,9 @@
// Used to create a new instance from a coded dictionary.
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
 
// Returns an image of size |region| containing a scaled copy of |image| and
// transparency around two edges if |region| != |image.size|.
- (NSImage *)imageEmbeddedInRegionOfSize:(NSSize)region;
// Returns an image whose size is self.size * cellSize. If the image is smaller and/or has an inset
// there will be a transparent area around the edges.
- (NSImage *)imageWithCellSize:(CGSize)cellSize;
 
// Binds an image. Data is optional and only used for animated GIFs. Not to be used after
// -initWithDictionary.
Loading
Loading
Loading
Loading
@@ -16,6 +16,7 @@ static NSString *const kImageInfoSizeKey = @"Size";
static NSString *const kImageInfoImageKey = @"Image"; // data
static NSString *const kImageInfoPreserveAspectRatioKey = @"Preserve Aspect Ratio";
static NSString *const kImageInfoFilenameKey = @"Filename";
static NSString *const kImageInfoInsetKey = @"Inset";
static NSString *const kImageInfoCodeKey = @"Code";
 
@interface iTermImageInfo ()
Loading
Loading
@@ -41,6 +42,7 @@ static NSString *const kImageInfoCodeKey = @"Code";
self = [super init];
if (self) {
_size = [dictionary[kImageInfoSizeKey] sizeValue];
_inset = [dictionary[kImageInfoInsetKey] edgeInsetsValue];
_data = [dictionary[kImageInfoImageKey] retain];
_animatedImage = [[iTermAnimatedImageInfo alloc] initWithData:_data];
if (!_animatedImage) {
Loading
Loading
@@ -90,6 +92,7 @@ static NSString *const kImageInfoCodeKey = @"Code";
 
- (NSDictionary *)dictionary {
return @{ kImageInfoSizeKey: [NSValue valueWithSize:_size],
kImageInfoInsetKey: [NSValue valueWithEdgeInsets:_inset],
kImageInfoImageKey: _data ?: [NSData data],
kImageInfoPreserveAspectRatioKey: @(_preserveAspectRatio),
kImageInfoFilenameKey: _filename ?: @"",
Loading
Loading
@@ -109,7 +112,7 @@ static NSString *const kImageInfoCodeKey = @"Code";
}
}
 
- (NSImage *)imageEmbeddedInRegionOfSize:(NSSize)region {
- (NSImage *)imageWithCellSize:(CGSize)cellSize {
if (!_image && !_animatedImage) {
return nil;
}
Loading
Loading
@@ -119,6 +122,8 @@ static NSString *const kImageInfoCodeKey = @"Code";
int frame = _animatedImage.currentFrame; // 0 if not animated
NSImage *embeddedImage = _embeddedImages[@(frame)];
 
NSSize region = NSMakeSize(cellSize.width * _size.width,
cellSize.height * _size.height);
if (!NSEqualSizes(embeddedImage.size, region)) {
NSImage *canvas = [[[NSImage alloc] init] autorelease];
NSSize size;
Loading
Loading
@@ -143,10 +148,15 @@ static NSString *const kImageInfoCodeKey = @"Code";
}
[canvas setSize:region];
[canvas lockFocus];
[theImage drawInRect:NSMakeRect((region.width - size.width) / 2,
(region.height - size.height) / 2,
size.width,
size.height)];
NSEdgeInsets inset = _inset;
inset.top *= cellSize.height;
inset.bottom *= cellSize.height;
inset.left *= cellSize.width;
inset.right *= cellSize.width;
[theImage drawInRect:NSMakeRect((region.width - size.width) / 2 + inset.left,
(region.height - size.height) / 2 + inset.bottom,
MAX(0, size.width - inset.left - inset.right),
MAX(0, size.height - inset.top - inset.bottom))];
[canvas unlockFocus];
 
self.embeddedImages[@(frame)] = canvas;
Loading
Loading
Loading
Loading
@@ -908,9 +908,7 @@ extern int CGContextGetFontSmoothingStyle(CGContextRef);
 
- (void)drawImageCellInRun:(CRun *)run atPoint:(NSPoint)point {
iTermImageInfo *imageInfo = GetImageInfo(run->attrs.imageCode);
NSImage *image =
[imageInfo imageEmbeddedInRegionOfSize:NSMakeSize(_cellSize.width * imageInfo.size.width,
_cellSize.height * imageInfo.size.height)];
NSImage *image = [imageInfo imageWithCellSize:_cellSize];
NSSize chunkSize = NSMakeSize(image.size.width / imageInfo.size.width,
image.size.height / imageInfo.size.height);
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment