blob: 37cf067557206c6e02c843c48a0aa3b8c29db5f0 [file] [log] [blame]
/*
* 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 = (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__