Indentations break the feed.
[SquirrelJME.git] / nanocoat / lib / scritchui / scritchPencilRasterText.c
blob818a199fd0d8f4d61bd4d1f97c04d33ac9a780c7
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/util.h"
13 #include "lib/scritchui/scritchui.h"
14 #include "lib/scritchui/scritchuiPencil.h"
15 #include "lib/scritchui/scritchuiTypes.h"
16 #include "lib/scritchui/core/coreRaster.h"
17 #include "sjme/debug.h"
18 #include "sjme/fixed.h"
20 sjme_errorCode sjme_scritchpen_core_drawChar(
21 sjme_attrInNotNull sjme_scritchui_pencil g,
22 sjme_attrInPositive sjme_jint c,
23 sjme_attrInValue sjme_jint x,
24 sjme_attrInValue sjme_jint y,
25 sjme_attrInValue sjme_jint anchor,
26 sjme_attrOutNullable sjme_jint* outCw)
28 sjme_errorCode error;
29 sjme_scritchui_pencilFont font;
30 sjme_jint cw, ch, area, dx, dy, sx, sy, v, scanLen;
31 sjme_jint offX, offY;
32 sjme_jubyte* bitmap;
33 sjme_scritchui_pencilBitLineFunc bitline;
35 if (g == NULL)
36 return SJME_ERROR_NULL_ARGUMENTS;
38 /* We need the font for rendering. */
39 font = g->state.font;
40 if (font == NULL)
41 return SJME_ERROR_ILLEGAL_STATE;
43 /* Need character width. */
44 cw = 0;
45 if (sjme_error_is(error = font->api->pixelCharWidth(
46 font, c, &cw)))
47 return sjme_error_default(error);
49 /* Do not draw space characters. */
50 if (c == '\t' || c == ' ')
52 /* Do report their length however! */
53 if (outCw != NULL)
54 *outCw = cw;
56 return SJME_ERROR_NONE;
59 /* Translate. */
60 if (sjme_error_is(error = g->util->applyTranslate(g, &x, &y)))
61 return sjme_error_default(error);
63 /* Need to lock? */
64 if (sjme_error_is(error = sjme_scritchpen_core_lock(g)))
65 return sjme_error_default(error);
67 /* And the pixel height, since this is a bitmap font. */
68 ch = 0;
69 if (sjme_error_is(error = font->api->metricPixelSize(
70 font, &ch)))
71 goto fail_any;
73 /** Do not bother drawing nothing. */
74 if (cw == 0 || ch == 0)
75 return SJME_ERROR_NONE;
77 /* Calculate anchor point accordingly. */
78 if (anchor != 0)
79 if (sjme_error_is(error = sjme_scritchpen_coreUtil_applyAnchor(
80 anchor,
81 x, y, cw, ch, 0, &x, &y)))
82 goto fail_any;
84 /* Determine scanline length for each bitmap row. */
85 scanLen = sjme_scritchui_pencilFontScanLen(cw);
87 /* Allocate bitmap. */
88 area = sizeof(*bitmap) * (scanLen * ch);
89 bitmap = sjme_alloca(area);
90 if (bitmap == NULL)
92 error = sjme_error_outOfMemory(NULL, area);
93 goto fail_any;
96 /* Initialize. */
97 memset(bitmap, 0, area);
99 /* Offsets for proper glyph drawing. */
100 offX = 0;
101 offY = 0;
103 /* Get glyph bitmap. */
104 if (sjme_error_is(error = font->api->renderBitmap(font,
105 c, bitmap, 0, scanLen,
106 ch, &offX, &offY)))
107 goto fail_any;
109 /* Draw bit-lines for the glyphs. */
110 for (sy = 0, dy = y + offY, v = 0; sy < ch; sy++, dy++)
111 for (sx = 0, dx = x + offX; sx < scanLen; sx++, dx += 8, v++)
113 /* Which bitline to use? */
114 bitline = sjme_scritchui_pencilBitLines[bitmap[v]];
116 /* Render the bitline. */
117 if (sjme_error_is(error = bitline(g, dx, dy)))
118 goto fail_any;
121 /* Release lock. */
122 if (sjme_error_is(error = sjme_scritchpen_core_lockRelease(g)))
123 return sjme_error_default(error);
125 /* Success! */
126 if (outCw != NULL)
127 *outCw = cw;
129 return SJME_ERROR_NONE;
131 fail_any:
132 /* Need to release the lock? */
133 if (sjme_error_is(sjme_scritchpen_core_lockRelease(g)))
134 return sjme_error_default(error);
136 return sjme_error_default(error);
139 sjme_errorCode sjme_scritchpen_core_drawChars(
140 sjme_attrInNotNull sjme_scritchui_pencil g,
141 sjme_attrInNotNull sjme_jchar* s,
142 sjme_attrInPositive sjme_jint o,
143 sjme_attrInPositive sjme_jint l,
144 sjme_attrInValue sjme_jint x,
145 sjme_attrInValue sjme_jint y,
146 sjme_attrInValue sjme_jint anchor)
148 sjme_errorCode error;
150 if (g == NULL)
151 return SJME_ERROR_NULL_ARGUMENTS;
153 /* Need to lock? */
154 if (sjme_error_is(error = sjme_scritchpen_core_lock(g)))
155 return sjme_error_default(error);
157 sjme_todo("Impl?");
158 return sjme_error_notImplemented(0);
160 /* Release lock. */
161 if (sjme_error_is(error = sjme_scritchpen_core_lockRelease(g)))
162 return sjme_error_default(error);
164 return sjme_error_notImplemented(0);
166 fail_any:
167 /* Need to release the lock? */
168 if (sjme_error_is(sjme_scritchpen_core_lockRelease(g)))
169 return sjme_error_default(error);
171 return sjme_error_default(error);
174 sjme_errorCode sjme_scritchpen_core_drawSubstring(
175 sjme_attrInNotNull sjme_scritchui_pencil g,
176 sjme_attrInNotNull const sjme_charSeq* s,
177 sjme_attrInPositive sjme_jint o,
178 sjme_attrInPositive sjme_jint l,
179 sjme_attrInValue sjme_jint x,
180 sjme_attrInValue sjme_jint y,
181 sjme_attrInValue sjme_jint anchor)
183 sjme_errorCode error;
184 sjme_jint seqLen, at, dx, dy, bx, lineHeight, tw, cw, baseline;
185 sjme_jchar c;
186 sjme_scritchui_pencilFont font;
188 if (g == NULL || s == NULL)
189 return SJME_ERROR_NULL_ARGUMENTS;
191 if (o < 0 || l < 0 || (o + l) < 0)
192 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
194 /* We need the font for rendering. */
195 font = g->state.font;
196 if (font == NULL)
197 return SJME_ERROR_ILLEGAL_STATE;
199 /* Lock. */
200 if (sjme_error_is(error = sjme_scritchpen_core_lock(g)))
201 return sjme_error_default(error);
203 /* Need to get the height of a line. */
204 lineHeight = -1;
205 if (sjme_error_is(error = font->api->metricPixelHeight(font,
206 &lineHeight)) || lineHeight < 0)
208 error = sjme_error_defaultOr(error,
209 SJME_ERROR_FONT_NEGATIVE_HEIGHT);
210 goto fail_fontHeight;
213 /* Need the font baseline. */
214 baseline = 0;
215 if (sjme_error_is(error = font->api->metricPixelBaseline(
216 font, &baseline)))
217 goto fail_fontBaseline;
219 /* Get sequence length for further checking. */
220 seqLen = -1;
221 if (sjme_error_is(error = sjme_charSeq_length(s,
222 &seqLen)) || seqLen < 0)
223 goto fail_seqLen;
225 /* Out of bounds? */
226 if ((o + l) > seqLen)
228 error = SJME_ERROR_INDEX_OUT_OF_BOUNDS;
229 goto fail_seqBounds;
232 /* Determine visual size of this block of text. */
233 tw = -1;
234 if (sjme_error_is(error = font->api->stringWidth(font,
235 s, o, l, &tw)) || tw < 0)
236 goto fail_blockDim;
238 /* Determine anchor point of this block of text. */
239 dx = x;
240 dy = y;
241 if (anchor != 0 && sjme_error_is(error =
242 sjme_scritchpen_coreUtil_applyAnchor(
243 anchor & SJME_SCRITCHUI_ANCHOR_TEXT_MASK, x, y,
244 tw, lineHeight, baseline, &dx, &dy)))
245 goto fail_anchor;
247 /* Base X is the initial starting coordinate. */
248 bx = dx;
250 /* Draw each character in the string. */
251 for (at = 0; at < l; at++)
253 /* Get the next character to render. */
254 c = 0;
255 if (sjme_error_is(error = sjme_charSeq_charAt(
256 s, o + at, &c)))
257 goto fail_charAt;
259 /* Reset to start of line or next line? */
260 if (c == '\r' || c == '\n')
262 /* Go to next line? */
263 if (c == '\n')
264 dy += lineHeight;
266 /* Reset to line base. */
267 dx = bx;
268 continue;
271 /* Render character, note always at top+left anchor. */
272 cw = 0;
273 if (sjme_error_is(error = g->api->drawChar(g, c, dx, dy,
274 0, &cw)))
275 goto fail_drawChar;
277 /* Move over. */
278 dx += cw;
281 /* Release lock. */
282 if (sjme_error_is(error = sjme_scritchpen_core_lockRelease(g)))
283 return sjme_error_default(error);
285 /* Success! */
286 return SJME_ERROR_NONE;
288 fail_drawChar:
289 fail_charAt:
290 fail_anchor:
291 fail_blockDim:
292 fail_seqBounds:
293 fail_seqLen:
294 fail_fontBaseline:
295 fail_fontHeight:
296 /* Need to release the lock? */
297 if (sjme_error_is(sjme_scritchpen_core_lockRelease(g)))
298 return sjme_error_default(error);
300 return sjme_error_default(error);
303 sjme_errorCode sjme_scritchpen_core_setFont(
304 sjme_attrInNotNull sjme_scritchui_pencil g,
305 sjme_attrInNotNull sjme_scritchui_pencilFont font)
307 if (g == NULL || font == NULL)
308 return SJME_ERROR_NULL_ARGUMENTS;
310 /* Set font used. */
311 g->state.font = font;
313 /* Success! */
314 return SJME_ERROR_NONE;