/* * fontconfig/src/fcrange.c * * Copyright © 2002 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. The authors make no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "fcint.h" FcRange * FcRangeCreateDouble (double begin, double end) { FcRange *ret = malloc (sizeof (FcRange)); if (ret) { ret->is_double = FcTrue; ret->is_inclusive = FcDoubleCmpEQ (begin, end); ret->u.d.begin = begin; ret->u.d.end = end; } return ret; } FcRange * FcRangeCreateInteger (FcChar32 begin, FcChar32 end) { FcRange *ret = malloc (sizeof (FcRange)); if (ret) { ret->is_double = FcFalse; ret->is_inclusive = (begin == end); ret->u.i.begin = begin; ret->u.i.end = end; } return ret; } void FcRangeDestroy (FcRange *range) { free (range); } FcRange * FcRangeCopy (const FcRange *range) { FcRange *ret; if (range->is_double) ret = FcRangeCreateDouble (range->u.d.begin, range->u.d.end); else ret = FcRangeCreateInteger (range->u.i.begin, range->u.i.end); return ret; } FcBool FcRangeGetDouble(const FcRange *range, double *begin, double *end) { if (!range) return FcFalse; if (range->is_double) { if (begin) *begin = range->u.d.begin; if (end) *end = range->u.d.end; } else { if (begin) *begin = (double)range->u.i.begin; if (end) *end = (double)range->u.i.end; } return FcTrue; } FcRange FcRangeCanonicalize (const FcRange *range) { FcRange new; if (range->is_double) new = *range; else { new.is_double = FcTrue; new.is_inclusive = range->is_inclusive; new.u.d.begin = (double)range->u.i.begin; new.u.d.end = (double)range->u.i.end; } return new; } FcRange * FcRangePromote (double v, FcValuePromotionBuffer *vbuf) { typedef struct { FcRange r; } FcRangePromotionBuffer; FcRangePromotionBuffer *buf = (FcRangePromotionBuffer *) vbuf; FC_ASSERT_STATIC (sizeof (FcRangePromotionBuffer) <= sizeof (FcValuePromotionBuffer)); buf->r.is_double = FcTrue; buf->r.is_inclusive = FcTrue; buf->r.u.d.begin = v; buf->r.u.d.end = v; return &buf->r; } FcBool FcRangeIsZero (const FcRange *r) { FcRange c; if (!r) return FcFalse; c = FcRangeCanonicalize (r); return FcDoubleIsZero (c.u.d.begin) && FcDoubleIsZero (c.u.d.end); } FcBool FcRangeIsInRange (const FcRange *a, const FcRange *b) { FcRange ca, cb; FcBool f; if (!a || !b) return FcFalse; ca = FcRangeCanonicalize (a); cb = FcRangeCanonicalize (b); if (ca.is_inclusive & cb.is_inclusive) f = ca.u.d.end <= cb.u.d.end; else f = ca.u.d.end < cb.u.d.end; return FcDoubleCmpGE (ca.u.d.begin, cb.u.d.begin) && f; } FcBool FcRangeCompare (FcOp op, const FcRange *a, const FcRange *b) { FcRange ca, cb; switch ((int) op) { case FcOpEqual: case FcOpContains: case FcOpListing: return FcRangeIsInRange (a, b); case FcOpNotEqual: case FcOpNotContains: return !FcRangeIsInRange (a, b); case FcOpLess: ca = FcRangeCanonicalize (a); cb = FcRangeCanonicalize (b); return ca.u.d.begin < cb.u.d.begin; case FcOpLessEqual: ca = FcRangeCanonicalize (a); cb = FcRangeCanonicalize (b); return FcDoubleCmpLE (ca.u.d.begin, cb.u.d.begin); case FcOpMore: ca = FcRangeCanonicalize (a); cb = FcRangeCanonicalize (b); return ca.u.d.end > cb.u.d.end; case FcOpMoreEqual: ca = FcRangeCanonicalize (a); cb = FcRangeCanonicalize (b); return FcDoubleCmpGE (ca.u.d.end, cb.u.d.end); default: break; } return FcFalse; } FcChar32 FcRangeHash (const FcRange *r) { FcRange c = FcRangeCanonicalize (r); int b = (int) (c.u.d.begin * 100); int e = FcDoubleCmpEQ (c.u.d.end, DBL_MAX) ? INT_MAX : (int) (c.u.d.end * 100); return b ^ (b << 1) ^ (e << 9); } FcBool FcRangeSerializeAlloc (FcSerialize *serialize, const FcRange *r) { if (!FcSerializeAlloc (serialize, r, sizeof (FcRange))) return FcFalse; return FcTrue; } FcRange * FcRangeSerialize (FcSerialize *serialize, const FcRange *r) { FcRange *r_serialize = FcSerializePtr (serialize, r); if (!r_serialize) return NULL; memcpy (r_serialize, r, sizeof (FcRange)); return r_serialize; } #define __fcrange__ #include "fcaliastail.h" #undef __fcrange__