1/*---------------------------------------------------------------------------* 2 | PDFlib - A library for generating PDF on the fly | 3 +---------------------------------------------------------------------------+ 4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. | 5 +---------------------------------------------------------------------------+ 6 | | 7 | This software is subject to the PDFlib license. It is NOT in the | 8 | public domain. Extended versions and commercial licenses are | 9 | available, please check http://www.pdflib.com. | 10 | | 11 *---------------------------------------------------------------------------*/ 12 13/* $Id: pc_geom.c 14574 2005-10-29 16:27:43Z bonefish $ 14 * 15 * Various geometry routines 16 * 17 */ 18 19#include "pc_util.h" 20#include "pc_geom.h" 21 22 23/* ---------------------- matrix functions ----------------------------- */ 24 25pdc_bool 26pdc_is_identity_matrix(pdc_matrix *m) 27{ 28 return (m->a == (float) 1 && 29 m->b == (float) 0 && 30 m->c == (float) 0 && 31 m->d == (float) 1 && 32 m->e == (float) 0 && 33 m->f == (float) 0); 34} 35 36/* translation matrix */ 37void 38pdc_translation_matrix(float tx, float ty, pdc_matrix *M) 39{ 40 M->a = (float) 1; 41 M->b = (float) 0; 42 M->c = (float) 0; 43 M->d = (float) 1; 44 M->e = tx; 45 M->f = ty; 46} 47 48/* scale matrix */ 49void 50pdc_scale_matrix(float sx, float sy, pdc_matrix *M) 51{ 52 M->a = sx; 53 M->b = (float) 0; 54 M->c = (float) 0; 55 M->d = sy; 56 M->e = (float) 0; 57 M->f = (float) 0; 58} 59 60/* rotation matrix */ 61void 62pdc_rotation_matrix(float alpha, pdc_matrix *M) 63{ 64 double phi, c, s; 65 66 phi = (alpha * PDC_M_PI) / 180.0; 67 c = cos(phi); 68 s = sin(phi); 69 70 M->a = (float) c; 71 M->b = (float) s; 72 M->c = (float) -s; 73 M->d = (float) c; 74 M->e = (float) 0; 75 M->f = (float) 0; 76} 77 78/* skew matrix */ 79void 80pdc_skew_matrix(float alpha, float beta, pdc_matrix *M) 81{ 82 M->a = (float) 1; 83 M->b = (float) tan(alpha * PDC_M_PI / 180.0); 84 M->c = (float) tan(beta * PDC_M_PI / 180.0); 85 M->d = (float) 1; 86 M->e = (float) 0; 87 M->f = (float) 0; 88} 89 90/* left-multiply M to N and store the result in N */ 91void 92pdc_multiply_matrix(const pdc_matrix *M, pdc_matrix *N) 93{ 94 pdc_matrix result; 95 96 result.a = M->a * N->a + M->b * N->c; 97 result.b = M->a * N->b + M->b * N->d; 98 result.c = M->c * N->a + M->d * N->c; 99 result.d = M->c * N->b + M->d * N->d; 100 101 result.e = M->e * N->a + M->f * N->c + N->e; 102 result.f = M->e * N->b + M->f * N->d + N->f; 103 104 N->a = result.a; 105 N->b = result.b; 106 N->c = result.c; 107 N->d = result.d; 108 N->e = result.e; 109 N->f = result.f; 110} 111 112/* invert M and store the result in N */ 113void 114pdc_invert_matrix(pdc_core *pdc, pdc_matrix *N, pdc_matrix *M) 115{ 116 float det = M->a * M->d - M->b * M->c; 117 118 if (fabs(det) < (float) PDC_SMALLREAL) 119 pdc_error(pdc, PDC_E_INT_INVMATRIX, 120 pdc_errprintf(pdc, "%f %f %f %f %f %f", 121 M->a, M->b, M->c, M->d, M->e, M->f), 122 0, 0, 0); 123 124 N->a = M->d/det; 125 N->b = -M->b/det; 126 N->c = -M->c/det; 127 N->d = M->a/det; 128 N->e = -(M->e * N->a + M->f * N->c); 129 N->f = -(M->e * N->b + M->f * N->d); 130} 131 132/* transform point */ 133void 134pdc_transform_point(const pdc_matrix *M, float x, float y, float *tx, float *ty) 135{ 136 *tx = M->a * x + M->c * y + M->e; 137 *ty = M->b * x + M->d * y + M->f; 138} 139 140/* ---------------------- utility functions ----------------------------- */ 141 142void 143pdc_place_element(pdc_fitmethod method, pdc_scalar minfscale, 144 const pdc_box *fitbox, const pdc_vector *relpos, 145 const pdc_vector *elemsize, pdc_box *elembox, 146 pdc_vector *scale) 147{ 148 pdc_vector refpos; 149 pdc_scalar width, height, det, fscale = 1.0; 150 pdc_bool xscaling = pdc_false; 151 152 /* reference position in fitbox */ 153 width = fitbox->ur.x - fitbox->ll.x; 154 height = fitbox->ur.y - fitbox->ll.y; 155 refpos.x = fitbox->ll.x + relpos->x * width; 156 refpos.y = fitbox->ll.y + relpos->y * height; 157 158 /* first check */ 159 switch (method) 160 { 161 case pdc_entire: 162 case pdc_slice: 163 case pdc_meet: 164 case pdc_tauto: 165 if (fabs(width) > PDC_FLOAT_PREC && fabs(height) > PDC_FLOAT_PREC) 166 { 167 if (method != pdc_entire) 168 { 169 det = elemsize->x * height - elemsize->y * width; 170 xscaling = (method == pdc_slice && det <= 0) || 171 ((method == pdc_meet || method == pdc_tauto) && 172 det > 0) ? pdc_true : pdc_false; 173 if (xscaling) 174 fscale = width / elemsize->x; 175 else 176 fscale = height / elemsize->y; 177 } 178 179 if (method == pdc_tauto) 180 { 181 if(fscale >= 1.0) 182 { 183 method = pdc_nofit; 184 } 185 else if (fscale < minfscale) 186 { 187 method = pdc_meet; 188 } 189 } 190 } 191 else 192 { 193 method = pdc_nofit; 194 } 195 break; 196 197 default: 198 break; 199 } 200 201 /* calculation */ 202 switch (method) 203 { 204 /* entire box is covered by entire element */ 205 case pdc_entire: 206 *elembox = *fitbox; 207 scale->x = width / elemsize->x; 208 scale->y = height / elemsize->y; 209 return; 210 211 /* fit into and preserve aspect ratio */ 212 case pdc_slice: 213 case pdc_meet: 214 if (xscaling) 215 height = fscale * elemsize->y; 216 else 217 width = fscale * elemsize->x; 218 scale->x = fscale; 219 scale->y = fscale; 220 break; 221 222 /* fit into and doesn't preserve aspect ratio */ 223 case pdc_tauto: 224 if (xscaling) 225 { 226 height = elemsize->y; 227 scale->x = fscale; 228 scale->y = 1.0; 229 } 230 else 231 { 232 width = elemsize->x; 233 scale->x = 1.0; 234 scale->y = fscale; 235 } 236 break; 237 238 /* only positioning */ 239 case pdc_nofit: 240 case pdc_clip: 241 width = elemsize->x; 242 height = elemsize->y; 243 scale->x = 1.0; 244 scale->y = 1.0; 245 break; 246 } 247 248 /* placed element box */ 249 elembox->ll.x = refpos.x - relpos->x * width; 250 elembox->ll.y = refpos.y - relpos->y * height; 251 elembox->ur.x = refpos.x + (1.0 - relpos->x) * width; 252 elembox->ur.y = refpos.y + (1.0 - relpos->y) * height; 253} 254 255void 256pdc_box2polyline(const pdc_box *box, pdc_vector *polyline) 257{ 258 /* counter clockwise */ 259 polyline[0].x = box->ll.x; 260 polyline[0].y = box->ll.y; 261 polyline[1].x = box->ur.x; 262 polyline[1].y = box->ll.y; 263 polyline[2].x = box->ur.x; 264 polyline[2].y = box->ur.y; 265 polyline[3].x = box->ll.x; 266 polyline[3].y = box->ur.y; 267 polyline[4] = polyline[0]; 268} 269 270/* --------------------------- rectangles --------------------------- */ 271pdc_bool 272pdc_rect_isnull(pdc_rectangle *r) 273{ 274 return 275 (r->llx == (float) 0 && r->lly == (float) 0 && 276 r->urx == (float) 0 && r->ury == (float) 0); 277} 278 279pdc_bool 280pdc_rect_contains(pdc_rectangle *r1, pdc_rectangle *r2) 281{ 282 return 283 (r1->llx <= r2->llx && r1->lly <= r2->lly && 284 r1->urx >= r2->urx && r1->ury >= r2->ury); 285} 286 287void 288pdc_rect_copy(pdc_rectangle *r1, pdc_rectangle *r2) 289{ 290 r1->llx = r2->llx; 291 r1->lly = r2->lly; 292 r1->urx = r2->urx; 293 r1->ury = r2->ury; 294} 295 296void 297pdc_rect_init(pdc_rectangle *r, float llx, float lly, float urx, float ury) 298{ 299 r->llx = llx; 300 r->lly = lly; 301 r->urx = urx; 302 r->ury = ury; 303} 304 305void 306pdc_rect_transform(const pdc_matrix *M, pdc_rectangle *r1, pdc_rectangle *r2) 307{ 308 float x[4], y[4]; 309 int i; 310 311 pdc_transform_point(M, r1->llx, r1->lly, &x[0], &y[0]); 312 pdc_transform_point(M, r1->llx, r1->ury, &x[1], &y[1]); 313 pdc_transform_point(M, r1->urx, r1->ury, &x[2], &y[2]); 314 pdc_transform_point(M, r1->urx, r1->lly, &x[3], &y[3]); 315 316 pdc_rect_init(r2, (float) PDC_FLOAT_MAX, (float) PDC_FLOAT_MAX, 317 (float) PDC_FLOAT_MIN, (float) PDC_FLOAT_MIN); 318 319 for (i = 0; i < 4; i++) 320 { 321 if (x[i] < r2->llx) 322 r2->llx = x[i]; 323 if (y[i] < r2->lly) 324 r2->lly = y[i]; 325 326 if (x[i] > r2->urx) 327 r2->urx = x[i]; 328 if (y[i] > r2->ury) 329 r2->ury = y[i]; 330 } 331} 332 333