Skip to content

Commit

Permalink
add GE 16 = glyph API support
Browse files Browse the repository at this point in the history
  • Loading branch information
s-u committed Jul 20, 2024
1 parent e8329cc commit bf3f1a9
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/cairogd.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,12 @@ Rboolean Rcairo_new_device_driver(NewDevDesc *dd, const char *type, int conn, co
#endif

#if R_GE_version >= 13
dd->deviceVersion = R_GE_definitions;
dd->deviceVersion = R_GE_definitions;
#endif
#if R_GE_version >= 16
/* FIXME: we don't actually implement 14 and 15 */
dd->deviceVersion = R_GE_glyphs;
#endif

dd->deviceSpecific = (void *) xd;

#ifdef JGD_DEBUG
Expand Down
91 changes: 91 additions & 0 deletions src/cairotalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ static void CairoGD_releaseClipPath(SEXP ref, pDevDesc dd);
static SEXP CairoGD_setMask(SEXP path, SEXP ref, pDevDesc dd);
static void CairoGD_releaseMask(SEXP ref, pDevDesc dd);

#if R_GE_version >= 16
/* this is required since 14 otherwise R segfaults */
static SEXP CairoGD_Capabilities(SEXP capabilities);

/* GE 16 glyph API */
static void CairoGD_Glyph(int n, int *glyphs, double *x, double *y,
SEXP font, double size,
int col, double rot, pDevDesc dd);
#endif

/* fake mbcs support for old R versions */
#if R_GE_version < 4
#define mbcslocale 0
Expand Down Expand Up @@ -1419,6 +1429,82 @@ static void CairoGD_TextNative(double x, double y, constxt char *str,
CairoGD_TextEnc(x, y, str, rot, hadj, gc, dd, "");
}

#if R_GE_version >= 16
static SEXP CairoGD_Capabilities(SEXP capabilities) {
SEXP glyphs = PROTECT(ScalarInteger(1));
SET_VECTOR_ELT(capabilities, R_GE_capability_glyphs, glyphs);
UNPROTECT(1);
return capabilities;
}

static void CairoGD_Glyph(int n, int *glyphs, double *x, double *y,
SEXP font, double size,
int col, double rot, pDevDesc dd) {
CairoGDDesc *xd = (CairoGDDesc *) dd->deviceSpecific;
cairo_t *cc;

if (!xd || !xd->cb) return;

cc = xd->cb->cc;

/* font info is explicit so we don't use our regular cache and mapping */
double weight = R_GE_glyphFontWeight(font);
int style = R_GE_glyphFontStyle(font);
int wt = (weight > 400) ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL;
int sl = (style == R_GE_text_style_normal) ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC;

#ifdef JGD_DEBUG
Rprintf("INFO: Glyph(n=%d), fontfile='%s', index=%d, weight=%f, style=%d, col=%x, rot=%f\n",
n, R_GE_glyphFontFile(font) ? R_GE_glyphFontFile(font) : "<NULL>",
R_GE_glyphFontIndex(font), weight, style, col, rot);
#endif

cairo_font_face_t *cairo_face = NULL;
#if USE_CAIRO_FT
FcPattern *pattern = FcPatternBuild(NULL,
FC_FILE, FcTypeString,
R_GE_glyphFontFile(font),
FC_INDEX, FcTypeInteger,
R_GE_glyphFontIndex(font),
NULL);
cairo_face = cairo_ft_font_face_create_for_pattern(pattern);
FcPatternDestroy(pattern);
#endif
if (cairo_face &&
cairo_font_face_status(cairo_face) == CAIRO_STATUS_SUCCESS) {
cairo_set_font_face(cc, cairo_face);
} else /* fall back - hopefully not needed */
cairo_select_font_face(cc, R_GE_glyphFontFamily(font), sl, wt);

/* FIXME: not sure if we need to scale - Quartz uses 72 baseline - check sizes */
cairo_set_font_size (cc, size / (72*dd->ipr[0]));

Rcairo_set_color(cc, col);

int i = 0;
while (i < n) {
if (rot != 0.0) {
cairo_save(cc);
cairo_translate(cc, x[i], y[i]);
cairo_rotate(cc, -rot/180.*M_PI);
cairo_translate(cc, -x[i], -y[i]);
}

cairo_glyph_t cairoGlyph;
cairoGlyph.index = glyphs[i];
cairoGlyph.x = x[i];
cairoGlyph.y = y[i];

cairo_show_glyphs(cc, &cairoGlyph, 1);
/* for path ops use cairo_glyph_path(cc, &cairoGlyph, 1); instead */

if (rot != 0.0)
cairo_restore(cc);
i++;
}
}
#endif

static SEXP CairoGD_setPattern(SEXP pattern, pDevDesc dd) {
return R_NilValue;
}
Expand Down Expand Up @@ -1475,6 +1561,11 @@ void Rcairo_setup_gd_functions(NewDevDesc *dd) {
dd->releaseClipPath = CairoGD_releaseClipPath;
dd->setMask = CairoGD_setMask;
dd->releaseMask = CairoGD_releaseMask;
#if R_GE_version >= 16
/* NOTE: caps must be set from 14 on or else R segfaults */
dd->capabilities = CairoGD_Capabilities;
dd->glyph = CairoGD_Glyph;
#endif
#endif
#endif
#endif
Expand Down

0 comments on commit bf3f1a9

Please sign in to comment.