1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
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 // -------------------------------------------------------------------------*/
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
)
29 sjme_scritchui_pencilFont font
;
30 sjme_jint cw
, ch
, area
, dx
, dy
, sx
, sy
, v
, scanLen
;
33 sjme_scritchui_pencilBitLineFunc bitline
;
36 return SJME_ERROR_NULL_ARGUMENTS
;
38 /* We need the font for rendering. */
41 return SJME_ERROR_ILLEGAL_STATE
;
43 /* Need character width. */
45 if (sjme_error_is(error
= font
->api
->pixelCharWidth(
47 return sjme_error_default(error
);
49 /* Do not draw space characters. */
50 if (c
== '\t' || c
== ' ')
52 /* Do report their length however! */
56 return SJME_ERROR_NONE
;
60 if (sjme_error_is(error
= g
->util
->applyTranslate(g
, &x
, &y
)))
61 return sjme_error_default(error
);
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. */
69 if (sjme_error_is(error
= font
->api
->metricPixelSize(
73 /** Do not bother drawing nothing. */
74 if (cw
== 0 || ch
== 0)
75 return SJME_ERROR_NONE
;
77 /* Calculate anchor point accordingly. */
79 if (sjme_error_is(error
= sjme_scritchpen_coreUtil_applyAnchor(
81 x
, y
, cw
, ch
, 0, &x
, &y
)))
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
);
92 error
= sjme_error_outOfMemory(NULL
, area
);
97 memset(bitmap
, 0, area
);
99 /* Offsets for proper glyph drawing. */
103 /* Get glyph bitmap. */
104 if (sjme_error_is(error
= font
->api
->renderBitmap(font
,
105 c
, bitmap
, 0, scanLen
,
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
)))
122 if (sjme_error_is(error
= sjme_scritchpen_core_lockRelease(g
)))
123 return sjme_error_default(error
);
129 return SJME_ERROR_NONE
;
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
;
151 return SJME_ERROR_NULL_ARGUMENTS
;
154 if (sjme_error_is(error
= sjme_scritchpen_core_lock(g
)))
155 return sjme_error_default(error
);
158 return sjme_error_notImplemented(0);
161 if (sjme_error_is(error
= sjme_scritchpen_core_lockRelease(g
)))
162 return sjme_error_default(error
);
164 return sjme_error_notImplemented(0);
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
;
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
;
197 return SJME_ERROR_ILLEGAL_STATE
;
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. */
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. */
215 if (sjme_error_is(error
= font
->api
->metricPixelBaseline(
217 goto fail_fontBaseline
;
219 /* Get sequence length for further checking. */
221 if (sjme_error_is(error
= sjme_charSeq_length(s
,
222 &seqLen
)) || seqLen
< 0)
226 if ((o
+ l
) > seqLen
)
228 error
= SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
232 /* Determine visual size of this block of text. */
234 if (sjme_error_is(error
= font
->api
->stringWidth(font
,
235 s
, o
, l
, &tw
)) || tw
< 0)
238 /* Determine anchor point of this block of text. */
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
)))
247 /* Base X is the initial starting coordinate. */
250 /* Draw each character in the string. */
251 for (at
= 0; at
< l
; at
++)
253 /* Get the next character to render. */
255 if (sjme_error_is(error
= sjme_charSeq_charAt(
259 /* Reset to start of line or next line? */
260 if (c
== '\r' || c
== '\n')
262 /* Go to next line? */
266 /* Reset to line base. */
271 /* Render character, note always at top+left anchor. */
273 if (sjme_error_is(error
= g
->api
->drawChar(g
, c
, dx
, dy
,
282 if (sjme_error_is(error
= sjme_scritchpen_core_lockRelease(g
)))
283 return sjme_error_default(error
);
286 return SJME_ERROR_NONE
;
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
;
311 g
->state
.font
= font
;
314 return SJME_ERROR_NONE
;