#include #include #include #include #include "xwchar.h" #include "text.h" #define BUF_SIZE 1024 FontName * fontname_new(void) { FontName *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("fontname_new"); exit(1); } p->next = NULL; p->head = HEAD_ISO8859_1; p->foundry = None; p->name = None; p->base_point = 120; return p; } void fontname_delete(FontName *p) { if (p) free(p); } void fontnamelist_delete(FontNameList l) { FontName *p = l, *q; while (p != NULL) { q = p; p = p->next; fontname_delete(q); } } static OC* _oc_new(void) { OC *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("oc_new"); exit(1); } p->fitable = NULL; return p; } static FontInfoTable* fontinfotable_new(void) { FontInfoTable *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("oc_new"); exit(1); } p->next = NULL; p->head = 0; p->fi = NULL; return p; } /* 全 encoding で一括フォント指定 */ OC * oc_new(FontFaceTableList fftl, FontNameList fnl, int fonttype, double factor) { OC *oc = _oc_new(); FontFaceTable *p = fftl->next; XrmQuark slant, weight; slant = XrmStringToQuark((fonttype & FONTTYPE_ITALIC) ? "i" : "r"); weight = XrmStringToQuark((fonttype & FONTTYPE_BOLD)? "bold":"medium"); while (p != NULL) { FontFace *ff; FontInfo *fi; FontName *q = fnl; /* find font name */ while (q) { if (p->head == q->head) break; q = q->next; } if (q == NULL) q = fnl; if ((ff = FindFontFace(p->faces, q->foundry, q->name, weight, slant, None, 0)) && (fi = FindFontInfo(ff, q->base_point * factor, 0))) { FontInfoTable *fit = fontinfotable_new(); fit->head = p->head; fit->fi = fi; fit->next = oc->fitable; oc->fitable = fit; } p = p->next; } return oc; } void oc_delete(OC *oc) { FontInfoTable *fit, *p; if (oc) { fit = oc->fitable; while (fit != NULL) { fit->fi->count--; /* XXX free font */ p = fit; fit = fit->next; free(p); } free(oc); } } static OCStat * OCStat_new(wchar_t *str, int len) { OCStat *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("OCStat_new"); exit(1); } p->str = str; p->len = len; p->cur = 0; return p; } static void OCStat_delete(OCStat *p) { if (p) free(p); } static void LoadFont(FontInfo *fi) { char xlfd[1024]; XFontStruct *fs; FontFace *face = fi->parent; sprintf(xlfd, "-%s-%s-%s-%s-*--*-%d-*-*-%s-*-%s", XrmQuarkToString(face->foundry), XrmQuarkToString(face->name), XrmQuarkToString(face->weight), XrmQuarkToString(face->slant), fi->point, XrmQuarkToString(face->spacing), XrmQuarkToString(face->encoding)); if ((fs = XLoadQueryFont(face->dpy, xlfd)) == NULL) fprintf(stderr, "warn: can't load font [%s].\n", xlfd); fi->fs = fs; #if 0 fprintf(stderr,"load font: [%p] %s\n", fs, xlfd); #endif } static int wc_convert(OC *oc, OCStat *stat, char *buf, int blen, XFontStruct **fs) { int in, nbyte; wchar_t *str = stat->str; char *out = buf; wchar_t head = HEAD_MASK, head_r; int mask, msb; for (in = stat->cur; in < stat->len; in++) { if (head == HEAD_MASK) { if (IS_LATIN_1(str[in])) { head_r = head = HEAD_ISO8859_1; nbyte = 1; mask = 0xff; msb = 0; } else if (IS_UNICODE(str[in])) { head_r = head = HEAD_UNICODE; nbyte = 2; mask = 0xff; } else { head_r = head = str[in] & HEAD_MASK; if (!IS_MB(head)) { nbyte = 1; if (head == HEAD_JIS_ROMAN) { mask = 0x7f; msb = 0; } else { mask = 0x7f; msb = 0x80; } } else { nbyte = 2; mask = 0x7f; } } /* font search */ { FontInfoTable *p; retry: p = oc->fitable; while (p != NULL) { if (p->head == head) { /* load font */ if (!p->fi->fs) LoadFont(p->fi); *fs = p->fi->fs; goto end; } p = p->next; } if (head == HEAD_JISX0208_O) { head = HEAD_JISX0208; goto retry; } /* not found */ nbyte = -1; head = HEAD_ISO8859_1; fprintf(stderr, "warn: can't find font:[%lx]\n", head); goto retry; } end: ; } else { wchar_t head2; if (IS_LATIN_1(str[in])) head2 = HEAD_ISO8859_1; else if (IS_UNICODE(str[in])) head2 = HEAD_UNICODE; else head2 = str[in] & HEAD_MASK; if (head_r != head2) break; /* change encoding and break */ } switch (nbyte) { case 1: blen--; if (blen <= 0) break; *out++ = (str[in] & mask) | msb; break; case 2: blen-=2; if (blen <= 0) break; *out++ = (str[in] >> 8) & mask; *out++ = str[in] & mask; break; default: blen--; if (blen <= 0) break; *out++ = '='; break; } } *out = '\0'; stat->cur = in; return out - buf; } int WcDrawString(Display *dpy, Drawable drawable, OC *outc, GC gc, int x, int y, wchar_t *string, int length) { char buf[BUF_SIZE]; XFontStruct *fs; int len; int escapement = 0; OCStat *stat = OCStat_new(string, length); while ((len = wc_convert(outc, stat, buf, sizeof(buf), &fs)) > 0) { XSetFont(dpy, gc, fs->fid); if (fs->min_byte1 == 0 && fs->max_byte1 == 0) { XDrawString(dpy, drawable, gc, x + escapement, y, buf, len); escapement += XTextWidth(fs, buf, len); } else { XDrawString16(dpy, drawable, gc, x + escapement, y, (XChar2b*)buf, len/2); escapement += XTextWidth16(fs, (XChar2b*)buf, len/2); } } OCStat_delete(stat); return escapement; } int WcDrawImageString(Display *dpy, Drawable drawable, OC *oc, GC gc, int x, int y, wchar_t *string, int length) { char buf[BUF_SIZE]; XFontStruct *fs; int len; int escapement = 0; OCStat *stat = OCStat_new(string, length); while ((len = wc_convert(oc, stat, buf, sizeof(buf), &fs)) > 0) { XSetFont(dpy, gc, fs->fid); if (fs->min_byte1 == 0 && fs->max_byte1 == 0) { XDrawImageString(dpy, drawable, gc, x + escapement, y, buf, len); escapement += XTextWidth(fs, buf, len); } else { XDrawImageString16(dpy, drawable, gc, x + escapement, y, (XChar2b*)buf, len/2); escapement += XTextWidth16(fs, (XChar2b*)buf, len/2); } } OCStat_delete(stat); return escapement; } int WcTextEscapement(OC *oc, wchar_t *string, int length) { char buf[BUF_SIZE]; XFontStruct *fs; int len; int escapement = 0; OCStat *stat = OCStat_new(string, length); static XFontStruct *old_fs; static int old_escapement; while ((len = wc_convert(oc, stat, buf, BUF_SIZE, &fs)) > 0) { if (fs->min_byte1 == 0 && fs->max_byte1 == 0) { escapement += XTextWidth(fs, buf, len); old_fs = fs; } else { if ((fs == old_fs) && (len == 2)) { /* special case for word wraping */ escapement += old_escapement; } else { old_fs = fs; old_escapement = XTextWidth16(fs, (XChar2b*)buf, len/2); escapement += old_escapement; if (len != 2) { old_fs = NULL; } } } } OCStat_delete(stat); return escapement; } #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif void WcExtents(OC *oc, wchar_t *string, int length, XCharStruct *overall_return) { int len; char buf[BUF_SIZE]; XCharStruct all; XFontStruct *fs; OCStat *stat = OCStat_new(string, length); int flag = 0; int dir, ascent, descent; overall_return->width = 0; overall_return->ascent = 0; overall_return->descent = 0; while ((len = wc_convert(oc, stat, buf, sizeof(buf), &fs)) > 0) { if (fs->min_byte1 == 0 && fs->max_byte1 == 0) { XTextExtents(fs, buf, len, &dir, &ascent, &descent, &all); } else { XTextExtents16(fs, (XChar2b*)buf, len/2, &dir, &ascent, &descent, &all); } if (!flag) { overall_return->lbearing = all.lbearing; flag = 1; } overall_return->width += all.width; overall_return->ascent = MAX(overall_return->ascent, all.ascent); overall_return->descent = MAX(overall_return->descent, all.descent); } overall_return->rbearing = all.rbearing - all.width + overall_return->width; OCStat_delete(stat); } /* form Xlibint.h */ /* $XFree86: xc/lib/X11/Xlibint.h,v 3.7 1996/12/23 05:59:50 dawes Exp $ */ /* $XConsortium: Xlibint.h /main/114 1996/10/22 14:24:29 kaleb $ */ /* Copyright (c) 1984, 1985, 1987, 1989 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. */ /* * Xlibint.h - Header definition and support file for the internal * support routines used by the C subroutine interface * library (Xlib) to the X Window System. * * Warning, there be dragons here.... */ #include /* snip snip */ #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ (((cs)->rbearing|(cs)->lbearing| \ (cs)->ascent|(cs)->descent) == 0)) /* * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit * character. If the character is in the column and exists, then return the * appropriate metrics (note that fonts with common per-character metrics will * return min_bounds). If none of these hold true, try again with the default * char. */ #define CI_GET_CHAR_INFO_1D(fs,col,def,cs) \ { \ cs = def; \ if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ if (fs->per_char == NULL) { \ cs = &fs->min_bounds; \ } else { \ cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ if (CI_NONEXISTCHAR(cs)) cs = def; \ } \ } \ } #define CI_GET_DEFAULT_INFO_1D(fs,cs) \ CI_GET_CHAR_INFO_1D (fs, fs->default_char, NULL, cs) /* * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and * column. This is used for fonts that have more than row zero. */ #define CI_GET_CHAR_INFO_2D(fs,row,col,def,cs) \ { \ cs = def; \ if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ if (fs->per_char == NULL) { \ cs = &fs->min_bounds; \ } else { \ cs = &fs->per_char[((row - fs->min_byte1) * \ (fs->max_char_or_byte2 - \ fs->min_char_or_byte2 + 1)) + \ (col - fs->min_char_or_byte2)]; \ if (CI_NONEXISTCHAR(cs)) cs = def; \ } \ } \ } #define CI_GET_DEFAULT_INFO_2D(fs,cs) \ { \ unsigned int r = (fs->default_char >> 8); \ unsigned int c = (fs->default_char & 0xff); \ CI_GET_CHAR_INFO_2D (fs, r, c, NULL, cs); \ } int WcWidth(OC *oc, wchar_t wc) { static wchar_t head_old = 0xffffffff; static XFontStruct *fs; wchar_t head; int mask, msb; head = wc & HEAD_MASK; if (head != head_old) { /* cache */ head_old = head; if (!IS_MB(head)) { if (IS_LATIN_1(head)) { head = HEAD_ISO8859_1; mask = 0xff; msb = 0; } else if (head == HEAD_JIS_ROMAN) { mask = 0x7f; msb = 0; } else { mask = 0x7f; msb = 0x80; } } /* font search */ { FontInfoTable *p; retry: p = oc->fitable; while (p != NULL) { if (p->head == head) { if (!p->fi->fs) LoadFont(p->fi); fs = p->fi->fs; goto end; } p = p->next; } if (head == HEAD_JISX0208_O) { head = HEAD_JISX0208; goto retry; } /* not found */ head = HEAD_ISO8859_1; goto retry; } end: ; } { register XCharStruct *def; register XCharStruct *cs; if (fs->min_byte1 == 0 && fs->max_byte1 == 0) { CI_GET_DEFAULT_INFO_1D(fs,def); CI_GET_CHAR_INFO_1D(fs,((wc & mask)|msb),def,cs); return cs->width; } else { u_int r = wc & 0x7f; u_int c = (wc >> 8) & 0x7f; CI_GET_DEFAULT_INFO_2D (fs, def); CI_GET_CHAR_INFO_2D (fs, r, c, def, cs); return cs->width; } } } int gyomatsu_kinsoku(wchar_t wc) { wchar_t head; if (IS_LATIN_1(wc)) { if (wc == '(' || wc == '[') return -1; } else if ((head = (wc & HEAD_MASK)) == HEAD_JISX0208) { wchar_t ch = wc & 0x00007f7f; /* 括弧開き */ if (ch == 0x214a || ch == 0x214c || ch == 0x214e || ch == 0x2150 || ch == 0x2152 || ch == 0x2154 || ch == 0x2156 || ch == 0x2158 || ch == 0x215a) return -1; } return 0; } int gyoto_kinsoku(wchar_t wc) { wchar_t head; if (IS_LATIN_1(wc)) { if (wc == '.' || wc == ',' || wc == '!' || wc == '?') return -1; } else if ((head = (wc & HEAD_MASK)) == HEAD_JISX0208) { wchar_t ch = wc & 0x00007f7f; /* 句読点 */ if ((ch > 0x2121 && ch < 0x2125) || ch == 0x2129 || ch == 0x212a || /* 拗音 */ ch == 0x2421 || ch == 0x2423 || ch == 0x2425 || ch == 0x2427 || ch == 0x2429 || ch == 0x2443 || ch == 0x2463 || ch == 0x2465 || ch == 0x2467 || ch == 0x246e || ch == 0x2521 || ch == 0x2523 || ch == 0x2525 || ch == 0x2527 || ch == 0x2529 || ch == 0x2543 || ch == 0x2563 || ch == 0x2565 || ch == 0x2567 || ch == 0x256e || /* 括弧閉じ */ ch == 0x214b || ch == 0x214d || ch == 0x214f || ch == 0x2151 || ch == 0x2153 || ch == 0x2155 || ch == 0x2157 || ch == 0x2159 || ch == 0x215b ) return -1; } return 0; }