## KaleidoTile

# Revision History

4.4 | 15 Dec 2025 | Zoom and crop images from camera. Minor changes for better legibility on iOS/iPadOS/macOS 26.
4.3.1 | 26 May 2025 | In macOS App Sandbox settings, added read/write permission for user-selected files.
4.3.0 | 23 May 2025 | Runs on macOS as well as iOS and iPadOS. Exports PNG images as Mail, Messages, AirDrop, Save to Files, Copy, etc Updated for iOS 17+
| 14 Nov 2024 | Full Swift 6 Concurrency.
4.2.2 | 24 Feb 2024 | Added option to disable Inertia.
4.2.1 | 7 Jan 2024 | Added German translation, thanks to Stas Drisner.
4.2.0 | 10 May 2023 | Entire app re-written in Swift and SwiftUI. Eliminates frame-by-frame retiling for greatly reduced CPU load. Instead it uses a fixed tiling, and lets the tiling's orientation to be alternately plain and reflected, so that the "popping" around the perimeter of the hyperbolic tiling becomes unnoticeable. In the face decoration panel, a NavigationView works fine on iPhone but fails completely on iPad (it fails differently on iPadOS 15 and 16, but fails on both). So I replaced the NavigationView (which is deprecated in iOS 16) with a NavigationStack (which was first introduced in iOS 16) and increased the deployment target to iOS 16.0. Added "Image from Files" to complement "Image from Photo Library"
4.1.5 | 17 May 2022 | (macOS) Replaced the old Mac-specific KaleidoTile (which relied on OpenGL graphics, which Apple deprecated 4 years ago) with a new MacCatalyst adaptation of iOS KaleidoTile (which uses Metal graphics). (macOS) Let user save image to any folder, with any name (not just to Photos Library).
| 16 May 2022 | (iOS) Increased PICKER_DIGIT_WIDTH from 24.0 to 36.0 for compatibility with current iOS.
| 19 Dec 2021 | (legacy iOS) Changed iOS Deployment Target to iOS 14, because Apple has stopped supporting iOS 12. Thus, in particular, I no longer have a maintainable iOS 12 device to test on. (legacy iOS) Added UINavigationBarAppearance so that navigation bars will have an opaque background when running on iOS 15.
| 22 Nov 2020 | Changed various GPU uniforms, colors in buffers, etc. to half-precision (__fp16 and faux_simd_half4) where appropriate.
| 5 Nov 2020 | Removed workaround for bug that function-constant assignments like constant bool gFoo [[ function_constant(0) ]]; constant bool gBar = ! gFoo; used to work as expected on iOS but fail on macOS. They now work correctly on both OS’s.
4.1.4 | 30 Jun 2020 | Adapted color picker to use wide-color when available.
| 30 Jun 2020 | Implemented -gestureRecognizerShouldBegin: to return NO, to fix a bug that had allowed a drag in KaleidoTile's color picker to get "stolen" and re-interpreted as a scroll of the enclosing popover.
| 29 Jun 2020 | Replaced manual texture loading with Asset Catalogs and MTKTextureLoader.
| 16 Apr 2020 | Renders to Wide Color (Display P3) when available. Some of the shared code that won't be needed in the upcoming SwiftUI versions of the Geometry Games apps has been migrated to "-LEGACY" files, to allow the SwiftUI versions to include desired utilities without including legacy cruft like PixelRGBA, ImageRGBA, etc.
4.1.3 | 31 Mar 2020 | (iOS) Converted launch screen format from .xib to .storyboard to comply with new App Store requirements. (iOS) Toolbar self-adjusts at runtime to default height for device (iPad or iPhone). (iOS) Made toolbar opaque to make it brighter.
4.1.2 | 8 Nov 2019 | Replaced functions deprecated in iOS 13 or macOS 10.15 with non-deprecated alternatives.
4.1.1 | 13 Jan 2019 | (iOS) Fixed bug to allow proper creation of mipmapped power-of-two size textures (for example from the user's photo library) on devices with 3× displays (for example on iPhone X). Thanks to Bondy Palien for reporting this bug.
4.1 | 11 Nov 2018 | (macOS) Enabled Hardened Runtime to allow Notarization by Apple.
| 17 Oct 2018 | (iOS) Table images, toolbar icons and other images re-created at @1x, @2x and @3x. Source files for those images all simplified and tidied up (now mostly as iDraw files). (iOS) Toolbar icons resized to 24pt, which is the new recommended size.
| 16 Sep 2018 | (iOS) Removed vestigial OpenGL ES code.
| 30 Apr 2018 | (macOS) On multi-GPU systems, selects the GPU that's already running the displays attached to the main computer (but ignores any externally attached removable GPUs). If the system switches to a different GPU, this app switches to that GPU as well. (macOS) No longer calls [[NSNotificationCenter defaultCenter] removeObserver:self] because it's no longer necessary.
4.0 | 20 Apr 2018 | New: KaleidoTile for iOS
| 20 Apr 2018 | Lets users decorate their polyhedra and tilings using images from their photo library or images taken directly with their device's camera
| 20 Apr 2018 | Graphics rewritten using Metal
| 14 Apr 2018 | (macOS) Main content view is now layer-backed. When going fullscreen, avoids macOS 10.13.4 bug.
| 28 Sep 2017 | CPU code consistently uses "double" (rather than "float") for essentially everything.
| 12 Dec 2016 | (macOS) Exports images as PNG instead of TIFF.
| 6 Dec 2016 | (Mac) Mac version is now Metal-only. Reason: The Mac OpenGL version of the Geometry Games uses an older approach that would have been very time-consuming to rewrite using a CAOpenGLLayer to bring it into line with iOS OpenGL, iOS Metal and Mac Metal versions. It hardly seemed worth investing that much time into OpenGL code that would soon get phased out anyhow. In any case, users of older Macs will always be able to download an older, OpenGL-compatible version of each app. (Mac) Given that the Mac version is now Metal-only, it now requires macOS 10.12 or later. Reason: macOS 10.12 is the only version I can test the apps on, and I prefer not to release an app for earlier versions of the operating system, on which it's never been tested.
| 30 Nov 2016 | Created a single project document with targets for iOS and macOS. Created that single project document from scratch, to get rid of years of legacy cruft.
| 15 May 2016 | Separated OpenGL(ES)-specific data and code from graphics-system-independent data and code, in preparation for a migration from OpenGL(ES) to Metal on iOS and Mac (and maybe eventually to Vulkan on Android and to DX12 on Windows).
3.10 | 20 Apr 2016 | Added Chinese translation, thanks to 焦堂生 (Tangsheng Jiao).
3.9 | 17 Nov 2015 | (Mac) Updated code for Mac OS X 10.10, replacing all deprecated method calls. Requires OpenGL 3.3.
| 12 Nov 2015 | (Mac) Converted memory management from Manual Retain-Release (MRR) to Automatic Reference Counting (ARC).
| 16 Oct 2015 | Suppressed the Language menu to avoid displaying UniHan characters incorrectly (and also because the Language menu wasn't really useful except in the Torus Games).
| 12 Jan 2015 | Moved MIDI and WAV playback to shared code.
3.8.2 | 22 Aug 2014 | Further migration to Char16.
| 21 Aug 2014 | Expanded visibility of OpenGL headers, so the ModelData can refer to OpenGL objects as GLuint instead of "unsigned int", thus improving clarity and avoiding integer conversion warnings.
| 20 Aug 2014 | Replaced L"…" → u"…" and L'·' → u'·'. The L syntax required -fshort-wchar to get 16-bit wide characters and generated copious warnings in Android, while the u syntax is part of the C11 standard.
| 19 Aug 2014 | Completed deferred maintenance of Windows version (accommodated changes from last 15 months when I had no Windows computer).
| 16 Dec 2013 | Handles localized text as UTF-16 instead of UTF-8.
3.8.1 | 16 May 2013 | (Win) Improved font quality (especially East Asian) on Windows Vista and newer.
3.8 | 9 May 2013 | First version requiring OpenGL 3.2 or OpenGL ES 2.0.
3.7 | 2 May 2013 | Last version compatible with OpenGL 2.
| 24 Apr 2013 | (Win) Moved much functionality from individual applications to shared code. (Win) Simplified implementation of various features. Removed cruft.
| 8 Mar 2013 | (Mac) Moved much functionality from individual applications to shared code.
| 5 Mar 2013 | Replaced platform-specific language lists with a single language list in app's common code. Simplified language menu handling. Moved endonyms and Win32 LANGIDs to Geometry Games shared code.
| 28 Feb 2013 | (Mac) Updated Objective-C syntax to use @{}, @[], @() and @autorelease.
| 21 Nov 2012 | (Mac) Re-organized instance variables, moving them from .h to .m files (@interface to @implementation) as allowed by the “new” Objective-C runtime.
3.6.6 | 2 Oct 2012 | (Win) To avoid bugs in Intel Integrated Graphics drivers, ignores VAO extension and directs all OpenGL 2 users (on Windows) to the legacy version of the program. Simplified extensions handling.
| 1 Jul 2012 | Instanced vertex attribute arrays work spectacularly well, so I eliminated USE_INSTANCED_TILING_ARRAY, making the changes permanent.
| 28 Jun 2012 | Portuguese menus and study questions revised to conform to the Acordo Ortográfico of 1990, which went into effect in 2009.
| 12 Jun 2012 | (Mac) imageAsBitmapImageRepOfSize rescales images larger than 1024×1024 when running with OpenGL 2 (on older computers), but leaves the requested size unchanged when running with OpenGL 3 (on mid-aged or newer computers).
3.6.5 | 3 Feb 2012 | (Mac) imageAsBitmapImageRepOfSize no longer rejects sizes greater than 1024×1024, but instead rescales the image.
| 3 Feb 2012 | (Win) The application as a whole is now willing to use the OpenGL 2 FBO extension for Copy/Save. However, to ensure that all users get correct basic functionality, it calls glGenerateMipmap only on OpenGL 3.3 or higher. On OpenGL 3.2 or earlier it falls back to glTexParameteri(…, GL_GENERATE_MIPMAP, …) to avoid buggy glGenerateMipmap implementations.
3.6.4 | 20 Jan 2012 | First version to require Vertex Array Objects.
3.6.3 | 20 Jan 2012 | Last version to run without Vertex Array Objects.
| 18 Jan 2012 | Disentangled Vertex Array Object (VAO) code from Vertex Buffer Object (VBO) code.
| 17 Jan 2012 | Stores tile placements on GPU as a VBO, which gets read at render time as an "instanced vertex attribute" (when available) for much faster rendering of deep hyperbolic tilings. On my PC the frame rate increased from 4 fps to 51 fps for a (2,3,7) tiling out to radius 6.5.
| 16 Dec 2011 | (Mac) Created an opaque ModelData typedef and move much more functionality into the GeometryGamesView class to reduce code duplication among different applications.
| 5 Dec 2011 | (Mac) Created a shared GeometryGamesView class to reduce code duplication among different applications.
3.6.2 | 18 Nov 2011 | (Mac) The ModelData is now packaged as an Objective-C object. The WindowController sees the ModelData and the View. The View sees the ModelData. This design goes against Apple's advice to let the Controller mediate between the Model and the View (as illustrated by the 2-way arrows in the figure at developer.apple.com/technologies/mac/cocoa.html ), but ultimately achieves much cleaner code. As an added bonus, the pointers WindowController→ModelData, WindowController→View and View→ModelData all point in a consistent direction (no cycles), so they may all be strong (retained) references. There's no longer any need for weak (non-retained) references. (Mac) The Mac OS 10.6 style fullscreen mode would switch the first responder to the WindowController, regardless of what it had been previously. Now that Mac OS 10.7 provides a far cleaner fullscreen mode (and I've eliminated the 10.6 fullscreen mode entirely), the first responder is the View, not the WindowController. The View now handles all keystroke and mouse activity, while the WindowController handles the menus.
| 18 Nov 2011 | Enlarges/reduces Euclidean tiles correctly.
3.6.1 | 28 Jul 2011 | Korean added, thanks to 박하은. (Mac) Uses OpenGL 3.2 on Mac OS 10.7. (Mac) Mac OS 10.7 fullscreen mode support. (Mac) Assorted small changes for Mac OS 10.7 compatibility.
| 23 Jun 2011 | Wrote code to generating tilings via geometry shader, but do not plan to release it until after testings on Mac OS under Open GL 3. (Under Windows it increases the frame rate of deep hyperbolic tilings by an order of magnitude, by eliminating the once-per-tile CPU-to-GPU call. But it's actually a tiny bit slower than the old code for x8 spherical tilings, where the per-vertex cost is more important than the per-tile cost. Also, there's a noticeable pause whenever it needs to recompile its shaders -- to avoid that it could precompile all possibile combinations.)
| 5 Jun 2011 | Chooses mesh refinement automatically. Default hyperbolic tiling radius increased from 4.5 to 5.5.
| 2 Jun 2011 | (Mac) Pauses animation when hidden (⌘H).
3.6 | 20 May 2011 | Public release of accumulated changes.
| April & May | Lots of small improvements and maintenance, which I got bored of recording in the revision histories. Includes improvements to support older, buggier OpenGL drivers as well as newer ones.
| 29 Mar 2011 | (Mac) Rewrote user interface, replacing old single-class based architecture with simpler and more logical AppDelegate/WindowController/View architecture. (Mac) Replaced groups of related menu command handlers with single tag-based handlers.
| 15 Mar 2011 | Replaced 256×1 ControlPanelBackground.rgba with equivalent 256×2 image. On certain systems (for example, Manual Arala Chaves' Win7 laptop) the OpenGL driver has a bug that glGenerateMipmap() fails to mark a 1-pixel high image as ready-for-use.
| 14 Mar 2011 | (Win) GeometryGames-Win32-LoadEntryPoints.c loads entry points based on OpenGL version and available extensions.
| 10 Mar 2011 | Background texture scales according to intrinsic units. Background texture rendered in 3D for spherical and Euclidean tilings.
| 10 Mar 2011 | Archimedean name maintains aspect ratio even while window does not.
| 10 Mar 2011 | Replaced cursor pushing/popping mechanism with plain setting, to avoid problem that on first click it would revert to a plain arrow.
| 9 Mar 2011 | Added full-screen mode (publicly available). Added dual-projector polarized stereo 3D, for Manuel Arala Chaves at Atractor and Jouko Koskinen at Heureka. It's not part of the public version. To activate it, uncomment #define RUN_DUAL_MONITOR_FULLSCREEN_STEREO_MAC and/or #define RUN_DUAL_MONITOR_FULLSCREEN_STEREO_WIN and recompile. Selecting "Full Screen" will still give ordinary full-screen mode on a single-monitor system, but on a dual-monitor system will give dual-projector polarized stereo 3D.
| 28 Feb 2011 | Moved SetUpOneShader() to shared code, and simplified parameter handling.
| 24 Feb 2011 | Replaced application-wide texture settings (for mipmapping, anisotropic filtering, etc.) with per-texture settings. The finer control lays the foundation for iOS versions of the software, where trilinear mipmapping and anisotropic filtering are computationally more expensive. Moved SetUpOneTexture() to shared code.
| 20 Feb 2011 | (Mac) For rendering text into OpenGL textures, replaced deprecated ATSUI functions with new Core Text functions. Replaced application-specific SetAlphaTextureFromString() with shared SetAlphaTextureFromString().
| 15 Feb 2011 | Having Copy/Save Image read the back/front buffer was a bit dicey, so Copy/Save Image now draws into an offscreen buffer instead. The new system has the flexibility to draw the image at any size, not necessarily the view size, even though there's still no user interface to set a custom size.
| 11 Feb 2011 | Extension checking moved to shared Geometry Games utilities.
| 30 Jan 2011 | New, simpler algorithm for handing window dimensions. Eliminates ResizeGLView(). Handles mouse movements correctly even when aspect ratio isn't 5:4. Control panel maintains 1:4 aspect ratio whenever the window's width is at least half its height. Removed and archived Preferences panel.
| 23 Jan 2011 | Uses shared GeometryGames-OpenGL.h. Graphics code made OpenGL ES compatible.
| 20 Jan 2011 | Removed GeoWall support (could eventually get replaced with dual-projector full-screen mode if needed). Added greyscale vs. color anaglyphic 3D.
| 12 Nov 2010 | Replaced version-based runtime choices with extension-based runtime choices.
| 10 Nov 2010 | Uses shared Geometry Games utilities.
| 7 Jul 2010 | VAO usage now controlled by extension availability instead of version number. This allows greater VAO usage, but more importantly it simplifies the code by eliminating lots of #ifdef/#else/#endif blocks.
3.5.2 | 22 Jun 2010 | Added Italian translation, thanks to Angelo Contardi.
| 4 Jun 2010 | Removed Smooth Edges from menu and preference panel. Multisample now gets used iff the program wants it and the host computer provides it.
| 3 Jun 2010 | (Mac) Minor changes: Saved NIB file as XIB file. XIB file declares main view as subclass of NSOpenGLView instead of subclass of NSView, which lets us set the pixel format in Interface Builder, and also affects what initializer get called. Removed hack from reshape method (no longer needed). Removed windowWillMiniaturize method (the hack it contained is no longer needed).
| 30 May 2010 | (Mac) Includes copy of gl3.h bundled with source code.
| 10 May 2010 | Added glBindVertexArray(0) call to PrepTriangleVAOs(). No problems had arisen without it, but nevertheless it seems safer to include that call. Added glBindBuffer(..., 0) calls at very end of PrepTriangleVAOs(). Again no problems had arisen, but it seems safer.
3.5.1 | 6 May 2010 | (Win) Corrected "Save As" function to repaint window before saving image.
3.5 | 3 May 2010 | Revised graphics code OpenGL 2.0 → OpenGL 3.0. Compiles against the forward-compatible gl3.h instead of the backward-compatible gl.h. Removed all fixed-function (OpenGL 1) graphics code.
3.4 OpenGL 1 archive | 27 Apr 2010 | Changed "Rhombitruncated Cuboctahedron" → "Truncated Cuboctahedron" "Rhombitruncated Icosidodecahedron" → "Truncated Icosidodecahedron" and similarly in other languages (excluding French, which retains the grand/petit forms).
| 26 Apr 2010 | Removed spoken polyhedron names. They really weren't so important, and they presented an obstacle to revising the polyhedron names in English, as well as an ongoing burden to people translating KaleidoTile into other languages. Removed the option to show or not show the Archimedean polyhedron names. Now they always get shown.
| 12 Jan 2010 | Moved all colors from plain (r,g,b,α) to premultiplied (αr, αg, αb, α) for rigorous transparency, eliminating all artifacts, and correct mipmap generation. Accepts premultiplied or nonpremultiplied pasted images on Mac.
| 5 Dec 2009 | Reorganized texture management.
| 19 Nov 2009 | Added side-by-side stereoscopic 3D for display on polarized lens systems like GeoWall.
| 19 Nov 2009 | Improved handling of non-square tiling panel.
| 16 Nov 2009 | Revised ResizeGLView() for greater flexibility.
| 26 Oct 2009 | (Win) Simplified loading of Open GL entry points.
3.3 | 19 Oct 2009 | Reorganized drawing code to use programmable vertex and fragment shaders (OpenGL 2.0) instead of old-style fixed function pipeline (OpenGL 1.5). New code uses generic vertex attributes for forward compatibility with OpenGL 3.2.
| 20 Sep 2009 | (Mac) Migrated NSString literals with UTF-8 to newer, simpler format.
| 17 Sep 2009 | Rewrote menu translation code for Mac OS 10.6 compatibility.
3.2.2 | 19 May 2009 | Added user-adjustable hyperbolic tiling depth.
| 16 May 2009 | Moved responsibility for requesting a display redraw from platform-dependent code to platform-independent code. Minor changes for OpenGL ES compatibility.
| 4 May 2009 | Minor maintenance on Win32 user interface
3.2.1 | 22 Apr 2009 | (Win) If KaleidoTile fails to load a post-OpenGL 1.1 function under its permanent name (e.g. "glBindBuffer"), it looks for it under its former extension name (e.g. "glBindBufferARB").
3.2 | 7 Apr 2009 | Added user-controlled scale factor for Euclidean tilings. Added data persistence ("user prefs" on Mac, "registry keys" on Windows) so KaleidoTile now remembers the multisampling ("Smooth Edges") setting from a previous session.
| 6 Apr 2009 | Replaced quadratic-time tiling algorithm with linear-time tiling algorithm. Tiles in real time, with no precomputed matrices. Enforces cutoff distance relative to current tiling position, so as the tiling moves, the boundary tiles pop in and out one at a time, not en masse.
| 14 Mar 2009 | Reorganized drawing code to use Vertex Buffer Objects instead of display lists, because displays lists are deprecated in standard OpenGL and don't exist at all in OpenGL ES. New drawing code almost doubles the frame rate for large hyperbolic tilings (e.g. from 19fps to 34fps).
| 13 Mar 2009 | Changed projection matrix to show hyperbolic tilings in Poincaré disk model rather than from the more limited inside-the-hyperboloid viewpoint. When KaleidoTile was first written, standard consumer PCs and Macs weren't fast enough to handle the Poincaré disk in real time, but now they are. Changed coordinate conventions so that KaleidoTile looks down the positive z-axis instead of the negative z-axis.
| 10 Feb 2009 | Simplified default language initialization on Mac OS X, eliminating LanguageCode.strings files.
3.1.4 | 20 Jan 2009 | Added Welsh (thanks to Uned Gyfieithu Prifysgol Bangor).
3.1.3 | 4 Nov 2008 | Suppressed needless backface calls for flat and hyperbolic tilings.
| 31 Oct 2008 | Removed depth buffer.
| 19 Oct 2008 | No longer suppresses background when Cut Along Mirror Lines is enabled.
| 17 Oct 2008 | Avoids calling ErrorMessage() when the OpenGL context is active.
3.1.2 | 8 Oct 2008 | Provides a clear explanation if the application gets separated from its supporting files.
3.1.1 | 3 Oct 2008 | Smooth Edges disabled by default, for better performance on low-end computers More efficient algorithm for pasting images into KaleidoTile on Mac OS X
3.1.0 | 8 Sep 2008 | Completely re-written user interface runs on Mac OS X as well as on Windows, for each language, a single platform-independent file contains all localized strings, the Windows version no longer needs separate .rc and .dll files for each language, the Mac OS X version needs no language-specific NIB files. Background fully user-customizable, with color, stock image, or user-provided image. Suspends continuous redraw when display is static. Added Japanese, thanks to Tatsu Takeuchi.
3.0.2 | 15 Nov 2007 | Added Portuguese (thanks to Atractor). [Note: 3.0.2 was built using old KaleidoTile code, while new code is under development.]
3.0.1 | 14 Apr 2007 | Added French (thanks to Jean-Michel Celibert). Suspends frame rate measurement while minimized. Switched to gcc compiler with CodeBlocks IDE. Minor internal changes. [Note: 3.0.1 was built using old KaleidoTile code, while new code is under development.]
3.0.0 | 18 Nov 2005 | Initial KaleidoTile 3 release. Completely re-written using OpenGL graphics. Improved user interface. Full support for current-generation 3D graphics cards.