aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2020-04-28 18:47:10 +0200
committerMattias Andrée <maandree@kth.se>2020-04-28 18:47:10 +0200
commit9761455b328c86d8caedbf2f8ebd1bec8936e749 (patch)
tree81dd4f0982ae15a4dfe9f15ff5ce9342756f5a81
parentAdd code (untested) for applying glyphs to an image (diff)
downloadlibskrift-9761455b328c86d8caedbf2f8ebd1bec8936e749.tar.gz
libskrift-9761455b328c86d8caedbf2f8ebd1bec8936e749.tar.bz2
libskrift-9761455b328c86d8caedbf2f8ebd1bec8936e749.tar.xz
Fix drawing issues (there is still some left)
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile1
-rw-r--r--demo.c63
-rw-r--r--libskrift.h11
-rw-r--r--libskrift_apply_glyph.c48
-rw-r--r--libskrift_draw_text.c27
-rw-r--r--libskrift_merge_glyphs.c15
6 files changed, 114 insertions, 51 deletions
diff --git a/Makefile b/Makefile
index dd440d0..4c70752 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ OBJ =\
libskrift_calculate_dpi.o\
libskrift_close_font.o\
libskrift_create_context.o\
+ libskrift_draw_text.o\
libskrift_format_settings.o\
libskrift_free_context.o\
libskrift_get_grapheme_glyph.o\
diff --git a/demo.c b/demo.c
index 9157a5c..062f515 100644
--- a/demo.c
+++ b/demo.c
@@ -11,13 +11,14 @@ main(void)
{
LIBSKRIFT_FONT *font;
LIBSKRIFT_CONTEXT *ctx;
- struct libskrift_glyph *glyph;
+ struct libskrift_image image = {LIBSKRIFT_R8G8B8A8, LIBSKRIFT_HOST_SUBPIXEL, 0, 800, 600, NULL, NULL, NULL};
struct libskrift_rendering rendering = LIBSKRIFT_DEFAULT_RENDERING;
- uint16_t i, x, y;
+ struct libskrift_colour colour = LIBSKRIFT_PREMULTIPLY(1, 1, .80f, .50f, .20f);
double height;
+ size_t size, i;
rendering.smoothing = LIBSKRIFT_SUBPIXEL;
- rendering.subpixel_order = LIBSKRIFT_RGB;
+ rendering.subpixel_order = LIBSKRIFT_NONE;
rendering.flags = 0;
if (libskrift_open_font_file(&font, DEMO_FONT)) {
@@ -31,43 +32,37 @@ main(void)
}
libskrift_close_font(font);
-#if 1
- if (libskrift_get_cluster_glyph(ctx, "x̴̑", NULL, 0, 0, &glyph) < 0) {
- perror("libskrift_get_cluster_glyph");
+ size = 4;
+ size *= (size_t)image.width;
+ size *= (size_t)image.height;
+ image.image = malloc(size);
+ if (!image.image) {
+ perror("malloc");
return -1;
}
-#else
- if (libskrift_get_grapheme_glyph(ctx, 197 /* Å */, 0, 0, &glyph)) {
- perror("libskrift_get_grapheme_glyph");
- return -1;
+ for (i = 0; i < size; i += 4) {
+ ((uint8_t *)image.image)[i + 0] = 32U;
+ ((uint8_t *)image.image)[i + 1] = 48U;
+ ((uint8_t *)image.image)[i + 2] = 64U;
+ ((uint8_t *)image.image)[i + 3] = 192U;
}
-#endif
- if (rendering.smoothing == LIBSKRIFT_GREYSCALE) {
- printf("P2\n%u %u\n255\n", glyph->width, glyph->height);
- printf("# x-position: %i\n", glyph->x);
- printf("# y-position: %i\n", glyph->y);
- printf("# advance: %lf\n", glyph->advance);
- for (i = y = 0; y < glyph->height; y++) {
- for (x = 0; x < glyph->width; x++, i++)
- printf("%3u ", glyph->image[i]);
- printf("\n\n");
- }
- fflush(stdout);
- } else {
- printf("P3\n%u %u\n255\n", glyph->width, glyph->height);
- printf("# x-position: %i\n", glyph->x);
- printf("# y-position: %i\n", glyph->y);
- printf("# advance: %lf\n", glyph->advance);
- for (i = y = 0; y < glyph->height; y++) {
- for (x = 0; x < glyph->width * 3; x++, i++)
- printf("%3u ", glyph->image[i]);
- printf("\n\n");
- }
- fflush(stdout);
+ if (libskrift_draw_text(ctx, "hello world", &colour, 0, 300, &image) < 0) {
+ perror("libskrift_draw_text");
+ return -1;
}
- free(glyph);
+ printf("P7\n");
+ printf("WIDTH %u\n", image.width);
+ printf("HEIGHT %u\n", image.height);
+ printf("DEPTH 4\n");
+ printf("MAXVAL 255\n");
+ printf("TUPLTYPE RGB_ALPHA\n");
+ printf("ENDHDR\n");
+ fwrite(image.image, 1, size, stdout);
+ fflush(stdout);
+
+ free(image.image);
libskrift_free_context(ctx);
return 0;
}
diff --git a/libskrift.h b/libskrift.h
index 93adb79..aeeaad2 100644
--- a/libskrift.h
+++ b/libskrift.h
@@ -184,6 +184,13 @@ struct libskrift_colour {
#define LIBSKRIFT_NO_SAVED_GRAPHEME {0, 0}
+#define LIBSKRIFT_PREMULTIPLY(OPACITY, ALPHA, RED, GREEN, BLUE)\
+ {(OPACITY),\
+ (ALPHA) * (OPACITY),\
+ (RED) * (ALPHA) * (OPACITY),\
+ (GREEN) * (ALPHA) * (OPACITY),\
+ (BLUE) * (ALPHA) * (OPACITY)}
+
_LIBSKRIFT_GCC_ONLY(__attribute__((__const__, __warn_unused_result__)))
inline double
@@ -253,6 +260,10 @@ _LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 6))))
int libskrift_apply_glyph(LIBSKRIFT_CONTEXT *, const struct libskrift_glyph *, const struct libskrift_colour *,
int16_t, int16_t, struct libskrift_image *);
+_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 6))))
+int libskrift_draw_text(LIBSKRIFT_CONTEXT *, const char *, const struct libskrift_colour *,
+ int16_t, int16_t, struct libskrift_image *);
+
_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__)))
void libskrift_srgb_preprocess(struct libskrift_image *, size_t, size_t, size_t, size_t);
diff --git a/libskrift_apply_glyph.c b/libskrift_apply_glyph.c
index 05770ce..85e4bd2 100644
--- a/libskrift_apply_glyph.c
+++ b/libskrift_apply_glyph.c
@@ -45,10 +45,10 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp
size_t img_linesize, gly_linesize, i, gly_psize, usize;
size_t ri, gi, bi, rj, gj, bj;
uint16_t x1, y1, x2, y2;
- int16_t sx2, sy2;
+ int16_t sx1, sy1, sx2, sy2;
uint8_t high;
uint8_t *img, *img_start = image->image;
- const uint8_t *gly = glyph->image;
+ const uint8_t *gly = glyph->image, *gly_start;
const uint16_t u16 = 0x0102;
const uint32_t u32 = 0x01020304L;
const uint64_t u64 = 0x0102030405060708LL;
@@ -69,30 +69,42 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp
return -1;
}
- /* Drawing area on image */
- sx2 = (int16_t)(x + (int16_t)glyph->width);
- sy2 = (int16_t)(y + (int16_t)glyph->height);
- x1 = x < 0 ? 0 : (uint16_t)x;
- y1 = y < 0 ? 0 : (uint16_t)y;
- if (sx2 <= 0 || sy2 <= 0 || x1 >= image->width || y1 >= image->height)
+ /* Top left corner of glyph on image */
+ sx1 = (int16_t)(x + glyph->x);
+ sy1 = (int16_t)(y + glyph->y);
+
+ /* Post-bottom right corner of glyph on image */
+ sx2 = (int16_t)(sx1 + (int16_t)glyph->width);
+ sy2 = (int16_t)(sy1 + (int16_t)glyph->height);
+ if (sx2 <= 0 || sy2 <= 0)
+ return 0;
+
+ /* First pixel in image to draw on */
+ x1 = sx1 < 0 ? 0 : (uint16_t)sx1;
+ y1 = sy1 < 0 ? 0 : (uint16_t)sy1;
+ if (x1 >= image->width || y1 >= image->height)
return 0;
+
+ /* Post-last pixel in image to draw on */
+ sx2 = (int16_t)(sx1 + (int16_t)glyph->width);
+ sy2 = (int16_t)(sy1 + (int16_t)glyph->height);
x2 = (uint16_t)sx2 < image->width ? (uint16_t)sx2 : image->width;
y2 = (uint16_t)sy2 < image->height ? (uint16_t)sy2 : image->height;
- sx2 = (int16_t)x2;
- sy2 = (int16_t)y2;
- /* Drawing area on glyph */
- startc = x <= 0 ? 0 : (size_t)-x;
- startr = y <= 0 ? 0 : (size_t)-y;
- endc = x2 < image->width ? glyph->width : (uint16_t)(sx2 - x);
- endr = y2 < image->height ? glyph->height : (uint16_t)(sy2 - y);
+ /* First pixel in glyph to draw */
+ startc = (uint16_t)((int16_t)x1 - sx1);
+ startr = (uint16_t)((int16_t)y1 - sy1);
+
+ /* Post-last pixel in glyph to draw*/
+ endc = (uint16_t)((int16_t)x2 - sx1);
+ endr = (uint16_t)((int16_t)y2 - sy1);
img_linesize = (size_t)image->width * psize;
img_start += (size_t)y1 * img_linesize;
img_start += (size_t)x1 * psize;
- gly_psize = ctx->rendering.smoothing ? 3 : 1;
- gly_linesize = (size_t)image->width * gly_psize;
+ gly_psize = (ctx->rendering.smoothing == LIBSKRIFT_SUBPIXEL) ? 3 : 1;
+ gly_linesize = (size_t)glyph->width * gly_psize;
gly += startr * gly_linesize;
usize = image->endian >= LIBSKRIFT_HOST_SUBPIXEL ? settings.spsize : psize;
@@ -180,6 +192,7 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp
rj = (size_t)settings.rpos * settings.spsize;
gj = (size_t)settings.gpos * settings.spsize;
bj = (size_t)settings.bpos * settings.spsize;
+ gly_start = gly;
for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) {
for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) {
img[i + rj] ^= gly[c + ri];
@@ -191,6 +204,7 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp
ri = rj + j;
gi = gj + j;
bi = bj + j;
+ gly = gly_start;
for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) {
for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) {
img[i + ri] = img[i + rj];
diff --git a/libskrift_draw_text.c b/libskrift_draw_text.c
new file mode 100644
index 0000000..8f46df4
--- /dev/null
+++ b/libskrift_draw_text.c
@@ -0,0 +1,27 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+int
+libskrift_draw_text(LIBSKRIFT_CONTEXT *ctx, const char *text, const struct libskrift_colour *colour,
+ int16_t x, int16_t y, struct libskrift_image *image)
+{
+ struct libskrift_saved_grapheme saved = LIBSKRIFT_NO_SAVED_GRAPHEME;
+ struct libskrift_glyph *glyph;
+ double xpos = 0;
+ ssize_t len;
+ int r;
+
+ for (; *text; text += len) {
+ len = libskrift_get_cluster_glyph(ctx, text, &saved, xpos, 0, &glyph);
+ if (len < 0)
+ return -1;
+
+ r = libskrift_apply_glyph(ctx, glyph, colour, x, y, image);
+ xpos += glyph->advance;
+ free(glyph);
+ if (r)
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libskrift_merge_glyphs.c b/libskrift_merge_glyphs.c
index 6c62fc8..4df6f7a 100644
--- a/libskrift_merge_glyphs.c
+++ b/libskrift_merge_glyphs.c
@@ -10,9 +10,24 @@ libskrift_merge_glyphs(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *gly
int16_t x1a, x1b, x2a, x2b, y1a, y1b, y2a, y2b, x1, x2, y1, y2;
size_t width, height, r, c, size, psize;
size_t src_off, dest_off, src_linesize, dest_linesize;
+ const struct libskrift_glyph *t;
psize = ctx->rendering.smoothing ? 3 : 1;
+ if (!(glyph1->width | glyph1->height)) {
+ t = glyph1;
+ glyph1 = glyph2;
+ glyph2 = t;
+ }
+ if (!(glyph2->width | glyph2->height)) {
+ size = offsetof(struct libskrift_glyph, image) + glyph1->size;
+ *glyphp = calloc(1, size);
+ if (!*glyphp)
+ return -1;
+ memcpy(*glyphp, glyph1, size);
+ return 0;
+ }
+
x1a = glyph1->x;
x1b = glyph2->x;
y1a = glyph1->y;