Handle text drawing in windows with alpha buffers properly. Try to find good visuals before resorting to the default visual.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@18721 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Alexander Malmberg 2004-02-29 20:45:05 +00:00
parent 180b1ec31a
commit 88ebd73c93
4 changed files with 478 additions and 38 deletions

View file

@ -1,3 +1,14 @@
2004-02-29 21:42 Alexander Malmberg <alexander@malmberg.org>
* Source/art/ftfont.h, Source/art/ftfont.m: Add
-drawGlyphs::at::to::::::alpha::color::::transform:drawinfo: method.
* Source/art/ARTContext.m (-GSShowGlyphs::): Use it if the
destination window has an alpha buffer.
(-initWithContextInfo:): Try to find a DirectColor or TrueColor
visual before falling back on the default visual.
2004-02-28 Adam Fedor <fedor@gnu.org>
* Version 0.9.2

View file

@ -331,13 +331,27 @@ very expensive
x = p.x;
y = wi->sy - p.y;
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
drawinfo: &DI];
if (wi->has_alpha)
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
alpha: wi->alpha + clip_x0 + clip_y0 * wi->sx : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
drawinfo: &DI];
}
else
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
drawinfo: &DI];
}
UPDATE_UNBUFFERED
}
@ -638,45 +652,78 @@ very expensive
- (id) initWithContextInfo: (NSDictionary *)info
{
NSString *contextType;
contextType = [info objectForKey:
NSGraphicsContextRepresentationFormatAttributeName];
NSString *contextType;
contextType = [info objectForKey:
NSGraphicsContextRepresentationFormatAttributeName];
self = [super initWithContextInfo: info];
if (contextType)
{
/* Most likely this is a PS or PDF context, so just return what
super gave us */
return self;
}
self = [super initWithContextInfo: info];
if (contextType)
{
/* Most likely this is a PS or PDF context, so just return what
super gave us
TODO: figure out if this comment still applies
*/
return self;
}
/* Create a default gstate */
gstate = [[ARTGState allocWithZone: [self zone]] initWithDrawContext: self];
[gstate DPSsetalpha: 1.0];
[gstate DPSsetlinewidth: 1.0];
/* Create a default gstate */
gstate = [[ARTGState allocWithZone: [self zone]] initWithDrawContext: self];
[gstate DPSsetalpha: 1.0];
[gstate DPSsetlinewidth: 1.0];
#ifdef RDS
{
RDSServer *s=(RDSServer *)server;
int bpp;
int red_mask,green_mask,blue_mask;
[s getPixelFormat: &bpp masks: &red_mask : &green_mask : &blue_mask];
artcontext_setup_draw_info(&DI,red_mask,green_mask,blue_mask,bpp);
}
{
RDSServer *s=(RDSServer *)server;
int bpp;
int red_mask, green_mask, blue_mask;
[s getPixelFormat: &bpp masks: &red_mask : &green_mask : &blue_mask];
artcontext_setup_draw_info(&DI, red_mask, green_mask, blue_mask, bpp);
}
#else
{
Display *d=[(XGServer *)server xDisplay];
Visual *v=DefaultVisual(d,DefaultScreen(d));
int bpp=DefaultDepth(d,DefaultScreen(d));
XImage *i=XCreateImage(d,v,bpp,ZPixmap,0,NULL,8,8,8,0);
bpp=i->bits_per_pixel;
XDestroyImage(i);
{
Display *d = [(XGServer *)server xDisplay];
int bpp;
Visual *visual;
XVisualInfo template;
XVisualInfo *visualInfo;
int numMatches;
XImage *i;
artcontext_setup_draw_info(&DI,v->red_mask,v->green_mask,v->blue_mask,bpp);
}
/*
We need a visual that we can generate pixel values for by ourselves.
Thus, we try to find a DirectColor or TrueColor visual. If that fails,
we use the default visual and hope that it's usable.
*/
template.class=DirectColor;
visualInfo=XGetVisualInfo(d, VisualClassMask, &template, &numMatches);
if (!visualInfo)
{
template.class=TrueColor;
visualInfo=XGetVisualInfo(d, VisualClassMask, &template, &numMatches);
}
if (visualInfo)
{
visual = visualInfo->visual;
bpp = visualInfo->depth;
XFree(visualInfo);
}
else
{
visual = DefaultVisual(d, DefaultScreen(d));
bpp = DefaultDepth(d, DefaultScreen(d));
}
i = XCreateImage(d, visual, bpp, ZPixmap, 0, NULL, 8, 8, 8, 0);
bpp = i->bits_per_pixel;
XDestroyImage(i);
/* Only returns if the visual was usable. */
artcontext_setup_draw_info(&DI, visual->red_mask, visual->green_mask,
visual->blue_mask, bpp);
}
#endif
return self;
return self;
}

View file

@ -45,6 +45,16 @@
transform: (NSAffineTransform *)transform
drawinfo: (struct draw_info_s *)di;
-(void) drawGlyphs: (const NSGlyph *)glyphs : (int)length
at: (int)x : (int)y
to: (int)x0 : (int)y0 : (int)x1 : (int)y1
: (unsigned char *)buf : (int)bpl
alpha: (unsigned char *)abuf : (int)abpl
color: (unsigned char)r : (unsigned char)g : (unsigned char)b
: (unsigned char)alpha
transform: (NSAffineTransform *)transform
drawinfo: (struct draw_info_s *)di;
/* TODO: see if this is really necessary */
-(void) drawString: (const char *)s
at: (int)x:(int)y

View file

@ -1688,6 +1688,378 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_
}
}
-(void) drawGlyphs: (const NSGlyph *)glyphs : (int)length
at: (int)x : (int)y
to: (int)x0 : (int)y0 : (int)x1 : (int)y1
: (unsigned char *)buf : (int)bpl
alpha: (unsigned char *)abuf : (int)abpl
color: (unsigned char)r : (unsigned char)g : (unsigned char)b
: (unsigned char)alpha
transform: (NSAffineTransform *)transform
drawinfo: (struct draw_info_s *)di
{
unsigned int glyph;
int use_sbit;
FTC_SBit sbit;
#ifdef FT212_STUFF
FTC_ImageDesc cur;
#else
FTC_ImageTypeRec cur;
#endif
FT_Matrix ftmatrix;
FT_Vector ftdelta;
FT_Error error;
if (!alpha)
return;
/* TODO: if we had guaranteed upper bounds on glyph image size we
could do some basic clipping here */
x1 -= x0;
y1 -= y0;
x -= x0;
y -= y0;
/* NSLog(@"[%@ draw using matrix: (%g %g %g %g %g %g)] transform=%@\n",
self,
matrix[0], matrix[1], matrix[2],
matrix[3], matrix[4], matrix[5],
transform
);*/
cur = imgd;
{
float xx, xy, yx, yy;
xx = matrix[0] * transform->matrix.m11 + matrix[1] * transform->matrix.m21;
yx = matrix[0] * transform->matrix.m12 + matrix[1] * transform->matrix.m22;
xy = matrix[2] * transform->matrix.m11 + matrix[3] * transform->matrix.m21;
yy = matrix[2] * transform->matrix.m12 + matrix[3] * transform->matrix.m22;
/* If we're drawing 'normal' text (unscaled, unrotated, reasonable
size), we can and should use the sbit cache for screen fonts. */
if (screenFont &&
fabs(xx - ((int)xx)) < 0.01 && fabs(yy - ((int)yy)) < 0.01 &&
fabs(xy) < 0.01 && fabs(yx) < 0.01 &&
xx < 72 && yy < 72 && xx > 0.5 && yy > 0.5)
{
use_sbit = 1;
cur.font.pix_width = xx;
cur.font.pix_height = yy;
if (xx == yy && xx < 16 && xx >= 8)
{
int rh = face_info->render_hints_hack;
if (rh & 0x10000)
{
#ifdef FT212_STUFF
cur.type = ftc_image_grays;
#else
cur.flags = FT_LOAD_TARGET_NORMAL;
#endif
rh = (rh >> 8) & 0xff;
}
else
{
#ifdef FT212_STUFF
cur.type = ftc_image_mono;
#else
cur.flags = FT_LOAD_TARGET_MONO;
#endif
rh = rh & 0xff;
}
if (rh & 1)
#ifdef FT212_STUFF
cur.type |= ftc_image_flag_autohinted;
#else
cur.flags |= FT_LOAD_FORCE_AUTOHINT;
#endif
if (!(rh & 2))
#ifdef FT212_STUFF
cur.type |= ftc_image_flag_unhinted;
#else
cur.flags |= FT_LOAD_NO_HINTING;
#endif
}
else if (xx < 8)
#ifdef FT212_STUFF
cur.type = ftc_image_grays | ftc_image_flag_unhinted;
#else
cur.flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
#endif
else
#ifdef FT212_STUFF
cur.type = ftc_image_grays;
#else
cur.flags = FT_LOAD_TARGET_NORMAL;
#endif
}
else
{
float f;
use_sbit = 0;
f = fabs(xx * yy - xy * yx);
if (f > 1)
f = sqrt(f);
else
f = 1.0;
f = (int)f;
cur.font.pix_width = cur.font.pix_height = f;
ftmatrix.xx = xx / f * 65536.0;
ftmatrix.xy = xy / f * 65536.0;
ftmatrix.yx = yx / f * 65536.0;
ftmatrix.yy = yy / f * 65536.0;
ftdelta.x = ftdelta.y = 0;
}
}
/* NSLog(@"drawString: '%s' at: %i:%i to: %i:%i:%i:%i:%p\n",
s, x, y, x0, y0, x1, y1, buf);*/
for (; length; length--, glyphs++)
{
glyph = *glyphs - 1;
if (use_sbit)
{
if ((error = FTC_SBitCache_Lookup(ftc_sbitcache, &cur, glyph, &sbit, NULL)))
{
if (glyph != 0xffffffff)
NSLog(@"FTC_SBitCache_Lookup() failed with error %08x (%08x, %08x, %ix%i, %08x)\n",
error, glyph, cur.font.face_id, cur.font.pix_width, cur.font.pix_height,
#ifdef FT212_STUFF
cur.type
#else
cur.flags
#endif
);
continue;
}
if (!sbit->buffer)
{
x += sbit->xadvance;
continue;
}
if (sbit->format == ft_pixel_mode_grays)
{
int gx = x + sbit->left, gy = y - sbit->top;
int sbpl = sbit->pitch;
int sx = sbit->width, sy = sbit->height;
const unsigned char *src = sbit->buffer;
unsigned char *dst = buf;
unsigned char *adst = abuf;
if (gy < 0)
{
sy += gy;
src -= sbpl * gy;
gy = 0;
}
else if (gy > 0)
{
dst += bpl * gy;
adst += abpl * gy;
}
sy += gy;
if (sy > y1)
sy = y1;
if (gx < 0)
{
sx += gx;
src -= gx;
gx = 0;
}
else if (gx > 0)
{
dst += DI.bytes_per_pixel * gx;
adst += gx;
}
sx += gx;
if (sx > x1)
sx = x1;
sx -= gx;
if (sx > 0)
{
for (; gy < sy; gy++, src += sbpl, dst += bpl, adst += abpl)
RENDER_BLIT_ALPHA_A(dst, adst, src, r, g, b, alpha, sx);
}
}
else if (sbit->format == ft_pixel_mode_mono)
{
int gx = x + sbit->left, gy = y - sbit->top;
int sbpl = sbit->pitch;
int sx = sbit->width, sy = sbit->height;
const unsigned char *src = sbit->buffer;
unsigned char *dst = buf;
unsigned char *adst = abuf;
int src_ofs = 0;
if (gy < 0)
{
sy += gy;
src -= sbpl * gy;
gy = 0;
}
else if (gy > 0)
{
dst += bpl * gy;
adst += abpl * gy;
}
sy += gy;
if (sy > y1)
sy = y1;
if (gx < 0)
{
sx += gx;
src -= gx / 8;
src_ofs = (-gx) & 7;
gx = 0;
}
else if (gx > 0)
{
dst += DI.bytes_per_pixel * gx;
adst += gx;
}
sx += gx;
if (sx > x1)
sx = x1;
sx -= gx;
if (sx > 0)
{
for (; gy < sy; gy++, src += sbpl, dst += bpl, adst += bpl)
RENDER_BLIT_MONO_A(dst, adst, src, src_ofs, r, g, b, alpha, sx);
}
}
else
{
NSLog(@"unhandled font bitmap format %i", sbit->format);
}
x += sbit->xadvance;
}
else
{
FT_Face face;
FT_Glyph gl;
FT_BitmapGlyph gb;
if ((error=FTC_Manager_Lookup_Size(ftc_manager, &cur.font, &face, 0)))
{
NSLog(@"FTC_Manager_Lookup_Size() failed with error %08x\n",error);
continue;
}
/* TODO: for rotations of 90, 180, 270, and integer
scales hinting might still be a good idea. */
if ((error=FT_Load_Glyph(face, glyph, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)))
{
NSLog(@"FT_Load_Glyph() failed with error %08x\n",error);
continue;
}
if ((error=FT_Get_Glyph(face->glyph, &gl)))
{
NSLog(@"FT_Get_Glyph() failed with error %08x\n",error);
continue;
}
if ((error=FT_Glyph_Transform(gl, &ftmatrix, &ftdelta)))
{
NSLog(@"FT_Glyph_Transform() failed with error %08x\n",error);
continue;
}
if ((error=FT_Glyph_To_Bitmap(&gl, ft_render_mode_normal, 0, 1)))
{
NSLog(@"FT_Glyph_To_Bitmap() failed with error %08x\n",error);
FT_Done_Glyph(gl);
continue;
}
gb = (FT_BitmapGlyph)gl;
if (gb->bitmap.pixel_mode == ft_pixel_mode_grays)
{
int gx = x + gb->left, gy = y - gb->top;
int sbpl = gb->bitmap.pitch;
int sx = gb->bitmap.width, sy = gb->bitmap.rows;
const unsigned char *src = gb->bitmap.buffer;
unsigned char *dst = buf;
unsigned char *adst = abuf;
if (gy < 0)
{
sy += gy;
src -= sbpl * gy;
gy = 0;
}
else if (gy > 0)
{
dst += bpl * gy;
adst += abpl * gy;
}
sy += gy;
if (sy > y1)
sy = y1;
if (gx < 0)
{
sx += gx;
src -= gx;
gx = 0;
}
else if (gx > 0)
{
dst += DI.bytes_per_pixel * gx;
adst += gx;
}
sx += gx;
if (sx > x1)
sx = x1;
sx -= gx;
if (sx > 0)
{
for (; gy < sy; gy++, src += sbpl, dst += bpl, adst += bpl)
RENDER_BLIT_ALPHA_A(dst, adst, src, r, g, b, alpha, sx);
}
}
/* TODO: will this case ever appear? */
/* else if (gb->bitmap.pixel_mode==ft_pixel_mode_mono)*/
else
{
NSLog(@"unhandled font bitmap format %i", gb->bitmap.pixel_mode);
}
ftdelta.x += gl->advance.x >> 10;
ftdelta.y += gl->advance.y >> 10;
FT_Done_Glyph(gl);
}
}
}
-(BOOL) glyphIsEncoded: (NSGlyph)glyph
{