Skip to content

Commit

Permalink
fix underlines on GDI+; text_out with alpha/color uses shaping
Browse files Browse the repository at this point in the history
  • Loading branch information
dk committed Nov 23, 2024
1 parent 35051a2 commit f3a9664
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 186 deletions.
45 changes: 45 additions & 0 deletions api/utf8.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,51 @@ prima_utf8_uvchr_end(const char * text, const char * end, unsigned int *charlen)
return uv;
}

uint32_t*
prima_string2uint32( register const char * src, unsigned int dlen, Bool is_utf8, unsigned int * size)
{
uint32_t *ret;

*size = is_utf8 ? prima_utf8_length(src, dlen) : dlen;
if (!(ret = ( uint32_t*) malloc(sizeof(uint32_t) * (*size)))) {
warn("Not enough memory: %ld bytes", (unsigned long int)(sizeof(uint32_t) * (*size)));
return NULL;
}

if (is_utf8) {
uint32_t *dst = ret;
while ( dlen > 0 && dst - ret < *size) {
UV uv;
unsigned int charlen;
uv = prima_utf8_uvchr(src, dlen, &charlen);
if ( uv > 0x10FFFF ) uv = 0x10FFFF;
*(dst++) = uv;
if ( charlen == 0 ) break;
src += charlen;
dlen -= charlen;
}
*size = dst - ret;
} else {
register int i = *size;
register uint32_t *dst = ret;
while (i-- > 0) *(dst++) = *((unsigned char*) src++);
}

return ret;
}

uint32_t*
prima_sv2uint32( SV * text, unsigned int * size, unsigned int * flags)
{
STRLEN dlen;
const char * src;

src = (const char*) SvPV(text, dlen);
if (prima_is_utf8_sv(text))
*flags |= toUTF8;
return prima_string2uint32( src, dlen, *flags & toUTF8, size);
}

#ifdef __cplusplus
}
#endif
42 changes: 1 addition & 41 deletions class/Drawable/shape.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,46 +23,6 @@ warn_malloc(ssize_t size)
return ret;
}

static uint32_t*
sv2uint32( SV * text, unsigned int * size, unsigned int * flags)
{
STRLEN dlen;
register char * src;
uint32_t *ret;

src = SvPV(text, dlen);
if (prima_is_utf8_sv(text)) {
*flags |= toUTF8;
*size = prima_utf8_length(src, dlen);
} else {
*size = dlen;
}

if (!(ret = ( uint32_t*) warn_malloc(sizeof(uint32_t) * (*size))))
return NULL;

if (*flags & toUTF8 ) {
uint32_t *dst = ret;
while ( dlen > 0 && dst - ret < *size) {
UV uv;
unsigned int charlen;
uv = prima_utf8_uvchr(src, dlen, &charlen);
if ( uv > 0x10FFFF ) uv = 0x10FFFF;
*(dst++) = uv;
if ( charlen == 0 ) break;
src += charlen;
dlen -= charlen;
}
*size = dst - ret;
} else {
register int i = *size;
register uint32_t *dst = ret;
while (i-- > 0) *(dst++) = *((unsigned char*) src++);
}

return ret;
}

/*
Iterator for individual shaper runs. Each run has same direction
and its indexes are increasing/decreasing monotonically. The latter is
Expand Down Expand Up @@ -631,7 +591,7 @@ Drawable_text_shape( Handle self, SV * text_sv, HV * profile)
}

/* allocate buffers */
if (!(t.text = sv2uint32(text_sv, &t.len, &t.flags)))
if (!(t.text = prima_sv2uint32(text_sv, &t.len, &t.flags)))
goto EXIT;
if ( replace_tabs >= 0 ) {
int i;
Expand Down
3 changes: 1 addition & 2 deletions class/Drawable/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ Drawable_get_text_width( Handle self, SV * text, int flags, int from, int len)
if (t.advances)
return Drawable_get_glyphs_width(self, &t, flags & toAddOverhangs);
dmENTER(0);
res = apc_gp_get_glyphs_width( self, &t);
res = apc_gp_get_glyphs_width( self, &t, flags);
dmLEAVE;
} else {
SV * ret;
Expand Down Expand Up @@ -335,7 +335,6 @@ Drawable_get_glyphs_box( Handle self, PGlyphsOutRec t, Point * pt)
SaveFont savefont;
FontABC *abc;

t-> flags = 0;
text_out_baseline = ( my-> textOutBaseline == Drawable_textOutBaseline) ?
apc_gp_get_text_out_baseline(self) :
my-> get_textOutBaseline(self);
Expand Down
10 changes: 8 additions & 2 deletions include/apricot.h
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,12 @@ list_index_of( PList self, Handle item);
extern int
prima_utf8_length( const char * utf8, int length);

extern uint32_t*
prima_sv2uint32( SV * text, unsigned int * size, unsigned int * flags);

extern uint32_t*
prima_string2uint32( const char * text, unsigned int dlen, Bool is_utf8, unsigned int * size);

extern Bool
prima_is_utf8_sv( SV * sv);

Expand Down Expand Up @@ -4068,7 +4074,7 @@ typedef Bool TextShapeFunc( Handle self, PTextShapeRec rec);
typedef TextShapeFunc *PTextShapeFunc;

typedef struct {
unsigned int len, flags, text_len;
unsigned int len, text_len;
uint16_t *glyphs, *indexes, *advances;
int16_t *positions;
uint16_t *fonts;
Expand Down Expand Up @@ -4130,7 +4136,7 @@ extern Point*
apc_gp_get_glyphs_box( Handle self, PGlyphsOutRec text);

extern int
apc_gp_get_glyphs_width( Handle self, PGlyphsOutRec text);
apc_gp_get_glyphs_width( Handle self, PGlyphsOutRec text, int flags);

extern ApiHandle
apc_gp_get_handle( Handle self);
Expand Down
4 changes: 2 additions & 2 deletions include/unix/guts.h
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ prima_xft_get_text_width( PCachedFont self, const char * text, int len,

extern int
prima_xft_get_glyphs_width( Handle self, PCachedFont selfxx, PGlyphsOutRec glyphs,
Point * overhangs);
int flags, Point * overhangs);

extern Point *
prima_xft_get_text_box( Handle self, const char * text, int len, int flags);
Expand Down Expand Up @@ -1896,7 +1896,7 @@ extern int
prima_fq_get_text_width( Handle self, const char * text, int len, int flags, Point * overhangs);

extern int
prima_fq_get_glyphs_width( Handle self, PGlyphsOutRec t, Point * overhangs);
prima_fq_get_glyphs_width( Handle self, PGlyphsOutRec t, Point * overhangs, int flags);

extern Point *
prima_fq_get_text_box( Handle self, const char * text, int len, int flags);
Expand Down
2 changes: 1 addition & 1 deletion include/win32/win32guts.h
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,9 @@ extern Bool text_aa_init( Handle self, HFONT font, Bool use_palette);
extern void text_aa_begin_render( Handle self, Bool use_palette);
extern Bool text_aa_render( Handle self, uint16_t glyph);
extern Bool text_aa_end_render( Handle self, int x, int y, NPoint* delta, ABCFLOAT * abc, int advance, int dx, int dy, Bool use_palette);
extern Bool text_aa_text_out( Handle self, int x, int y, void * text, int len, Bool wide);
extern void text_aa_free_arena(Handle self, Bool for_reuse);
extern Bool text_gp_glyphs_out( Handle self, PGlyphsOutRec t, int x, int y, Bool fixed_pitch);
extern int text_gp_get_glyphs_width( Handle self, PGlyphsOutRec t, int flags);
extern void wchar2char( char * dest, WCHAR * src, int lim);
extern Bool yield( Bool wait_for_event );

Expand Down
8 changes: 4 additions & 4 deletions unix/fontquery.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ prima_fq_get_text_width( Handle self, const char * text, int len, int flags, Poi
}

int
prima_fq_get_glyphs_width( Handle self, PGlyphsOutRec t, Point * overhangs)
prima_fq_get_glyphs_width( Handle self, PGlyphsOutRec t, int flags, Point * overhangs)
{
DEFXX;
int i, ret = 0;
Expand All @@ -486,8 +486,8 @@ prima_fq_get_glyphs_width( Handle self, PGlyphsOutRec t, Point * overhangs)
continue;
g = fc.current->glyph;
ret += FT266_to_short(g->advance.x);
if ( (t->flags & toAddOverhangs ) || overhangs) {
UPDATE_OVERHANGS(t->len,t->flags)
if ( (flags & toAddOverhangs ) || overhangs) {
UPDATE_OVERHANGS(t->len,flags)
}
}
return ret;
Expand All @@ -505,7 +505,7 @@ Point *
prima_fq_get_glyphs_box( Handle self, PGlyphsOutRec t)
{
Point ovx;
int w = prima_fq_get_glyphs_width(self, t, &ovx);
int w = prima_fq_get_glyphs_width(self, t, toAddOverhangs, &ovx);
return prima_get_text_box(self, ovx, w);
}

Expand Down
8 changes: 4 additions & 4 deletions unix/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,26 +826,26 @@ apc_gp_get_text_width( Handle self, const char * text, int len, int flags)
}

int
apc_gp_get_glyphs_width( Handle self, PGlyphsOutRec t)
apc_gp_get_glyphs_width( Handle self, PGlyphsOutRec t, int flags)
{
int ret;
if ( t->len > 65535 ) t->len = 65535;

#ifdef USE_FONTQUERY
if ( is_opt(optInFontQuery) ) {
if ( X(self)->font)
return prima_fq_get_glyphs_width( self, t, NULL);
return prima_fq_get_glyphs_width( self, t, flags, NULL);
return 0;
}
#endif

#ifdef USE_XFT
if ( X(self)-> font-> xft)
return prima_xft_get_glyphs_width( self, X(self)-> font, t, NULL);
return prima_xft_get_glyphs_width( self, X(self)-> font, t, flags, NULL);
#endif

SWAP_BYTES(t->glyphs,t->len);
ret = gp_get_text_width( self, (char*) t->glyphs, t->len, toUTF8 );
ret = gp_get_text_width( self, (char*) t->glyphs, t->len, flags | toUTF8 );
SWAP_BYTES(t->glyphs,t->len);
return ret;
}
Expand Down
12 changes: 6 additions & 6 deletions unix/xft.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ prima_xft_get_text_width(
}

int
prima_xft_get_glyphs_width( Handle self, PCachedFont selfxx, PGlyphsOutRec t, Point * overhangs)
prima_xft_get_glyphs_width( Handle self, PCachedFont selfxx, PGlyphsOutRec t, int flags, Point * overhangs)
{
int i, ret = 0;
FontContext fc;
Expand All @@ -622,8 +622,8 @@ prima_xft_get_glyphs_width( Handle self, PCachedFont selfxx, PGlyphsOutRec t, Po
font_context_next(&fc);
XftGlyphExtents( DISP, fc.xft_font, &ft_index, 1, &glyph);
ret += glyph. xOff * fc.width_factor + .5;
if ( (t->flags & toAddOverhangs ) || overhangs) {
UPDATE_OVERHANGS(t->len,t->flags,fc.width_factor)
if ( (flags & toAddOverhangs ) || overhangs) {
UPDATE_OVERHANGS(t->len,flags,fc.width_factor)
}
}
return ret;
Expand All @@ -643,7 +643,7 @@ prima_xft_get_glyphs_box( Handle self, PGlyphsOutRec t)
{
DEFXX;
Point ovx;
int p = prima_xft_get_glyphs_width(self, XX-> font, t, &ovx);
int p = prima_xft_get_glyphs_width(self, XX-> font, t, toAddOverhangs, &ovx);
return prima_get_text_box(self, ovx, p);
}

Expand Down Expand Up @@ -1234,7 +1234,7 @@ prima_xft_glyphs_out( Handle self, PGlyphsOutRec t, int x, int y)
/* emulate rops by blitting the text */
int dx;
TextBlit tb;
dx = prima_xft_get_glyphs_width( self, XX-> font, t, NULL);
dx = prima_xft_get_glyphs_width( self, XX-> font, t, toAddOverhangs, NULL);
if (!open_text_blit(self, x - baseline.x, y - baseline.y, dx, rop, &tb))
goto COPY_PUT;
xft_draw_glyphs(self, XX, &xftcolor,
Expand All @@ -1251,7 +1251,7 @@ prima_xft_glyphs_out( Handle self, PGlyphsOutRec t, int x, int y)
int l;
Point ovx;
t-> flags |= toAddOverhangs;
l = prima_xft_get_glyphs_width( self, XX-> font, t, &ovx);
l = prima_xft_get_glyphs_width( self, XX-> font, t, toAddOverhangs, &ovx);
overstrike(self, x, y, &ovx, l - ovx.x - ovx.y - 1);
}
XFLUSH;
Expand Down
28 changes: 0 additions & 28 deletions win32/gdiplus.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,34 +503,6 @@ aa_fill_palette(Handle self)
return true;
}

Bool
text_aa_text_out( Handle self, int x, int y, void * text, int len, Bool wide)
{
int i;
NPoint delta = { 0, 0 };

if ( !(aa_fill_palette(self) && aa_make_arena(self)))
return false;

for ( i = 0; i < len; i++) {
ABCFLOAT abc;
memset(sys alpha_arena_ptr, 0, sys alpha_arena_size.x * sys alpha_arena_size.y * 4);
if ( wide ) {
if (!GetCharABCWidthsFloatW( sys ps, ((WCHAR*)text)[i], ((WCHAR*)text)[i], &abc)) apiErrRet;
} else {
if (!GetCharABCWidthsFloatA( sys ps, ((char *)text)[i], ((char *)text)[i], &abc)) apiErrRet;
}
if ( wide ) {
if (!TextOutW( sys alpha_arena_dc, sys alpha_arena_size.x/2, sys alpha_arena_size.y/2, ((WCHAR*)text) + i, 1)) apiErrRet;
} else {
if (!TextOutA( sys alpha_arena_dc, sys alpha_arena_size.x/2, sys alpha_arena_size.y/2, ((char *)text) + i, 1)) apiErrRet;
}
if ( !text_aa_end_render(self, x, y, &delta, &abc, -1, 0, 0, true))
return false;
}
return true;
}

Bool
text_aa_init( Handle self, HFONT font, Bool use_palette)
{
Expand Down
Loading

0 comments on commit f3a9664

Please sign in to comment.