=head1 SYNOPSIS
- int bbox[6];
+ i_img_dim bbox[6];
if (i_wf_bbox(facename, size, text, text_len, bbox)) {
// we have the bbox
}
static void set_logfont(const char *face, int size, LOGFONT *lf);
-static LPVOID render_text(const char *face, int size, const char *text, int length, int aa,
- HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, int *bbox, int utf8);
+static unsigned char *render_text(const char *face, int size, const char *text, size_t length, int aa,
+ SIZE *psz, TEXTMETRIC *tm, size_t *bytes_per_line, i_img_dim *bbox, int utf8);
static LPWSTR utf8_to_wide_string(char const *text, int text_len, int *wide_chars);
+static LPWSTR latin1_to_wide_string(char const *text, int text_len, int *wide_chars);
/*
=item i_wf_bbox(face, size, text, length, bbox, utf8)
=cut
*/
-int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbox,
- int utf8) {
+int i_wf_bbox(const char *face, i_img_dim size, const char *text, size_t length,
+ i_img_dim *bbox, int utf8) {
LOGFONT lf;
HFONT font, oldFont;
HDC dc;
int got_first_ch = 0;
unsigned long first_ch, last_ch;
+ i_clear_error();
+
mm_log((1, "i_wf_bbox(face %s, size %d, text %p, length %d, bbox %p, utf8 %d)\n", face, size, text, length, bbox, utf8));
set_logfont(face, size, &lf);
ReleaseDC(NULL, dc);
DeleteObject(font);
- mm_log((1, " bbox=> negw=%d glob_desc=%d pos_wid=%d glob_asc=%d desc=%d asc=%d adv_width=%d rightb=%d\n", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], bbox[7]));
+ mm_log((1, " bbox=> negw=%" i_DF " glob_desc=%" i_DF " pos_wid=%" i_DF
+ " glob_asc=%" i_DF " desc=%" i_DF " asc=%" i_DF " adv_width=%" i_DF
+ " rightb=%" i_DF "\n", i_DFc(bbox[0]), i_DFc(bbox[1]), i_DFc(bbox[2]),
+ i_DFc(bbox[3]), i_DFc(bbox[4]), i_DFc(bbox[5]), i_DFc(bbox[6]),
+ i_DFc(bbox[7])));
return BBOX_RIGHT_BEARING + 1;
}
*/
int
-i_wf_text(const char *face, i_img *im, int tx, int ty, const i_color *cl, int size,
- const char *text, int len, int align, int aa, int utf8) {
+i_wf_text(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, const i_color *cl, i_img_dim size,
+ const char *text, size_t len, int align, int aa, int utf8) {
unsigned char *bits;
- HBITMAP bm;
SIZE sz;
- int line_width;
- int x, y;
+ size_t line_width;
+ i_img_dim x, y;
int ch;
TEXTMETRIC tm;
int top;
- int bbox[BOUNDING_BOX_COUNT];
+ i_img_dim bbox[BOUNDING_BOX_COUNT];
+ i_render *r;
+ unsigned char *outp;
+
+ i_clear_error();
- mm_log((1, "i_wf_text(face %s, im %p, tx %d, ty %d, cl %p, size %d, text %p, length %d, align %d, aa %d, utf8 %d)\n", face, im, tx, ty, cl, size, text, len, align, aa, aa, utf8));
+ mm_log((1, "i_wf_text(face %s, im %p, tx %" i_DF ", ty %" i_DF ", cl %p, size %" i_DF ", text %p, length %lu, align %d, aa %d, utf8 %d)\n", face, im, i_DFcp(tx, ty), cl, i_DFc(size), text, (unsigned long)len, align, aa, aa, utf8));
if (!i_wf_bbox(face, size, text, len, bbox, utf8))
return 0;
- bits = render_text(face, size, text, len, aa, &bm, &sz, &tm, bbox, utf8);
+ bits = render_text(face, size, text, len, aa, &sz, &tm, &line_width, bbox, utf8);
if (!bits)
return 0;
-
+
tx += bbox[BBOX_NEG_WIDTH];
- line_width = sz.cx * 3;
- line_width = (line_width + 3) / 4 * 4;
top = ty;
if (align) {
top -= tm.tmAscent;
top -= tm.tmAscent - bbox[BBOX_ASCENT];
}
+ r = i_render_new(im, sz.cx);
+ outp = bits;
for (y = 0; y < sz.cy; ++y) {
- for (x = 0; x < sz.cx; ++x) {
- i_color pel;
- int scale = bits[3 * x];
- i_gpix(im, tx+x, top+sz.cy-y-1, &pel);
- for (ch = 0; ch < im->channels; ++ch) {
- pel.channel[ch] =
- ((255-scale) * pel.channel[ch] + scale*cl->channel[ch]) / 255;
- }
- i_ppix(im, tx+x, top+sz.cy-y-1, &pel);
- }
- bits += line_width;
+ i_render_color(r, tx, top + sz.cy - y - 1, sz.cx, outp, cl);
+ outp += line_width;
}
- DeleteObject(bm);
+ i_render_delete(r);
+ myfree(bits);
return 1;
}
*/
int
-i_wf_cp(const char *face, i_img *im, int tx, int ty, int channel, int size,
- const char *text, int len, int align, int aa, int utf8) {
+i_wf_cp(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, int channel, i_img_dim size,
+ const char *text, size_t len, int align, int aa, int utf8) {
unsigned char *bits;
- HBITMAP bm;
SIZE sz;
- int line_width;
- int x, y;
+ size_t line_width;
+ i_img_dim x, y;
TEXTMETRIC tm;
- int top;
- int bbox[BOUNDING_BOX_COUNT];
+ i_img_dim top;
+ i_img_dim bbox[BOUNDING_BOX_COUNT];
+ unsigned char *outp;
- mm_log((1, "i_wf_cp(face %s, im %p, tx %d, ty %d, channel %d, size %d, text %p, length %d, align %d, aa %d, utf8 %d)\n", face, im, tx, ty, channel, size, text, len, align, aa, aa, utf8));
+ i_clear_error();
+
+ mm_log((1, "i_wf_cp(face %s, im %p, tx %" i_DF ", ty %" i_DF ", channel %d, size %" i_DF ", text %p, length %lu, align %d, aa %d, utf8 %d)\n", face, im, i_DFcp(tx, ty), channel, i_DFc(size), text, (unsigned long)len, align, aa, aa, utf8));
if (!i_wf_bbox(face, size, text, len, bbox, utf8))
return 0;
- bits = render_text(face, size, text, len, aa, &bm, &sz, &tm, bbox, utf8);
+ bits = render_text(face, size, text, len, aa, &sz, &tm, &line_width, bbox, utf8);
if (!bits)
return 0;
- line_width = sz.cx * 3;
- line_width = (line_width + 3) / 4 * 4;
top = ty;
if (align) {
top -= tm.tmAscent;
top -= tm.tmAscent - bbox[BBOX_ASCENT];
}
+ outp = bits;
for (y = 0; y < sz.cy; ++y) {
for (x = 0; x < sz.cx; ++x) {
i_color pel;
- int scale = bits[3 * x];
+ int scale = outp[x];
i_gpix(im, tx+x, top+sz.cy-y-1, &pel);
pel.channel[channel] = scale;
i_ppix(im, tx+x, top+sz.cy-y-1, &pel);
}
- bits += line_width;
+ outp += line_width;
}
- DeleteObject(bm);
+ myfree(bits);
return 1;
}
i_wf_addfont(char const *filename) {
i_clear_error();
+ mm_log((1, "i_wf_addfont(%s)\n", filename));
if (!gdi_dll) {
gdi_dll = GetModuleHandle("GDI32");
if (gdi_dll) {
AddFontResourceExAp = (AddFontResourceExA_t)GetProcAddress(gdi_dll, "AddFontResourceExA");
RemoveFontResourceExAp = (RemoveFontResourceExA_t)GetProcAddress(gdi_dll, "RemoveFontResourceExA");
+ mm_log((1, "i_wf_addfont: AddFontResourceExA %p RemoveFontResourceExA %p\n",
+ AddFontResourceExAp, RemoveFontResourceExAp));
}
}
- if (AddFontResourceExAp && RemoveFontResourceExAp
- && AddFontResourceExAp(filename, FR_PRIVATE, 0)) {
- return 1;
- }
- else if (AddFontResource(filename)) {
- return 1;
+ if (AddFontResourceExAp && RemoveFontResourceExAp) {
+ mm_log((1, "i_wf_addfont: adding via AddFontResourceEx()\n"));
+ if (AddFontResourceExAp(filename, FR_PRIVATE, 0)) {
+ return 1;
+ }
}
else {
- i_push_errorf(0, "Could not add resource: %ld", GetLastError());
- return 0;
+ mm_log((1, "i_wf_addfont: adding via AddFontResource()\n"));
+ if (AddFontResource(filename)) {
+ return 1;
+ }
}
+
+ mm_log((1, "i_wf_addfont failed: %ld\n", GetLastError()));
+ i_push_errorf(0, "Could not add resource: %ld", GetLastError());
+ return 0;
}
/*
i_wf_delfont(char const *filename) {
i_clear_error();
- if (AddFontResourceExAp && RemoveFontResourceExAp
- && RemoveFontResourceExAp(filename, FR_PRIVATE, 0)) {
- return 1;
- }
- else if (RemoveFontResource(filename)) {
- return 1;
+ mm_log((1, "i_wf_delfont(%s)\n", filename));
+
+ if (AddFontResourceExAp && RemoveFontResourceExAp) {
+ mm_log((1, "i_wf_delfont: removing via RemoveFontResourceEx()\n"));
+ if (RemoveFontResourceExAp(filename, FR_PRIVATE, 0))
+ return 1;
}
else {
- i_push_errorf(0, "Could not remove resource: %ld", GetLastError());
- return 0;
+ mm_log((1, "i_wf_delfont: adding via RemoveFontResourceEx()\n"));
+ if (RemoveFontResource(filename))
+ return 1;
}
+
+ mm_log((1, "i_wf_delfont failed: %ld\n", GetLastError()));
+ i_push_errorf(0, "Could not remove resource: %ld", GetLastError());
+ return 0;
}
/*
=cut
*/
-static LPVOID render_text(const char *face, int size, const char *text, int length, int aa,
- HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, int *bbox, int utf8) {
+static unsigned char *
+render_text(const char *face, int size, const char *text, size_t length, int aa,
+ SIZE *psz, TEXTMETRIC *tm, size_t *bytes_per_line, i_img_dim *bbox, int utf8) {
BITMAPINFO bmi;
BITMAPINFOHEADER *bmih = &bmi.bmiHeader;
HDC dc, bmpDc;
LPVOID bits;
int wide_count;
LPWSTR wide_text;
+ unsigned char *result;
dc = GetDC(NULL);
set_logfont(face, size, &lf);
wide_text = utf8_to_wide_string(text, length, &wide_count);
}
else {
- wide_text = NULL;
+ wide_text = latin1_to_wide_string(text, length, &wide_count);
}
bmpDc = CreateCompatibleDC(dc);
oldBm = SelectObject(bmpDc, bm);
SetTextColor(bmpDc, RGB(255, 255, 255));
SetBkColor(bmpDc, RGB(0, 0, 0));
- if (utf8) {
- TextOutW(bmpDc, -bbox[BBOX_NEG_WIDTH], 0, wide_text, wide_count);
- }
- else {
- TextOut(bmpDc, -bbox[BBOX_NEG_WIDTH], 0, text, length);
- }
+ TextOutW(bmpDc, -bbox[BBOX_NEG_WIDTH], 0, wide_text, wide_count);
SelectObject(bmpDc, oldBm);
}
else {
DeleteObject(font);
DeleteDC(bmpDc);
ReleaseDC(NULL, dc);
- if (wide_text)
- myfree(wide_text);
+ myfree(wide_text);
return NULL;
}
SelectObject(bmpDc, oldFont);
DeleteObject(font);
}
else {
- if (wide_text)
- myfree(wide_text);
+ myfree(wide_text);
i_push_errorf(0, "Could not create logical font: %ld",
GetLastError());
DeleteDC(bmpDc);
DeleteDC(bmpDc);
}
else {
- if (wide_text)
- myfree(wide_text);
+ myfree(wide_text);
i_push_errorf(0, "Could not create rendering DC: %ld", GetLastError());
ReleaseDC(NULL, dc);
return NULL;
}
- if (wide_text)
- myfree(wide_text);
+ myfree(wide_text);
ReleaseDC(NULL, dc);
- *pbm = bm;
*psz = sz;
- return bits;
+ /* convert into a map we can just pass to i_render_color() */
+ {
+ i_img_dim x, y;
+ unsigned char *outp, *ucbits;
+ size_t bits_line_width;
+
+ *bytes_per_line = sz.cx;
+ result = mymalloc(sz.cx * sz.cy);
+ outp = result;
+ ucbits = bits;
+ bits_line_width = sz.cx * 3;
+ bits_line_width = (bits_line_width + 3) / 4 * 4;
+
+ for (y = 0; y < sz.cy; ++y) {
+ for (x = 0; x < sz.cx; ++x) {
+ *outp++ = ucbits[3 * x];
+ }
+ ucbits += bits_line_width;
+ }
+ }
+ DeleteObject(bm);
+
+ return result;
}
/*
return result;
}
+static LPWSTR
+latin1_to_wide_string(char const *text, int text_len, int *wide_chars) {
+ LPWSTR result = mymalloc(sizeof(WCHAR) * (text_len + 1));
+ size_t i;
+
+ for (i = 0; i < text_len; ++i) {
+ result[i] = (unsigned char)text[i];
+ }
+ result[i] = 0;
+ *wide_chars = text_len;
+
+ return result;
+}
/*
=back