1/*
2    PPGNUstepGlue_PatternColorDrawingSpeedup.m
3
4    Copyright 2014-2018 Josh Freeman
5    http://www.twilightedge.com
6
7    This file is part of PikoPixel for GNUstep.
8    PikoPixel is a graphical application for drawing & editing pixel-art images.
9
10    PikoPixel is free software: you can redistribute it and/or modify it under
11    the terms of the GNU Affero General Public License as published by the
12    Free Software Foundation, either version 3 of the License, or (at your
13    option) any later version approved for PikoPixel by its copyright holder (or
14    an authorized proxy).
15
16    PikoPixel is distributed in the hope that it will be useful, but WITHOUT ANY
17    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18    FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19    details.
20
21    You should have received a copy of the GNU Affero General Public License
22    along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25// Speedup for drawing small-image pattern colors on GNUstep (Cairo?)
26
27#ifdef GNUSTEP
28
29#import <Cocoa/Cocoa.h>
30#import "NSObject_PPUtilities.h"
31#import "PPAppBootUtilities.h"
32#import "PPGeometry.h"
33
34
35#define kMinPatternImageDimension   32
36
37
38@implementation NSObject (PPGNUstepGlue_PatternColorDrawingSpeedup)
39
40// AA_ was inserted into the name of the _InstallPatches method to make sure it gets called
41// before ppGSGlue_BitmapGraphicsContext_Install (AfterAppLoads selectors are called
42// alphabetically) - this is because installing the BitmapGraphicsContext patches causes
43// +[PPCanvasView initialize] to be called, which loads some pattern colors (selection-tool
44// overlay)
45
46+ (void) ppGSGlue_AA_PatternColorDrawingSpeedup_InstallPatches
47{
48    macroSwizzleClassMethod(NSColor, colorWithPatternImage:, ppGSPatch_ColorWithPatternImage:);
49}
50
51+ (void) load
52{
53    macroPerformNSObjectSelectorAfterAppLoads(
54                                        ppGSGlue_AA_PatternColorDrawingSpeedup_InstallPatches);
55}
56
57@end
58
59@implementation NSColor (PPGNUstepGlue_PatternColorDrawingSpeedup)
60
61// PATCH: -[NSColor colorWithPatternImage:]
62//  On GNUstep (Cairo?), pattern-colors made from small images (< 32x32) draw slowly.
63//  The patch speeds up drawing by only returning pattern-colors with 32x32 (or larger) images;
64// When the passed image is too small, the returned pattern-color instead uses an upsized image,
65// drawn by tiling the original.
66
67+ (NSColor *) ppGSPatch_ColorWithPatternImage: (NSImage *) image
68{
69    NSColor *patternColor;
70    NSSize imageSize, minPatternSize;
71
72    patternColor = [self ppGSPatch_ColorWithPatternImage: image];
73
74    if (!patternColor)
75        goto ERROR;
76
77    imageSize = [image size];
78
79    if (PPGeometry_IsZeroSize(imageSize))
80    {
81        goto ERROR;
82    }
83
84    minPatternSize =
85            NSMakeSize(imageSize.width * ceilf(kMinPatternImageDimension / imageSize.width),
86                        imageSize.height * ceilf(kMinPatternImageDimension / imageSize.height));
87
88    if (!NSEqualSizes(imageSize, minPatternSize))
89    {
90        NSImage *upsizedPatternImage;
91        NSColor *upsizedPatternColor;
92
93        upsizedPatternImage = [[[NSImage alloc] initWithSize: minPatternSize] autorelease];
94
95        if (!upsizedPatternImage)
96            goto ERROR;
97
98        [upsizedPatternImage lockFocus];
99
100        [patternColor set];
101        NSRectFill(PPGeometry_OriginRectOfSize(minPatternSize));
102
103        [upsizedPatternImage unlockFocus];
104
105        upsizedPatternColor = [self ppGSPatch_ColorWithPatternImage: upsizedPatternImage];
106
107        if (!upsizedPatternColor)
108            goto ERROR;
109
110        patternColor = upsizedPatternColor;
111    }
112
113    return patternColor;
114
115ERROR:
116    return patternColor;
117}
118
119@end
120
121#endif  // GNUSTEP
122
123