aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGemini Lasswell2017-10-16 08:30:51 -0700
committerGemini Lasswell2017-10-24 09:02:49 -0700
commitcb73c70180f57f3fb99fae3aaefbacf0a61cea3f (patch)
tree67dab0331e0b70c3176ca5f536f35b0bd3591eff
parent4ec0d2dc6f149c4c14833793f20e1e54270b85f2 (diff)
downloademacs-cb73c70180f57f3fb99fae3aaefbacf0a61cea3f.tar.gz
emacs-cb73c70180f57f3fb99fae3aaefbacf0a61cea3f.zip
Make Snake, Tetris and Pong adjust to display DPI
Replace gamegrid's constant 16x16 glyph with a generated one based on display dimensions (bug#24658). * lisp/play/gamegrid.el (gamegrid-glyph-height-mm): New variable. (gamegrid-glyph-height): Deleted. (gamegrid-xpm, gamegrid-xbm): Constants replaced with functions. (gamegrid-colorize-glyph): Use new functions instead of constants. (gamegrid-calculate-glyph-size, gamegrid-insert-xbm-bits): New functions.
-rw-r--r--etc/NEWS7
-rw-r--r--lisp/play/gamegrid.el178
2 files changed, 150 insertions, 35 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 5c6c0b7f2a0..ec52460f776 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -82,6 +82,13 @@ globally or for individual definitions.
82the XTerm window title. This feature is experimental and is disabled 82the XTerm window title. This feature is experimental and is disabled
83by default. 83by default.
84 84
85** Gamegrid
86
87---
88*** Gamegrid now determines its default glyph size based on display
89dimensions, instead of always using 16 pixels. As a result, Tetris,
90Snake and Pong are more playable on HiDPI displays.
91
85 92
86* New Modes and Packages in Emacs 27.1 93* New Modes and Packages in Emacs 27.1
87 94
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index 6214e07506d..641ef7f2462 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -86,49 +86,157 @@ directory will be used.")
86(defvar gamegrid-mono-x-face nil) 86(defvar gamegrid-mono-x-face nil)
87(defvar gamegrid-mono-tty-face nil) 87(defvar gamegrid-mono-tty-face nil)
88 88
89;; ;;;;;;;;;;;;; constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 89(defvar gamegrid-glyph-height-mm 7.0
90 90 "Desired glyph height in mm.")
91(defconst gamegrid-glyph-height 16) 91
92 92;; ;;;;;;;;;;;;; glyph generation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
93(defconst gamegrid-xpm "\ 93
94(defun gamegrid-calculate-glyph-size ()
95 "Calculate appropriate glyph size in pixels based on display resolution.
96Return a multiple of 8 no less than 16."
97 (if (and (display-pixel-height) (display-mm-height))
98 (let* ((y-pitch (/ (display-pixel-height) (float (display-mm-height))))
99 (pixels (* y-pitch gamegrid-glyph-height-mm))
100 (rounded (* (floor (/ (+ pixels 4) 8)) 8)))
101 (max 16 rounded))
102 16))
103
104;; Example of glyph in XPM format:
105;;
106;; /* XPM */
107;; static char *noname[] = {
108;; /* width height ncolors chars_per_pixel */
109;; \"16 16 3 1\",
110;; /* colors */
111;; \"+ s col1\",
112;; \". s col2\",
113;; \"- s col3\",
114;; /* pixels */
115;; \"---------------+\",
116;; \"--------------++\",
117;; \"--............++\",
118;; \"--............++\",
119;; \"--............++\",
120;; \"--............++\",
121;; \"--............++\",
122;; \"--............++\",
123;; \"--............++\",
124;; \"--............++\",
125;; \"--............++\",
126;; \"--............++\",
127;; \"--............++\",
128;; \"--............++\",
129;; \"-+++++++++++++++\",
130;; \"++++++++++++++++\"
131;; };
132
133(defun gamegrid-xpm ()
134 "Generate the XPM format image used for each square."
135 (let* ((glyph-pixel-count (gamegrid-calculate-glyph-size))
136 (border-pixel-count (/ glyph-pixel-count 8))
137 (center-pixel-count (- glyph-pixel-count (* border-pixel-count 2))))
138 (with-temp-buffer
139 (insert (format "\
94/* XPM */ 140/* XPM */
95static char *noname[] = { 141static char *noname[] = {
96/* width height ncolors chars_per_pixel */ 142/* width height ncolors chars_per_pixel */
97\"16 16 3 1\", 143\"%s %s 3 1\",
98/* colors */ 144/* colors */
99\"+ s col1\", 145\"+ s col1\",
100\". s col2\", 146\". s col2\",
101\"- s col3\", 147\"- s col3\",
102/* pixels */ 148/* pixels */
103\"---------------+\", 149" glyph-pixel-count glyph-pixel-count))
104\"--------------++\", 150
105\"--............++\", 151 (dotimes (row border-pixel-count)
106\"--............++\", 152 (let ((edge-pixel-count (+ row 1)))
107\"--............++\", 153 (insert "\"")
108\"--............++\", 154 (dotimes (_ (- glyph-pixel-count edge-pixel-count)) (insert "-"))
109\"--............++\", 155 (dotimes (_ edge-pixel-count) (insert "+"))
110\"--............++\", 156 (insert "\",\n")))
111\"--............++\", 157
112\"--............++\", 158 (let ((middle (format "\"%s%s%s\",\n"
113\"--............++\", 159 (make-string border-pixel-count ?-)
114\"--............++\", 160 (make-string center-pixel-count ?.)
115\"--............++\", 161 (make-string border-pixel-count ?+))))
116\"--............++\", 162 (dotimes (_ center-pixel-count) (insert middle)))
117\"-+++++++++++++++\", 163
118\"++++++++++++++++\" 164 (dotimes (row border-pixel-count)
119}; 165 (let ((edge-pixel-count (- border-pixel-count row 1)))
120" 166 (insert "\"")
121 "XPM format image used for each square") 167 (dotimes (_ edge-pixel-count) (insert "-"))
122 168 (dotimes (_ (- glyph-pixel-count edge-pixel-count)) (insert "+"))
123(defvar gamegrid-xbm "\ 169 (insert "\"")
170 (if (/= row (1- border-pixel-count))
171 (insert ",\n")
172 (insert "\n};\n"))))
173 (buffer-string))))
174
175;; Example of glyph in XBM format:
176;;
177;; /* gamegrid XBM */
178;; #define gamegrid_width 16
179;; #define gamegrid_height 16
180;; static unsigned char gamegrid_bits[] = {
181;; 0xff, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a,
182;; 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a,
183;; 0x57, 0x15, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00 };
184
185(defun gamegrid-xbm ()
186 "Generate XBM format image used for each square."
187 (let* ((glyph-pixel-count (gamegrid-calculate-glyph-size))
188 (border-pixel-count (1- (/ glyph-pixel-count 4)))
189 (center-pixel-count (- glyph-pixel-count (* 2 border-pixel-count))))
190 (with-temp-buffer
191 (insert (format "\
124/* gamegrid XBM */ 192/* gamegrid XBM */
125#define gamegrid_width 16 193#define gamegrid_width %s
126#define gamegrid_height 16 194#define gamegrid_height %s
127static unsigned char gamegrid_bits[] = { 195static unsigned char gamegrid_bits[] = {
128 0xff, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a, 196" glyph-pixel-count glyph-pixel-count))
129 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a, 197 (dotimes (row border-pixel-count)
130 0x57, 0x15, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00 };" 198 (gamegrid-insert-xbm-bits
131 "XBM format image used for each square.") 199 (concat (make-string (- glyph-pixel-count row) ?1)
200 (make-string row ?0)))
201 (insert ", \n"))
202
203 (let* ((left-border (make-string border-pixel-count ?1))
204 (right-border (make-string border-pixel-count ?0))
205 (even-line (apply 'concat
206 (append (list left-border)
207 (make-list (/ center-pixel-count 2) "10")
208 (list right-border))))
209 (odd-line (apply 'concat
210 (append (list left-border)
211 (make-list (/ center-pixel-count 2) "01")
212 (list right-border)))))
213 (dotimes (row center-pixel-count)
214 (gamegrid-insert-xbm-bits (if (eq (logand row 1) 1) odd-line even-line))
215 (insert ", \n")))
216
217 (dotimes (row border-pixel-count)
218 (let ((edge-pixel-count (- border-pixel-count row)))
219 (gamegrid-insert-xbm-bits
220 (concat (make-string edge-pixel-count ?1)
221 (make-string (- glyph-pixel-count edge-pixel-count) ?0))))
222 (if (/= row (1- border-pixel-count))
223 (insert ", \n")
224 (insert " };\n")))
225 (buffer-string))))
226
227(defun gamegrid-insert-xbm-bits (str)
228 "Convert binary to hex and insert in current buffer.
229STR should be a string composed of 1s and 0s and be a multiple of
2308 in length. Divide it into 8 bit bytes, reverse the order of
231each, convert them to hex and insert them in comma separated C
232format."
233 (let ((byte-count (/ (length str) 8)))
234 (dotimes (i byte-count)
235 (let* ((byte (reverse (substring str (* i 8) (+ (* i 8) 8))))
236 (value (string-to-number byte 2)))
237 (insert (format "0x%02x" value))
238 (unless (= i (1- byte-count))
239 (insert ", "))))))
132 240
133;; ;;;;;;;;;;;;;;;; miscellaneous functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 241;; ;;;;;;;;;;;;;;;; miscellaneous functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
134 242
@@ -228,13 +336,13 @@ static unsigned char gamegrid_bits[] = {
228 gamegrid-mono-tty-face)))) 336 gamegrid-mono-tty-face))))
229 337
230(defun gamegrid-colorize-glyph (color) 338(defun gamegrid-colorize-glyph (color)
231 (find-image `((:type xpm :data ,gamegrid-xpm 339 (find-image `((:type xpm :data ,(gamegrid-xpm)
232 :ascent center 340 :ascent center
233 :color-symbols 341 :color-symbols
234 (("col1" . ,(gamegrid-color color 0.6)) 342 (("col1" . ,(gamegrid-color color 0.6))
235 ("col2" . ,(gamegrid-color color 0.8)) 343 ("col2" . ,(gamegrid-color color 0.8))
236 ("col3" . ,(gamegrid-color color 1.0)))) 344 ("col3" . ,(gamegrid-color color 1.0))))
237 (:type xbm :data ,gamegrid-xbm 345 (:type xbm :data ,(gamegrid-xbm)
238 :ascent center 346 :ascent center
239 :foreground ,(gamegrid-color color 1.0) 347 :foreground ,(gamegrid-color color 1.0)
240 :background ,(gamegrid-color color 0.5))))) 348 :background ,(gamegrid-color color 0.5)))))