void DrawCharacters(Page *page) { size_t start = page->start; size_t i; for (i = start; i < page->end; i++) { short x = character_positions[i].x; short y = character_positions[i].y; if (IsPrint(text[i])) { draw: ; XChar2b font_code; XFontStruct *font = SelectFont(text[i], &font_code); GC gc = XCreateGC(disp, back_buffer, 0, NULL); XCopyGC(disp, default_gc, GCForeground | GCBackground, gc); XSetFont(disp, gc, font->fid); XDrawString16(disp, back_buffer, gc, x, y + (font->ascent - default_font->ascent), &font_code, 1); XFreeGC(disp, gc); } else { if (EqAscii2b(text[i], '\n')) { // DOWNWARDS ARROW WITH TIP LEFTWARDS XChar2b symbol = { .byte1 = 0x21, .byte2 = 0xb2 }; XDrawString16(disp, back_buffer, control_gc, x, y, &symbol, 1); } else if (EqAscii2b(text[i], '\t')) { ; } else { goto draw; } } }
void Fl_Device::transformed_draw(const char *str, int n, float x, float y) { if (font_gc != fl_gc) { font_gc = fl_gc; XSetFont(fl_display, fl_gc, current_font->fid); } int X = int(floor(x+.5f)); int Y = int(floor(y+.5f)); #if HAVE_XUTF8 char glyph[2]; // byte1 and byte2 value of the UTF-8 char XChar2b buf[128]; // drawing buffer int pos = 0; // position in buffer int ulen; // byte length of the UTF-8 char unsigned int ucs; // Unicode value of the UTF-8 char unsigned int no_spc; // Spacing char equivalent of a non-spacing char while(n > 0) { if(pos>120) { XDrawString16(fl_display, fl_window, fl_gc, X, Y, buf, pos); X += XTextWidth16(current_font, buf, pos); pos = 0; } ulen = fl_fast_utf2ucs((unsigned char*)str, n, &ucs); if (ulen < 1) ulen = 1; no_spc = fl_nonspacing(ucs); if(no_spc) ucs = no_spc; if(fl_ucs2fontmap(glyph, ucs, fl_fontsize->encoding_num) < 0) { // the char is not valid in this encoding fl_ucs2fontmap(glyph, '?', fl_fontsize->encoding_num); } if(no_spc) { XDrawString16(fl_display, fl_window, fl_gc, X, Y, buf, pos); X += XTextWidth16(current_font, buf, pos); pos = 0; (*buf).byte1 = glyph[1]; (*buf).byte2 = glyph[0]; X -= XTextWidth16(current_font, buf, 1); } else { (*(buf + pos)).byte1 = glyph[1]; (*(buf + pos)).byte2 = glyph[0]; } pos++; str += ulen; n-=ulen; } if(pos>0) XDrawString16(fl_display, fl_window, fl_gc, X, Y, buf, pos); #else XDrawString(fl_display, fl_window, fl_gc, X, Y, str, n); #endif }
void MCOldFontlist::ctxt_drawtext(MCX11Context *ctxt, int2 x, int2 y, const char *s, uint2 l, MCFontStruct *of, Boolean image, bool p_unicode_override) { MCOldFontStruct *f; f = static_cast<MCOldFontStruct *>(of); bool useUnicode = (f->max_byte1 > 0 || f->unicode) || p_unicode_override; if ( useUnicode ) { uint2 x_l ; XChar2b x_s[l / 2]; x_l = (l + 1) / 2; for(int i = 0; i < x_l; ++i) x_s[i] . byte1 = s[i * 2 + 1], x_s[i] . byte2 = s[i * 2]; if (image) { XDrawImageString16(ctxt -> m_display, ctxt -> m_layers -> surface, ctxt -> m_gc, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , (const XChar2b *)x_s, x_l); XDrawImageString16(ctxt -> m_display, ctxt -> m_mask, ctxt -> m_gc1, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , (const XChar2b *)x_s, x_l); } else { XDrawString16(ctxt -> m_display, ctxt -> m_layers -> surface, ctxt -> m_gc, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , (const XChar2b *)x_s, x_l); XDrawString16(ctxt -> m_display, ctxt -> m_mask, ctxt -> m_gc1, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , (const XChar2b *)x_s, x_l); } } else { if (image) { XDrawImageString(ctxt -> m_display, ctxt -> m_layers -> surface, ctxt -> m_gc, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , s, l); XDrawImageString(ctxt -> m_display, ctxt -> m_mask, ctxt -> m_gc1, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , s, l); } else { XDrawString(ctxt -> m_display, ctxt -> m_layers -> surface, ctxt -> m_gc, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , s, l); XDrawString(ctxt -> m_display, ctxt -> m_mask, ctxt -> m_gc1, x - ctxt -> m_layers -> origin . x , y - ctxt -> m_layers -> origin . y , s, l); } } ctxt -> update_mask ( 0, ( y - ctxt -> m_layers -> origin . y ) - f -> ascent, ctxt -> m_layers -> clip . width, f -> ascent + f -> descent ) ; }
void polytext16_test(void) { int num_strings = 50; int i; long totaltime; char buf[80]; num_strings *= X.percent; GC_change_font(unicode_font,FALSE); XSync(X.dpy,0); start_timer(); for (i=0;i<num_strings;++i) { XDrawString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i, string16,sizeof(string16)/sizeof(XChar2b)); } XSync(X.dpy,0); totaltime = end_timer(); GC_change_font(X.fontname,FALSE); snprintf(buf,sizeof buf,"%d strings in %.2f seconds.",num_strings, (double) totaltime/1000000.); show_result(buf); }
/** Render string of 16-bit \a chars (foreground only) in \a pDrawable * on the back-end server associated with \a pDrawable's screen. If * the offscreen optimization is enabled, only draw when \a pDrawable * is at least partially visible. */ int dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); unsigned long n, i; int w; CharInfoPtr charinfo[255]; Drawable draw; GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, &n, charinfo); /* Calculate text width */ w = 0; for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth; if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) { DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc, x, y, (XChar2b *)chars, count); dmxSync(dmxScreen, FALSE); } return x+w; }
void XftDrawStringUtf8 (XftDraw *draw, XftColor *color, XftFont *font, int x, int y, XftChar8 *string, int len) { if (font->core) { XChar2b *xc; XChar2b xcloc[XFT_CORE_N16LOCAL]; int n; XftDrawCorePrepare (draw, color, font); xc = XftCoreConvertUtf8 (string, len, xcloc, &n); if (xc) { XDrawString16 (draw->dpy, draw->drawable, draw->core.draw_gc, x, y, xc, n); } if (xc != xcloc) free (xc); } #ifdef FREETYPE2 else if (XftDrawRenderPrepare (draw, color, font, XFT_DRAW_SRC_TEXT)) { XftRenderStringUtf8 (draw->dpy, draw->render.src[XFT_DRAW_SRC_TEXT].pict, font->u.ft.font, draw->render.pict, 0, 0, x, y, string, len); } #endif }
/* * Generate OpenGL-compatible bitmap. */ static void fill_bitmap(Display * dpy, Window win, GC gc, unsigned int width, unsigned int height, int x0, int y0, unsigned int c, GLubyte * bitmap) { XImage *image; unsigned int x, y; Pixmap pixmap; XChar2b char2b; pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1); XSetForeground(dpy, gc, 0); XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height); XSetForeground(dpy, gc, 1); char2b.byte1 = (c >> 8) & 0xff; char2b.byte2 = (c & 0xff); XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap); if (image) { /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ for (y = 0; y < height; y++) for (x = 0; x < 8 * width; x++) if (XGetPixel(image, x, y)) bitmap[width * (height - y - 1) + x / 8] |= (1 << (7 - (x % 8))); XDestroyImage(image); } XFreePixmap(dpy, pixmap); }
void debrush_do_draw_string_default_bmf( DEBrush *brush, int x, int y, const char *str, int len, bool needfill, DEColourGroup *colours) { GC gc=brush->d->normal_gc; if(brush->d->font==NULL) return; XSetForeground(ioncore_g.dpy, gc, PIXEL(colours->fg)); if(!needfill){ if(brush->d->font->fontset!=NULL){ #ifdef CF_DE_USE_XUTF8 if(ioncore_g.enc_utf8) Xutf8DrawString(ioncore_g.dpy, brush->win, brush->d->font->fontset, gc, x, y, str, len); else #endif XmbDrawString(ioncore_g.dpy, brush->win, brush->d->font->fontset, gc, x, y, str, len); }else if(brush->d->font->fontstruct!=NULL){ if(ioncore_g.enc_utf8){ XChar2b *str16; int len16=0; toucs(str, len, &str16, &len16); XDrawString16(ioncore_g.dpy, brush->win, gc, x, y, str16, len16); free(str16); }else{ XDrawString(ioncore_g.dpy, brush->win, gc, x, y, str, len); } } }else{ XSetBackground(ioncore_g.dpy, gc, PIXEL(colours->bg)); if(brush->d->font->fontset!=NULL){ #ifdef CF_DE_USE_XUTF8 if(ioncore_g.enc_utf8) Xutf8DrawImageString(ioncore_g.dpy, brush->win, brush->d->font->fontset, gc, x, y, str, len); else #endif XmbDrawImageString(ioncore_g.dpy, brush->win, brush->d->font->fontset, gc, x, y, str, len); }else if(brush->d->font->fontstruct!=NULL){ if(ioncore_g.enc_utf8){ XChar2b *str16; int len16=0; toucs(str, len, &str16, &len16); XDrawImageString16(ioncore_g.dpy, brush->win, gc, x, y, str16, len16); free(str16); }else{ XDrawImageString(ioncore_g.dpy, brush->win, gc, x, y, str, len); } } } }
int main(int argc, char *argv[]) { Display *display; int screen; GC gc; Window window; XWMHints hints; Atom protocols; XEvent event; unsigned long mask; Font xfont1, xfont2; display = XOpenDisplay(""); screen = DefaultScreen(display); gc = DefaultGC(display, screen); /* * Font names are hard-coded. */ xfont1 = XLoadFont(display, "a14"); xfont2 = XLoadFont(display, "k14"); window = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, W_WIDTH, W_HEIGHT, 2, BlackPixel(display, screen), WhitePixel(display, screen)); XStoreName(display, window, "XFontStruct demo"); hints.flags = InputHint; hints.input = True; XSetWMHints(display, window, &hints); protocols = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, window, &protocols, 1); mask = ExposureMask; XSelectInput(display, window, mask); XMapWindow(display, window); for (;;) { XNextEvent(display, &event); if (XFilterEvent(&event, window) == True) continue; switch (event.type) { case Expose: { XSetFont(display, gc, xfont1); XDrawString(display, window, gc, 10, 50, "abcdef", 6); XSetFont(display, gc, xfont2); /* JIS */ XDrawString16(display, window, gc, 10, 80, (XChar2b *) "\x24\x22\x24\x24", 4); break; } default: { break; } } } }
static void X11DRV_DrawString_normal( fontObject* pfo, Display* pdisp, Drawable d, GC gc, int x, int y, XChar2b* pstr, int count ) { wine_tsx11_lock(); XDrawString16( pdisp, d, gc, x, y, pstr, count ); wine_tsx11_unlock(); }
static void _XawLabelDraw16(Display *dpy, Drawable d, GC gc, int x, int y, char *str, int n) { int i; XChar2b *ptr; if (n > buf2blen) { buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b)); buf2blen = n; } for (ptr = buf2b, i = n; --i >= 0; ptr++) { ptr->byte1 = *str++; ptr->byte2 = *str++; } XDrawString16(dpy, d, gc, x, y, buf2b, n); }
/* gdk_x11_draw_text * * Modified by Li-Da Lho to draw 16 bits and Multibyte strings * * Interface changed: add "GdkFont *font" to specify font or fontset explicitely */ static void gdk_x11_draw_text (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length) { GdkDrawableImplX11 *impl; Display *xdisplay; impl = GDK_DRAWABLE_IMPL_X11 (drawable); xdisplay = GDK_SCREEN_XDISPLAY (impl->screen); if (font->type == GDK_FONT_FONT) { XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font); XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid); if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) { XDrawString (xdisplay, impl->xid, GDK_GC_GET_XGC (gc), x, y, text, text_length); } else { XDrawString16 (xdisplay, impl->xid, GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2); } } else if (font->type == GDK_FONT_FONTSET) { XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font); XmbDrawString (xdisplay, impl->xid, fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length); } else g_error("undefined font type\n"); }
/*ARGSUSED*/ static void XawLabelRedisplay(Widget gw, XEvent *event, Region region) { LabelWidget w = (LabelWidget)gw; GC gc; if (*Superclass->core_class.expose != NULL) (*Superclass->core_class.expose)(gw, event, region); gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC; #ifdef notdef if (region != NULL) XSetRegion(XtDisplay(gw), gc, region); #endif /*notdef*/ if (w->label.pixmap == None) { int len = w->label.label_len; char *label = w->label.label; Position y = w->label.label_y + w->label.font->max_bounds.ascent; Position ksy = w->label.label_y; /* display left bitmap */ if (w->label.left_bitmap && w->label.lbm_width != 0) XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc, 0, 0, w->label.lbm_width, w->label.lbm_height, w->label.internal_width, w->label.internal_height + w->label.lbm_y, 1L); if (w->simple.international == True) { XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset); ksy += XawAbs(ext->max_ink_extent.y); if (len == MULTI_LINE_LABEL) { char *nl; while ((nl = index(label, '\n')) != NULL) { XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc, w->label.label_x, ksy, label, (int)(nl - label)); ksy += ext->max_ink_extent.height; label = nl + 1; } len = strlen(label); } if (len) XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc, w->label.label_x, ksy, label, len); } else { if (len == MULTI_LINE_LABEL) { char *nl; while ((nl = index(label, '\n')) != NULL) { if (w->label.encoding) XDrawString16(XtDisplay(gw), XtWindow(gw), gc, w->label.label_x, y, (XChar2b *)label, (int)(nl - label) / 2); else XDrawString(XtDisplay(gw), XtWindow(gw), gc, w->label.label_x, y, label, (int)(nl - label)); y += w->label.font->max_bounds.ascent + w->label.font->max_bounds.descent; label = nl + 1; } len = strlen(label); } if (len) { if (w->label.encoding) XDrawString16(XtDisplay(gw), XtWindow(gw), gc, w->label.label_x, y, (XChar2b *)label, len / 2); else XDrawString(XtDisplay(gw), XtWindow(gw), gc, w->label.label_x, y, label, len); } } } else if (w->label.label_len == 1) XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc, 0, 0, w->label.label_width, w->label.label_height, w->label.label_x, w->label.label_y, 1L); else XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc, 0, 0, w->label.label_width, w->label.label_height, w->label.label_x, w->label.label_y); #ifdef notdef if (region != NULL) XSetClipMask(XtDisplay(gw), gc, (Pixmap)None); #endif /* notdef */ }
void my_gdk_draw_text(GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length) { #ifdef MOZ_WIDGET_GTK GdkWindowPrivate *drawable_private; GdkFontPrivate *font_private; GdkGCPrivate *gc_private; #endif /* MOZ_WIDGET_GTK */ g_return_if_fail (drawable != NULL); g_return_if_fail (font != NULL); g_return_if_fail (gc != NULL); g_return_if_fail (text != NULL); #ifdef MOZ_WIDGET_GTK drawable_private = (GdkWindowPrivate*) drawable; if (drawable_private->destroyed) return; gc_private = (GdkGCPrivate*) gc; font_private = (GdkFontPrivate*) font; #endif /* MOZ_WIDGET_GTK */ #ifdef MOZ_WIDGET_GTK2 if (GDK_IS_WINDOW(drawable) && GDK_WINDOW_OBJECT(drawable)->destroyed) return; #endif /* MOZ_WIDGET_GTK2 */ if (font->type == GDK_FONT_FONT) { #ifdef MOZ_WIDGET_GTK XFontStruct *xfont = (XFontStruct *) font_private->xfont; #endif /* MOZ_WIDGET_GTK */ #ifdef MOZ_WIDGET_GTK2 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT(font); #endif /* MOZ_WIDGET_GTK2 */ // gdk does this... we don't need it.. // XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid); // We clamp the sizes down to 32768 which is the maximum width of // a window. Even if a font was 1 pixel high and started at the // left, the maximum size of a draw request could only be 32k. if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) { #ifdef MOZ_WIDGET_GTK XDrawString (drawable_private->xdisplay, drawable_private->xwindow, gc_private->xgc, x, y, text, MIN(text_length, 32768)); #endif /* MOZ_WIDGET_GTK */ #ifdef MOZ_WIDGET_GTK2 XDrawString (GDK_WINDOW_XDISPLAY(drawable), GDK_DRAWABLE_XID(drawable), GDK_GC_XGC(gc), x, y, text, MIN(text_length, 32768)); #endif /* MOZ_WIDGET_GTK2 */ } else { #ifdef MOZ_WIDGET_GTK XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow, gc_private->xgc, x, y, (XChar2b *) text, MIN((text_length / 2), 32768)); #endif /* MOZ_WIDGET_GTK */ #ifdef MOZ_WIDGET_GTK2 XDrawString16 (GDK_WINDOW_XDISPLAY(drawable), GDK_DRAWABLE_XID(drawable), GDK_GC_XGC(gc), x, y, (XChar2b *) text, MIN((text_length / 2), 32768)); #endif /* MOZ_WIDGET_GTK2 */ } } else if (font->type == GDK_FONT_FONTSET) { #ifdef MOZ_WIDGET_GTK XFontSet fontset = (XFontSet) font_private->xfont; XmbDrawString (drawable_private->xdisplay, drawable_private->xwindow, fontset, gc_private->xgc, x, y, text, text_length); #endif /* MOZ_WIDGET_GTK */ #ifdef MOZ_WIDGET_GTK2 XFontSet fontset = (XFontSet) GDK_FONT_XFONT(font); XmbDrawString (GDK_WINDOW_XDISPLAY(drawable), GDK_DRAWABLE_XID(drawable), fontset, GDK_GC_XGC(gc), x, y, text, text_length); #endif /* MOZ_WIDGET_GTK2 */ } else g_error("undefined font type\n"); }
void captureXFont(Display * dpy, Font font, char *xfont, char *name) { int first, last, count; int cnt, len; Pixmap offscreen; Window drawable; XFontStruct *fontinfo; XImage *image; GC xgc; XGCValues values; int width, height; int i, j, k; XCharStruct *charinfo; XChar2b character; GLubyte *bitmapData; int x, y; int spanLength; int charWidth, charHeight, maxSpanLength, pixwidth; int grabList[MAX_GLYPHS_PER_GRAB]; int glyphsPerGrab = MAX_GLYPHS_PER_GRAB; int numToGrab; int rows, pages, byte1, byte2, index; int nullBitmap; drawable = RootWindow(dpy, DefaultScreen(dpy)); fontinfo = XQueryFont(dpy, font); pages = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1; first = (fontinfo->min_byte1 << 8) + fontinfo->min_char_or_byte2; last = (fontinfo->max_byte1 << 8) + fontinfo->max_char_or_byte2; count = last - first + 1; width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing; height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent; /* 16-bit fonts have more than one row; indexing into per_char is trickier. */ rows = fontinfo->max_byte1 - fontinfo->min_byte1 + 1; maxSpanLength = (width + 7) / 8; /* For portability reasons we don't use alloca for bitmapData, but we could. */ bitmapData = malloc(height * maxSpanLength); /* Be careful determining the width of the pixmap; the X protocol allows pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates max out at 2^15-1 (signed short size). If the width is too large, we need to limit the glyphs per grab. */ if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) { glyphsPerGrab = (1 << 15) / (8 * maxSpanLength); } pixwidth = glyphsPerGrab * 8 * maxSpanLength; offscreen = XCreatePixmap(dpy, drawable, pixwidth, height, 1); values.font = font; values.background = 0; values.foreground = 0; xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values); XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height); XSetForeground(dpy, xgc, 1); numToGrab = 0; if (fontinfo->per_char == NULL) { charinfo = &(fontinfo->min_bounds); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; spanLength = (charWidth + 7) / 8; } printf("\n/* GENERATED FILE -- DO NOT MODIFY */\n\n"); printf("#include \"glutbitmap.h\"\n\n"); for (i = first; count; i++, count--) { int undefined; if (rows == 1) { undefined = (fontinfo->min_char_or_byte2 > i || fontinfo->max_char_or_byte2 < i); } else { byte2 = i & 0xff; byte1 = i >> 8; undefined = (fontinfo->min_char_or_byte2 > byte2 || fontinfo->max_char_or_byte2 < byte2 || fontinfo->min_byte1 > byte1 || fontinfo->max_byte1 < byte1); } if (undefined) { goto PossiblyDoGrab; } if (fontinfo->per_char != NULL) { if (rows == 1) { index = i - fontinfo->min_char_or_byte2; } else { byte2 = i & 0xff; byte1 = i >> 8; index = (byte1 - fontinfo->min_byte1) * pages + (byte2 - fontinfo->min_char_or_byte2); } charinfo = &(fontinfo->per_char[index]); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; if (charWidth == 0 || charHeight == 0) { if (charinfo->width != 0) { /* Still must move raster pos even if empty character */ outputChar(i, 0, 0, 0, 0, charinfo->width, 0); } goto PossiblyDoGrab; } } grabList[numToGrab] = i; character.byte2 = i & 255; character.byte1 = i >> 8; /* XXX We could use XDrawImageString16 which would also paint the backing rectangle but X server bugs in some scalable font rasterizers makes it more effective to do XFillRectangles to clear the pixmap and then XDrawImage16 for the text. */ XDrawString16(dpy, offscreen, xgc, -charinfo->lbearing + 8 * maxSpanLength * numToGrab, charinfo->ascent, &character, 1); numToGrab++; PossiblyDoGrab: if (numToGrab >= glyphsPerGrab || count == 1) { image = XGetImage(dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap); for (j = numToGrab - 1; j >= 0; j--) { if (fontinfo->per_char != NULL) { byte2 = grabList[j] & 0xff; byte1 = grabList[j] >> 8; index = (byte1 - fontinfo->min_byte1) * pages + (byte2 - fontinfo->min_char_or_byte2); charinfo = &(fontinfo->per_char[index]); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; spanLength = (charWidth + 7) / 8; } memset(bitmapData, 0, height * spanLength); for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) { /* Little endian machines (such as DEC Alpha) could benefit from reversing the bit order here and changing the GL_UNPACK_LSB_FIRST parameter in glutBitmapCharacter to GL_TRUE. */ bitmapData[y * spanLength + x / 8] |= (1 << (7 - (x & 7))); } } } if (PRINTABLE(grabList[j])) { printf("/* char: 0x%x '%c' */\n\n", grabList[j], grabList[j]); } else { printf("/* char: 0x%x */\n\n", grabList[j]); } /* Determine if the bitmap is null. */ nullBitmap = 1; len = (charinfo->ascent + charinfo->descent) * ((charinfo->rbearing - charinfo->lbearing + 7) / 8); cnt = 0; while (cnt < len) { for (k = 0; k < 16 && cnt < len; k++, cnt++) { if (bitmapData[cnt] != 0) { nullBitmap = 0; } } } if (!nullBitmap) { printf("static const GLubyte ch%ddata[] = {\n", grabList[j]); len = (charinfo->ascent + charinfo->descent) * ((charinfo->rbearing - charinfo->lbearing + 7) / 8); cnt = 0; while (cnt < len) { for (k = 0; k < 16 && cnt < len; k++, cnt++) { printf("0x%x,", bitmapData[cnt]); } printf("\n"); } printf("};\n\n"); } else { charWidth = 0; charHeight = 0; } outputChar(grabList[j], charWidth, charHeight, -charinfo->lbearing, charinfo->descent, charinfo->width, !nullBitmap); } XDestroyImage(image); numToGrab = 0; if (count > 0) { XSetForeground(dpy, xgc, 0); XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height); XSetForeground(dpy, xgc, 1); } }
// 次のページの開始位置、あるいは文書の終端 (== text_length) を返す。 size_t FillPage(size_t start, Page *page, bool draw) { XWindowAttributes attrs; XGetWindowAttributes(disp, win, &attrs); // ページのサイズ。 const int LEFT_MARGIN = 50; const int RIGHT_MARGIN = attrs.width - LEFT_MARGIN; const int TOP_MARGIN = 50; const int BOTTOM_MARGIN = attrs.height - TOP_MARGIN; const XChar2b sp = { 0x00, 0x21 }; const int EM = GetCharWidth(sp); // 行の高さ。 const int LINE_HEIGHT = 22; // 現在の文字の描画位置。 int x = LEFT_MARGIN, y = TOP_MARGIN + font->ascent; size_t i; for (i = start; i < text_length; i++) { // カーソルの描画 if (draw && i == cursor_position) { XFillRectangle(disp, win, cursor_gc, x, y - font->ascent, CURSOR_WIDTH, font->ascent + font->descent); } if (IsPrint(text[i])) { // 印字可能文字の場合。 int width = GetCharWidth(text[i]); // この文字を描画すると右マージンにかかるようなら改行する。 // ただし、行頭に居る場合は改行しない。 if ( x + width > RIGHT_MARGIN && !ForbiddenAtStart(text[i]) && // 行頭禁止文字ならばぶらさげる x != LEFT_MARGIN ) { y += LINE_HEIGHT; x = LEFT_MARGIN; // ページにも収まらない場合、この位置で終了する。 if (y + font->descent > BOTTOM_MARGIN) { page->start = start; page->end = i; return i; } } if (draw) XDrawString16(disp, win, gc, x, y, &text[i], 1); x += width; } else { // ラインフィードで改行する。 if (EqAscii2b(text[i], '\n')) { if (draw) { // DOWNWARDS ARROW WITH TIP LEFTWARDS XChar2b symbol = { .byte1 = 0x21, .byte2 = 0xb2 }; XDrawString16(disp, win, control_gc, x, y, &symbol, 1); } y += LINE_HEIGHT; x = LEFT_MARGIN; // ページにも収まらない場合、次の位置で終了する。 // ページ区切り位置での改行は持ち越さない。 if (y + font->descent > BOTTOM_MARGIN) { page->start = start; page->end = i + 1; return i + 1; } } else if (EqAscii2b(text[i], '\t')) { int tab = EM * 8; x = LEFT_MARGIN + (((x - LEFT_MARGIN) / tab) + 1) * tab; } } } if (draw && i == cursor_position) { XFillRectangle(disp, win, cursor_gc, x, y - font->ascent, CURSOR_WIDTH, font->ascent + font->descent); } if (draw) XDrawString(disp, win, control_gc, x, y, "[EOF]", 5); // 全てのテキストを配置した。 page->start = start; page->end = text_length; return text_length; }
/** * Generate OpenGL-compatible bitmap by drawing an X character glyph * to an off-screen pixmap, then getting the image and testing pixels. * \param width bitmap width in pixels * \param height bitmap height in pixels */ static void fill_bitmap(Display *dpy, Pixmap pixmap, GC gc, unsigned int bitmapWidth, unsigned int bitmapHeight, unsigned int charWidth, unsigned int charHeight, int xPos, int yPos, unsigned int c, GLubyte * bitmap, int rotation) { const int bytesPerRow = (bitmapWidth + 7) / 8; XImage *image; XChar2b char2b; /* clear pixmap to 0 */ XSetForeground(dpy, gc, 0); XFillRectangle(dpy, pixmap, gc, 0, 0, charWidth, charHeight); /* The glyph is drawn snug up against the left/top edges of the pixmap */ XSetForeground(dpy, gc, 1); char2b.byte1 = (c >> 8) & 0xff; char2b.byte2 = (c & 0xff); XDrawString16(dpy, pixmap, gc, xPos, yPos, &char2b, 1); /* initialize GL bitmap */ memset(bitmap, 0, bytesPerRow * bitmapHeight); image = XGetImage(dpy, pixmap, 0, 0, charWidth, charHeight, 1, XYPixmap); if (image) { /* Set appropriate bits in the GL bitmap. * Note: X11 and OpenGL are upside down wrt each other). */ unsigned int x, y; if (rotation == 0) { for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { if (XGetPixel(image, x, y)) { int y2 = bitmapHeight - y - 1; bitmap[bytesPerRow * y2 + x / 8] |= (1 << (7 - (x % 8))); } } } } else if (rotation == 90) { for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { if (XGetPixel(image, x, y)) { int x2 = y; int y2 = x; bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); } } } } else if (rotation == 180) { for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { if (XGetPixel(image, x, y)) { int x2 = charWidth - x - 1; bitmap[bytesPerRow * y + x2 / 8] |= (1 << (7 - (x2 % 8))); } } } } else { for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { if (XGetPixel(image, x, y)) { int x2 = charHeight - y - 1; int y2 = charWidth - x - 1; bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); } } } } XDestroyImage(image); } }
FontInfoPtr SuckGlyphsFromServer(Display * dpy, Font font) { Pixmap offscreen; XFontStruct *fontinfo; XImage *image; GC xgc; XGCValues values; int numchars; int width, height, pixwidth; int i, j; XCharStruct *charinfo; XChar2b character; char *bitmapData; int x, y; int spanLength; int charWidth, charHeight, maxSpanLength; int grabList[MAX_GLYPHS_PER_GRAB]; int glyphsPerGrab = MAX_GLYPHS_PER_GRAB; int numToGrab, thisglyph; FontInfoPtr myfontinfo; fontinfo = XQueryFont(dpy, font); if (!fontinfo) return NULL; numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1; if (numchars < 1) return NULL; myfontinfo = (FontInfoPtr) malloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerCharInfo)); if (!myfontinfo) return NULL; myfontinfo->min_char = fontinfo->min_char_or_byte2; myfontinfo->max_char = fontinfo->max_char_or_byte2; myfontinfo->max_ascent = fontinfo->max_bounds.ascent; myfontinfo->max_descent = fontinfo->max_bounds.descent; myfontinfo->dlist_base = 0; width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing; height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent; maxSpanLength = (width + 7) / 8; /* * Be careful determining the width of the pixmap; the X protocol allows * pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates * max out at 2^15-1 (signed short size). If the width is too large, * we need to limit the glyphs per grab. */ if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) { glyphsPerGrab = (1 << 15) / (8 * maxSpanLength); } pixwidth = glyphsPerGrab * 8 * maxSpanLength; offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), pixwidth, height, 1); values.font = font; values.background = 0; values.foreground = 0; xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values); XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height); XSetForeground(dpy, xgc, 1); numToGrab = 0; if (fontinfo->per_char == NULL) { charinfo = &(fontinfo->min_bounds); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; spanLength = (charWidth + 7) / 8; } for (i = 0; i < numchars; i++) { if (fontinfo->per_char != NULL) { charinfo = &(fontinfo->per_char[i]); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; if (charWidth == 0 || charHeight == 0) { /* Still must move raster pos even if empty character */ myfontinfo->glyph[i].width = 0; myfontinfo->glyph[i].height = 0; myfontinfo->glyph[i].xoffset = 0; myfontinfo->glyph[i].yoffset = 0; myfontinfo->glyph[i].advance = charinfo->width; myfontinfo->glyph[i].bitmap = NULL; goto PossiblyDoGrab; } } grabList[numToGrab] = i; /* XXX is this right for large fonts? */ character.byte2 = (i + fontinfo->min_char_or_byte2) & 255; character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8; /* * XXX we could use XDrawImageString16 which would also paint the * backing rectangle but X server bugs in some scalable font * rasterizers makes it more effective to do XFillRectangles to clear * the pixmap and XDrawImage16 for the text. */ XDrawString16(dpy, offscreen, xgc, -charinfo->lbearing + 8 * maxSpanLength * numToGrab, charinfo->ascent, &character, 1); numToGrab++; PossiblyDoGrab: if (numToGrab >= glyphsPerGrab || i == numchars - 1) { image = XGetImage(dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap); for (j = 0; j < numToGrab; j++) { thisglyph = grabList[j]; if (fontinfo->per_char != NULL) { charinfo = &(fontinfo->per_char[thisglyph]); charWidth = charinfo->rbearing - charinfo->lbearing; charHeight = charinfo->ascent + charinfo->descent; spanLength = (charWidth + 7) / 8; } bitmapData = calloc(height * spanLength, sizeof(char)); if (!bitmapData) goto FreeFontAndReturn; DEBUG_GLYPH4("index %d, glyph %d (%d by %d)\n", j, thisglyph + fontinfo->min_char_or_byte2, charWidth, charHeight); for (y = 0; y < charHeight; y++) { for (x = 0; x < charWidth; x++) { /* * XXX The algorithm used to suck across the font ensures * that each glyph begins on a byte boundary. In theory * this would make it convienent to copy the glyph into * a byte oriented bitmap. We actually use the XGetPixel * function to extract each pixel from the image which is * not that efficient. We could either do tighter packing * in the pixmap or more efficient extraction from the * image. Oh well. */ if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) { DEBUG_GLYPH("x"); bitmapData[y * spanLength + x / 8] |= (1 << (x & 7)); } else { DEBUG_GLYPH(" "); } } DEBUG_GLYPH("\n"); } myfontinfo->glyph[thisglyph].width = charWidth; myfontinfo->glyph[thisglyph].height = charHeight; myfontinfo->glyph[thisglyph].xoffset = -charinfo->lbearing; myfontinfo->glyph[thisglyph].yoffset = charinfo->descent; myfontinfo->glyph[thisglyph].advance = charinfo->width; myfontinfo->glyph[thisglyph].bitmap = bitmapData; } XDestroyImage(image); numToGrab = 0; /* do we need to clear the offscreen pixmap to get more? */ if (i < numchars - 1) { XSetForeground(dpy, xgc, 0); XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height); XSetForeground(dpy, xgc, 1); } } } XFreeGC(dpy, xgc); XFreePixmap(dpy, offscreen); return myfontinfo; FreeFontAndReturn: XDestroyImage(image); XFreeGC(dpy, xgc); XFreePixmap(dpy, offscreen); for (j = i - 1; j >= 0; j--) { if (myfontinfo->glyph[j].bitmap) free(myfontinfo->glyph[j].bitmap); } free(myfontinfo); return NULL; }
void XUtf8DrawString( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes) { int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ XChar2b buf[128]; /* drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int i; /* current byte in the XChar2b buffer */ int first; /* first valid font index */ int last_fnum; /* font index of the previous char */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ nb_font = font_set->nb_font; if (nb_font < 1) { /* there is no font in the font_set :-( */ return; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; i = 0; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return; } first = fnum; last_fnum = fnum; while (num_bytes > 0) { int ulen; /* byte length of the UTF-8 char */ unsigned int ucs; /* Unicode value of the UTF-8 char */ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ if (i > 120) { /*** draw the buffer **/ XSetFont(display, gc, fonts[fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); x += XTextWidth16(fonts[fnum], buf, i); i = 0; } ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs); if (ulen < 1) ulen = 1; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) ucs = no_spc; /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || (ucs >= ranges[fnum * 2] && ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /** the char is not valid in all encodings -> * draw it using the first font :-( **/ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } if (last_fnum != fnum || no_spc) { XSetFont(display, gc, fonts[last_fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); x += XTextWidth16(fonts[last_fnum], buf, i); i = 0; (*buf).byte1 = glyph[0]; (*buf).byte2 = glyph[1]; if (no_spc) { x -= XTextWidth16(fonts[fnum], buf, 1); } } else { (*(buf + i)).byte1 = glyph[0]; (*(buf + i)).byte2 = glyph[1]; } last_fnum = fnum; i++; string += ulen; num_bytes -= ulen; } XSetFont(display, gc, fonts[fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); }