+static MRealizedFont *gd_font_open (MFrame *, MFont *, MFont *,
+ MRealizedFont *);
+static void gd_render (MDrawWindow, int, int, MGlyphString *,
+ MGlyph *, MGlyph *, int, MDrawRegion);
+
+static MFontDriver gd_font_driver =
+ { NULL, gd_font_open, NULL, NULL, NULL, gd_render, NULL };
+
+static MRealizedFont *
+gd_font_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
+{
+ double size = font->size ? font->size : spec->size;
+ int reg = spec->property[MFONT_REGISTRY];
+ MRealizedFont *new;
+
+ if (rfont)
+ {
+ MRealizedFont *save = NULL;
+
+ for (; rfont; rfont = rfont->next)
+ if (rfont->font == font
+ && (rfont->font->size ? rfont->font->size == size
+ : rfont->spec.size == size)
+ && rfont->spec.property[MFONT_REGISTRY] == reg)
+ {
+ if (! save)
+ save = rfont;
+ if (rfont->driver == &gd_font_driver)
+ return rfont;
+ }
+ rfont = save;
+ }
+ rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
+ if (! rfont)
+ return NULL;
+ M17N_OBJECT_REF (rfont->info);
+ MSTRUCT_CALLOC (new, MERROR_GD);
+ *new = *rfont;
+ new->driver = &gd_font_driver;
+ new->next = MPLIST_VAL (frame->realized_font_list);
+ MPLIST_VAL (frame->realized_font_list) = new;
+ return new;
+}
+
+static void
+gd_render (MDrawWindow win, int x, int y,
+ MGlyphString *gstring, MGlyph *from, MGlyph *to,
+ int reverse, MDrawRegion region)
+{
+ gdImagePtr img = (gdImagePtr) win;
+ FT_Face ft_face;
+ MRealizedFace *rface = from->rface;
+ FT_Int32 load_flags = FT_LOAD_RENDER;
+ int i, j;
+ int color, pixel;
+ int r, g, b;
+
+ if (from == to)
+ return;
+
+ /* It is assured that the all glyphs in the current range use the
+ same realized face. */
+ ft_face = rface->rfont->fontp;
+ color = ((int *) rface->info)[reverse ? COLOR_INVERSE : COLOR_NORMAL];
+ pixel = RESOLVE_COLOR (img, color);
+
+ if (gstring->anti_alias)
+ r = color >> 16, g = (color >> 8) & 0xFF, b = color & 0xFF;
+ else
+ {
+#ifdef FT_LOAD_TARGET_MONO
+ load_flags |= FT_LOAD_TARGET_MONO;
+#else
+ load_flags |= FT_LOAD_MONOCHROME;
+#endif
+ }
+
+ for (; from < to; x += from++->width)
+ {
+ unsigned char *bmp;
+ int xoff, yoff;
+ int width, pitch;
+
+ FT_Load_Glyph (ft_face, (FT_UInt) from->code, load_flags);
+ yoff = y - ft_face->glyph->bitmap_top + from->yoff;
+ bmp = ft_face->glyph->bitmap.buffer;
+ width = ft_face->glyph->bitmap.width;
+ pitch = ft_face->glyph->bitmap.pitch;
+ if (! gstring->anti_alias)
+ pitch *= 8;
+ if (width > pitch)
+ width = pitch;
+
+ if (gstring->anti_alias)
+ for (i = 0; i < ft_face->glyph->bitmap.rows;
+ i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
+ {
+ xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+ for (j = 0; j < width; j++, xoff++)
+ if (bmp[j] > 0)
+ {
+ int pixel1 = pixel;
+#if HAVE_GD > 1
+ int alpha = gdAlphaTransparent * (255 - bmp[j]) / 255;
+
+ if (alpha > 0)
+ pixel1 = gdImageColorResolveAlpha (img, r, g, b, alpha);
+#else
+ int f = bmp[j] >> 5;
+
+ if (f < 7)
+ {
+ int r1, g1, b1, color1;
+
+ pixel1 = gdImageGetPixel (img, xoff, yoff);
+ r1 = gdImageRed (img, pixel1);
+ g1 = gdImageGreen (img, pixel1);
+ b1 = gdImageBlue (img, pixel1);
+ color1 = ((((r * f + r1 * (7 - f)) / 7) << 16)
+ | (((g * f + g1 * (7 - f)) / 7) << 8)
+ | ((b * f + b1 * (7 - f)) / 7));
+ pixel1 = RESOLVE_COLOR (img, color1);
+ }
+#endif
+ gdImageSetPixel (img, xoff, yoff, pixel1);
+ }
+ }
+ else
+ for (i = 0; i < ft_face->glyph->bitmap.rows;
+ i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
+ {
+ xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+ for (j = 0; j < width; j++, xoff++)
+ if (bmp[j / 8] & (1 << (7 - (j % 8))))
+ gdImageSetPixel (img, xoff, yoff, pixel);
+ }
+ }
+}