Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

888 lines (756 sloc) 25.022 kB
/* $Id: rmstruct.c,v 1.3 2009/02/28 23:50:36 rmagick Exp $ */
/*============================================================================\
| Copyright (C) 2009 by Timothy P. Hunter
| Name: rmstruct.c
| Author: Tim Hunter
| Purpose: Contains various Struct class methods.
\============================================================================*/
#include "rmagick.h"
static const char *ComplianceType_name(ComplianceType *);
static VALUE ComplianceType_new(ComplianceType);
static const char *StretchType_name(StretchType);
static VALUE StretchType_new(StretchType);
static const char *StyleType_name(StyleType);
static VALUE StyleType_new(StyleType);
/*
Extern: Import_AffineMatrix
Purpose: Given a C AffineMatrix, create the equivalent
AffineMatrix object.
Notes: am = Magick::AffineMatrix.new(sx, rx, ry, sy, tx, ty)
*/
VALUE
Import_AffineMatrix(AffineMatrix *affine)
{
VALUE argv[6];
argv[0] = rb_float_new(affine->sx);
argv[1] = rb_float_new(affine->rx);
argv[2] = rb_float_new(affine->ry);
argv[3] = rb_float_new(affine->sy);
argv[4] = rb_float_new(affine->tx);
argv[5] = rb_float_new(affine->ty);
return rb_class_new_instance(6, argv, Class_AffineMatrix);
}
/*
Extern: Export_AffineMatrix
Purpose: Convert a Magick::AffineMatrix object to a AffineMatrix structure.
Notes: If not initialized, the defaults are [sx,rx,ry,sy,tx,ty] = [1,0,0,1,0,0]
*/
void
Export_AffineMatrix(AffineMatrix *am, VALUE st)
{
volatile VALUE values, v;
if (CLASS_OF(st) != Class_AffineMatrix)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(st)));
}
values = rb_funcall(st, rm_ID_values, 0);
v = rb_ary_entry(values, 0);
am->sx = v == Qnil ? 1.0 : NUM2DBL(v);
v = rb_ary_entry(values, 1);
am->rx = v == Qnil ? 0.0 : NUM2DBL(v);
v = rb_ary_entry(values, 2);
am->ry = v == Qnil ? 0.0 : NUM2DBL(v);
v = rb_ary_entry(values, 3);
am->sy = v == Qnil ? 1.0 : NUM2DBL(v);
v = rb_ary_entry(values, 4);
am->tx = v == Qnil ? 0.0 : NUM2DBL(v);
v = rb_ary_entry(values, 5);
am->ty = v == Qnil ? 0.0 : NUM2DBL(v);
}
/*
Extern: ChromaticityInfo_new(pp)
Purpose: Create a Magick::ChromaticityInfo object from a
ChromaticityInfo structure.
*/
VALUE
ChromaticityInfo_new(ChromaticityInfo *ci)
{
volatile VALUE red_primary;
volatile VALUE green_primary;
volatile VALUE blue_primary;
volatile VALUE white_point;
red_primary = Import_PrimaryInfo(&ci->red_primary);
green_primary = Import_PrimaryInfo(&ci->green_primary);
blue_primary = Import_PrimaryInfo(&ci->blue_primary);
white_point = Import_PrimaryInfo(&ci->white_point);
return rb_funcall(Class_Chromaticity, rm_ID_new, 4
, red_primary, green_primary, blue_primary, white_point);
}
/*
Extern: Export_ChromaticityInfo
Purpose: Extract the elements from a Magick::ChromaticityInfo
and store in a ChromaticityInfo structure.
*/
void
Export_ChromaticityInfo(ChromaticityInfo *ci, VALUE chrom)
{
volatile VALUE chrom_members;
volatile VALUE red_primary, green_primary, blue_primary, white_point;
volatile VALUE entry_members, x, y;
ID values_id;
if (CLASS_OF(chrom) != Class_Chromaticity)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(chrom)));
}
values_id = rm_ID_values;
// Get the struct members in an array
chrom_members = rb_funcall(chrom, values_id, 0);
red_primary = rb_ary_entry(chrom_members, 0);
green_primary = rb_ary_entry(chrom_members, 1);
blue_primary = rb_ary_entry(chrom_members, 2);
white_point = rb_ary_entry(chrom_members, 3);
// Get the red_primary PrimaryInfo members in an array
entry_members = rb_funcall(red_primary, values_id, 0);
x = rb_ary_entry(entry_members, 0); // red_primary.x
ci->red_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
y = rb_ary_entry(entry_members, 1); // red_primary.y
ci->red_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
ci->red_primary.z = 0.0;
// Get the green_primary PrimaryInfo members in an array
entry_members = rb_funcall(green_primary, values_id, 0);
x = rb_ary_entry(entry_members, 0); // green_primary.x
ci->green_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
y = rb_ary_entry(entry_members, 1); // green_primary.y
ci->green_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
ci->green_primary.z = 0.0;
// Get the blue_primary PrimaryInfo members in an array
entry_members = rb_funcall(blue_primary, values_id, 0);
x = rb_ary_entry(entry_members, 0); // blue_primary.x
ci->blue_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
y = rb_ary_entry(entry_members, 1); // blue_primary.y
ci->blue_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
ci->blue_primary.z = 0.0;
// Get the white_point PrimaryInfo members in an array
entry_members = rb_funcall(white_point, values_id, 0);
x = rb_ary_entry(entry_members, 0); // white_point.x
ci->white_point.x = x == Qnil ? 0.0 : NUM2DBL(x);
y = rb_ary_entry(entry_members, 1); // white_point.y
ci->white_point.y = y == Qnil ? 0.0 : NUM2DBL(y);
ci->white_point.z = 0.0;
}
/*
Method: Magick::Chromaticity#to_s
Purpose: Create a string representation of a Magick::Chromaticity
*/
VALUE
ChromaticityInfo_to_s(VALUE self)
{
ChromaticityInfo ci;
char buff[200];
Export_ChromaticityInfo(&ci, self);
sprintf(buff, "red_primary=(x=%g,y=%g) "
"green_primary=(x=%g,y=%g) "
"blue_primary=(x=%g,y=%g) "
"white_point=(x=%g,y=%g) ",
ci.red_primary.x, ci.red_primary.y,
ci.green_primary.x, ci.green_primary.y,
ci.blue_primary.x, ci.blue_primary.y,
ci.white_point.x, ci.white_point.y);
return rb_str_new2(buff);
}
/*
External: Import_ColorInfo
Purpose: Convert a ColorInfo structure to a Magick::Color
*/
VALUE
Import_ColorInfo(const ColorInfo *ci)
{
ComplianceType compliance_type;
volatile VALUE name;
volatile VALUE compliance;
volatile VALUE color;
name = rb_str_new2(ci->name);
compliance_type = ci->compliance;
compliance = ComplianceType_new(compliance_type);
color = Pixel_from_MagickPixelPacket(&(ci->color));
return rb_funcall(Class_Color, rm_ID_new, 3
, name, compliance, color);
}
/*
External: Export_ColorInfo
Purpose: Convert a Magick::Color to a ColorInfo structure
*/
void
Export_ColorInfo(ColorInfo *ci, VALUE st)
{
Pixel *pixel;
volatile VALUE members, m;
if (CLASS_OF(st) != Class_Color)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(st)));
}
memset(ci, '\0', sizeof(ColorInfo));
members = rb_funcall(st, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
if (m != Qnil)
{
(void) CloneString((char **)&(ci->name), StringValuePtr(m));
}
m = rb_ary_entry(members, 1);
if (m != Qnil)
{
VALUE_TO_ENUM(m, ci->compliance, ComplianceType);
}
m = rb_ary_entry(members, 2);
if (m != Qnil)
{
Data_Get_Struct(m, Pixel, pixel);
// For >= 6.3.0, ColorInfo.color is a MagickPixelPacket so we have to
// convert the PixelPacket.
GetMagickPixelPacket(NULL, &ci->color);
ci->color.red = (MagickRealType) pixel->red;
ci->color.green = (MagickRealType) pixel->green;
ci->color.blue = (MagickRealType) pixel->blue;
ci->color.opacity = (MagickRealType) OpaqueOpacity;
ci->color.index = (MagickRealType) 0;
}
}
/*
Extern: Color_to_MagickPixelPacket
Purpose: Convert either a String color name or
a Magick::Pixel to a MagickPixelPacket
Notes: The channel values in a MagickPixelPacket are doubles.
*/
void
Color_to_MagickPixelPacket(Image *image, MagickPixelPacket *mpp, VALUE color)
{
PixelPacket pp;
// image can be NULL
GetMagickPixelPacket(image, mpp);
memset(&pp, '\0', sizeof(pp));
Color_to_PixelPacket(&pp, color);
mpp->red = (MagickRealType) pp.red;
mpp->green = (MagickRealType) pp.green;
mpp->blue = (MagickRealType) pp.blue;
mpp->opacity = (MagickRealType) pp.opacity;
}
/*
Static: destroy_ColorInfo
Purpose: free the storage allocated by Export_ColorInfo, above.
*/
static void
destroy_ColorInfo(ColorInfo *ci)
{
magick_free((void*)ci->name);
ci->name = NULL;
}
/*
Method: Color#to_s
Purpose: Return a string representation of a Magick::Color object
*/
VALUE
Color_to_s(VALUE self)
{
ColorInfo ci;
char buff[1024];
Export_ColorInfo(&ci, self);
sprintf(buff, "name=%s, compliance=%s, "
#if (QuantumDepth == 32 || QuantumDepth == 64) && defined(HAVE_TYPE_LONG_DOUBLE)
"color.red=%Lg, color.green=%Lg, color.blue=%Lg, color.opacity=%Lg ",
#else
"color.red=%g, color.green=%g, color.blue=%g, color.opacity=%g ",
#endif
ci.name,
ComplianceType_name(&ci.compliance),
ci.color.red, ci.color.green, ci.color.blue, ci.color.opacity);
destroy_ColorInfo(&ci);
return rb_str_new2(buff);
}
/*
Static: ComplianceType_name
Purpose: Return the string representation of a ComplianceType value
Notes: xMagick will OR multiple compliance types so we have to
arbitrarily pick one name. Set the compliance argument
to the selected value.
*/
static const char *
ComplianceType_name(ComplianceType *c)
{
if ((*c & (SVGCompliance|X11Compliance|XPMCompliance))
== (SVGCompliance|X11Compliance|XPMCompliance))
{
return "AllCompliance";
}
else if (*c & SVGCompliance)
{
*c = SVGCompliance;
return "SVGCompliance";
}
else if (*c & X11Compliance)
{
*c = X11Compliance;
return "X11Compliance";
}
else if (*c & XPMCompliance)
{
*c = XPMCompliance;
return "XPMCompliance";
}
else if (*c == NoCompliance)
{
*c = NoCompliance;
return "NoCompliance";
}
else
{
*c = UndefinedCompliance;
return "UndefinedCompliance";
}
}
/*
* Static: ComplianceType_new
Purpose: construct a ComplianceType enum object for the specified value
*/
static VALUE
ComplianceType_new(ComplianceType compliance)
{
const char *name;
// Turn off undefined bits
compliance &= (SVGCompliance|X11Compliance|XPMCompliance);
name = ComplianceType_name(&compliance);
return rm_enum_new(Class_ComplianceType, ID2SYM(rb_intern(name)), INT2FIX(compliance));
}
/*
External: Import_TypeInfo
Purpose: Convert a TypeInfo structure to a Magick::Font
*/
VALUE
Import_TypeInfo(const TypeInfo *ti)
{
volatile VALUE name, description, family;
volatile VALUE style, stretch, weight;
volatile VALUE encoding, foundry, format;
name = rb_str_new2(ti->name);
family = rb_str_new2(ti->family);
style = StyleType_new(ti->style);
stretch = StretchType_new(ti->stretch);
weight = ULONG2NUM(ti->weight);
description = ti->description ? rb_str_new2(ti->description) : Qnil;
encoding = ti->encoding ? rb_str_new2(ti->encoding) : Qnil;
foundry = ti->foundry ? rb_str_new2(ti->foundry) : Qnil;
format = ti->format ? rb_str_new2(ti->format) : Qnil;
return rb_funcall(Class_Font, rm_ID_new, 9
, name, description, family, style
, stretch, weight, encoding, foundry, format);
}
/*
External: Export_TypeInfo
Purpose: Convert a Magick::Font to a TypeInfo structure
*/
void
Export_TypeInfo(TypeInfo *ti, VALUE st)
{
volatile VALUE members, m;
if (CLASS_OF(st) != Class_Font)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(st)));
}
memset(ti, '\0', sizeof(TypeInfo));
members = rb_funcall(st, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
if (m != Qnil)
{
(void) CloneString((char **)&(ti->name), StringValuePtr(m));
}
m = rb_ary_entry(members, 1);
if (m != Qnil)
{
(void) CloneString((char **)&(ti->description), StringValuePtr(m));
}
m = rb_ary_entry(members, 2);
if (m != Qnil)
{
(void) CloneString((char **)&(ti->family), StringValuePtr(m));
}
m = rb_ary_entry(members, 3); ti->style = m == Qnil ? 0 : FIX2INT(m);
m = rb_ary_entry(members, 4); ti->stretch = m == Qnil ? 0 : FIX2INT(m);
m = rb_ary_entry(members, 5); ti->weight = m == Qnil ? 0 : FIX2INT(m);
m = rb_ary_entry(members, 6);
if (m != Qnil)
(void) CloneString((char **)&(ti->encoding), StringValuePtr(m));
m = rb_ary_entry(members, 7);
if (m != Qnil)
(void) CloneString((char **)&(ti->foundry), StringValuePtr(m));
m = rb_ary_entry(members, 8);
if (m != Qnil)
(void) CloneString((char **)&(ti->format), StringValuePtr(m));
}
/*
Static: destroy_TypeInfo
Purpose: free the storage allocated by Export_TypeInfo, above.
*/
static void
destroy_TypeInfo(TypeInfo *ti)
{
magick_free((void*)ti->name);
ti->name = NULL;
magick_free((void*)ti->description);
ti->description = NULL;
magick_free((void*)ti->family);
ti->family = NULL;
magick_free((void*)ti->encoding);
ti->encoding = NULL;
magick_free((void*)ti->foundry);
ti->foundry = NULL;
magick_free((void*)ti->format);
ti->format = NULL;
}
/*
External: Font_to_s
Purpose: implement the Font#to_s method
*/
VALUE
Font_to_s(VALUE self)
{
TypeInfo ti;
char weight[20];
char buff[1024];
Export_TypeInfo(&ti, self);
switch (ti.weight)
{
case 400:
strcpy(weight, "NormalWeight");
break;
case 700:
strcpy(weight, "BoldWeight");
break;
default:
sprintf(weight, "%lu", ti.weight);
break;
}
sprintf(buff, "name=%s, description=%s, "
"family=%s, style=%s, stretch=%s, weight=%s, "
"encoding=%s, foundry=%s, format=%s",
ti.name,
ti.description,
ti.family,
StyleType_name(ti.style),
StretchType_name(ti.stretch),
weight,
ti.encoding ? ti.encoding : "",
ti.foundry ? ti.foundry : "",
ti.format ? ti.format : "");
destroy_TypeInfo(&ti);
return rb_str_new2(buff);
}
/*
Extern: Import_PointInfo(pp)
Purpose: Create a Magick::Point object from a PointInfo structure.
*/
VALUE
Import_PointInfo(PointInfo *p)
{
return rb_funcall(Class_Point, rm_ID_new, 2
, INT2FIX(p->x), INT2FIX(p->y));
}
/*
Extern: Export_PointInfo
Purpose: Convert a Magick::Point object to a PointInfo structure
*/
void
Export_PointInfo(PointInfo *pi, VALUE sp)
{
volatile VALUE members, m;
if (CLASS_OF(sp) != Class_Point)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(sp)));
}
members = rb_funcall(sp, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
pi->x = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 1);
pi->y = m == Qnil ? 0.0 : NUM2DBL(m);
}
/*
Extern: Import_PrimaryInfo(pp)
Purpose: Create a Magick::PrimaryInfo object from a PrimaryInfo structure.
*/
VALUE
Import_PrimaryInfo(PrimaryInfo *p)
{
return rb_funcall(Class_Primary, rm_ID_new, 3
, INT2FIX(p->x), INT2FIX(p->y), INT2FIX(p->z));
}
/*
Extern: Export_PrimaryInfo
Purpose: Convert a Magick::PrimaryInfo object to a PrimaryInfo structure
*/
void
Export_PrimaryInfo(PrimaryInfo *pi, VALUE sp)
{
volatile VALUE members, m;
if (CLASS_OF(sp) != Class_Primary)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(sp)));
}
members = rb_funcall(sp, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
pi->x = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 1);
pi->y = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 2);
pi->z = m == Qnil ? 0.0 : NUM2DBL(m);
}
/*
Method: Magick::PrimaryInfo#to_s
Purpose: Create a string representation of a Magick::PrimaryInfo
*/
VALUE
PrimaryInfo_to_s(VALUE self)
{
PrimaryInfo pi;
char buff[100];
Export_PrimaryInfo(&pi, self);
sprintf(buff, "x=%g, y=%g, z=%g", pi.x, pi.y, pi.z);
return rb_str_new2(buff);
}
/*
External: Import_RectangleInfo
Purpose: Convert a RectangleInfo structure to a Magick::Rectangle
*/
VALUE
Import_RectangleInfo(RectangleInfo *rect)
{
volatile VALUE width;
volatile VALUE height;
volatile VALUE x, y;
width = UINT2NUM(rect->width);
height = UINT2NUM(rect->height);
x = INT2NUM(rect->x);
y = INT2NUM(rect->y);
return rb_funcall(Class_Rectangle, rm_ID_new, 4
, width, height, x, y);
}
/*
External: Export_RectangleInfo
Purpose: Convert a Magick::Rectangle to a RectangleInfo structure.
*/
void
Export_RectangleInfo(RectangleInfo *rect, VALUE sr)
{
volatile VALUE members, m;
if (CLASS_OF(sr) != Class_Rectangle)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(sr)));
}
members = rb_funcall(sr, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
rect->width = m == Qnil ? 0 : NUM2ULONG(m);
m = rb_ary_entry(members, 1);
rect->height = m == Qnil ? 0 : NUM2ULONG(m);
m = rb_ary_entry(members, 2);
rect->x = m == Qnil ? 0 : NUM2LONG (m);
m = rb_ary_entry(members, 3);
rect->y = m == Qnil ? 0 : NUM2LONG (m);
}
/*
Method: Magick::Rectangle#to_s
Purpose: Create a string representation of a Magick::Rectangle
*/
VALUE
RectangleInfo_to_s(VALUE self)
{
RectangleInfo rect;
char buff[100];
Export_RectangleInfo(&rect, self);
sprintf(buff, "width=%lu, height=%lu, x=%ld, y=%ld"
, rect.width, rect.height, rect.x, rect.y);
return rb_str_new2(buff);
}
/*
External: Import_SegmentInfo
Purpose: Convert a SegmentInfo structure to a Magick::Segment
*/
VALUE
Import_SegmentInfo(SegmentInfo *segment)
{
volatile VALUE x1, y1, x2, y2;
x1 = rb_float_new(segment->x1);
y1 = rb_float_new(segment->y1);
x2 = rb_float_new(segment->x2);
y2 = rb_float_new(segment->y2);
return rb_funcall(Class_Segment, rm_ID_new, 4, x1, y1, x2, y2);
}
/*
External: Export_SegmentInfo
Purpose: Convert a Magick::Segment to a SegmentInfo structure.
*/
void
Export_SegmentInfo(SegmentInfo *segment, VALUE s)
{
volatile VALUE members, m;
if (CLASS_OF(s) != Class_Segment)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(s)));
}
members = rb_funcall(s, rm_ID_values, 0);
m = rb_ary_entry(members, 0);
segment->x1 = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 1);
segment->y1 = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 2);
segment->x2 = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 3);
segment->y2 = m == Qnil ? 0.0 : NUM2DBL(m);
}
/*
Method: Magick::SegmentInfo#to_s
Purpose: Create a string representation of a Magick::Segment
*/
VALUE
SegmentInfo_to_s(VALUE self)
{
SegmentInfo segment;
char buff[100];
Export_SegmentInfo(&segment, self);
sprintf(buff, "x1=%g, y1=%g, x2=%g, y2=%g"
, segment.x1, segment.y1, segment.x2, segment.y2);
return rb_str_new2(buff);
}
/*
Static: StretchType_name
Purpose: Return the string representation of a StretchType value
*/
static const char *
StretchType_name(StretchType stretch)
{
switch (stretch)
{
ENUM_TO_NAME(UndefinedStretch)
ENUM_TO_NAME(NormalStretch)
ENUM_TO_NAME(UltraCondensedStretch)
ENUM_TO_NAME(ExtraCondensedStretch)
ENUM_TO_NAME(CondensedStretch)
ENUM_TO_NAME(SemiCondensedStretch)
ENUM_TO_NAME(SemiExpandedStretch)
ENUM_TO_NAME(ExpandedStretch)
ENUM_TO_NAME(ExtraExpandedStretch)
ENUM_TO_NAME(UltraExpandedStretch)
ENUM_TO_NAME(AnyStretch)
}
return "UndefinedStretch";
}
/*
Static: StretchType_new
Purpose: Construct a StretchType enum for a specified StretchType value
*/
static VALUE
StretchType_new(StretchType stretch)
{
const char *name = StretchType_name(stretch);
return rm_enum_new(Class_StretchType, ID2SYM(rb_intern(name)), INT2FIX(stretch));
}
/*
Static: StyleType_name
Purpose: Return the string representation of a StyleType value
*/
static const char *
StyleType_name(StyleType style)
{
switch (style)
{
ENUM_TO_NAME(UndefinedStyle)
ENUM_TO_NAME(NormalStyle)
ENUM_TO_NAME(ItalicStyle)
ENUM_TO_NAME(ObliqueStyle)
ENUM_TO_NAME(AnyStyle)
}
return "UndefinedStyle";
}
/*
Static: StyleType_new
Purpose: Construct a StyleType enum for a specified StyleType value
*/
static VALUE
StyleType_new(StyleType style)
{
const char *name = StyleType_name(style);
return rm_enum_new(Class_StyleType, ID2SYM(rb_intern(name)), INT2FIX(style));
}
/*
External: Import_TypeMetric
Purpose: Convert a TypeMetric structure to a Magick::TypeMetric
*/
VALUE
Import_TypeMetric(TypeMetric *tm)
{
volatile VALUE pixels_per_em;
volatile VALUE ascent, descent;
volatile VALUE width, height, max_advance;
volatile VALUE bounds, underline_position, underline_thickness;
pixels_per_em = Import_PointInfo(&tm->pixels_per_em);
ascent = rb_float_new(tm->ascent);
descent = rb_float_new(tm->descent);
width = rb_float_new(tm->width);
height = rb_float_new(tm->height);
max_advance = rb_float_new(tm->max_advance);
bounds = Import_SegmentInfo(&tm->bounds);
underline_position = rb_float_new(tm->underline_position);
underline_thickness = rb_float_new(tm->underline_position);
return rb_funcall(Class_TypeMetric, rm_ID_new, 9
, pixels_per_em, ascent, descent, width
, height, max_advance, bounds
, underline_position, underline_thickness);
}
/*
External: Export_TypeMetric
Purpose: Convert a Magick::TypeMetric to a TypeMetric structure.
*/
void
Export_TypeMetric(TypeMetric *tm, VALUE st)
{
volatile VALUE members, m;
volatile VALUE pixels_per_em;
if (CLASS_OF(st) != Class_TypeMetric)
{
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(st)));
}
members = rb_funcall(st, rm_ID_values, 0);
pixels_per_em = rb_ary_entry(members, 0);
Export_PointInfo(&tm->pixels_per_em, pixels_per_em);
m = rb_ary_entry(members, 1);
tm->ascent = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 2);
tm->descent = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 3);
tm->width = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 4);
tm->height = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 5);
tm->max_advance = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 6);
Export_SegmentInfo(&tm->bounds, m);
m = rb_ary_entry(members, 7);
tm->underline_position = m == Qnil ? 0.0 : NUM2DBL(m);
m = rb_ary_entry(members, 8);
tm->underline_thickness = m == Qnil ? 0.0 : NUM2DBL(m);
}
/*
Method: Magick::TypeMetric#to_s
Purpose: Create a string representation of a Magick::TypeMetric
*/
VALUE
TypeMetric_to_s(VALUE self)
{
TypeMetric tm;
char buff[200];
Export_TypeMetric(&tm, self);
sprintf(buff, "pixels_per_em=(x=%g,y=%g) "
"ascent=%g descent=%g width=%g height=%g max_advance=%g "
"bounds.x1=%g bounds.y1=%g bounds.x2=%g bounds.y2=%g "
"underline_position=%g underline_thickness=%g",
tm.pixels_per_em.x, tm.pixels_per_em.y,
tm.ascent, tm.descent, tm.width, tm.height, tm.max_advance,
tm.bounds.x1, tm.bounds.y1, tm.bounds.x2, tm.bounds.y2,
tm.underline_position, tm.underline_thickness);
return rb_str_new2(buff);
}
Jump to Line
Something went wrong with that request. Please try again.