comparison src/graphics.cc @ 10402:9f2bf537a651

Implement text extent property
author Michael Goffioul <michael.goffioul@gmail.com>
date Sun, 07 Mar 2010 21:00:07 +0000
parents 57a59eae83cc
children 660c244d3206
comparison
equal deleted inserted replaced
10401:6d1e49abf95f 10402:9f2bf537a651
48 #include "oct-obj.h" 48 #include "oct-obj.h"
49 #include "oct-map.h" 49 #include "oct-map.h"
50 #include "ov-fcn-handle.h" 50 #include "ov-fcn-handle.h"
51 #include "parse.h" 51 #include "parse.h"
52 #include "toplev.h" 52 #include "toplev.h"
53 #include "txt-eng-ft.h"
53 #include "unwind-prot.h" 54 #include "unwind-prot.h"
54 55
55 // forward declaration 56 // forward declarations
56 static octave_value xget (const graphics_handle& h, const caseless_str& name); 57 static octave_value xget (const graphics_handle& h, const caseless_str& name);
58 static graphics_object xget_ancestor (const graphics_object& go_arg,
59 const std::string& type);
57 60
58 static void 61 static void
59 gripe_set_invalid (const std::string& pname) 62 gripe_set_invalid (const std::string& pname)
60 { 63 {
61 error ("set: invalid value for %s property", pname.c_str ()); 64 error ("set: invalid value for %s property", pname.c_str ());
309 static Matrix 312 static Matrix
310 convert_position (const Matrix& pos, const caseless_str& from_units, 313 convert_position (const Matrix& pos, const caseless_str& from_units,
311 const caseless_str& to_units, 314 const caseless_str& to_units,
312 const Matrix& parent_dim = Matrix (1, 2, 0.0)) 315 const Matrix& parent_dim = Matrix (1, 2, 0.0))
313 { 316 {
314 Matrix retval (1, 4); 317 Matrix retval (1, pos.numel ());
315 double res = 0; 318 double res = 0;
319 bool is_rectangle = (pos.numel () == 4);
316 320
317 if (from_units.compare ("pixels")) 321 if (from_units.compare ("pixels"))
318 retval = pos; 322 retval = pos;
319 else if (from_units.compare ("normalized")) 323 else if (from_units.compare ("normalized"))
320 { 324 {
321 retval(0) = pos(0) * parent_dim(0) + 1; 325 retval(0) = pos(0) * parent_dim(0) + 1;
322 retval(1) = pos(1) * parent_dim(1) + 1; 326 retval(1) = pos(1) * parent_dim(1) + 1;
323 retval(2) = pos(2) * parent_dim(0); 327 if (is_rectangle)
324 retval(3) = pos(3) * parent_dim(1); 328 {
329 retval(2) = pos(2) * parent_dim(0);
330 retval(3) = pos(3) * parent_dim(1);
331 }
332 else
333 retval(2) = 0;
325 } 334 }
326 else if (from_units.compare ("characters")) 335 else if (from_units.compare ("characters"))
327 { 336 {
328 if (res <= 0) 337 if (res <= 0)
329 res = xget (0, "screenpixelsperinch").double_value (); 338 res = xget (0, "screenpixelsperinch").double_value ();
336 345
337 if (f > 0) 346 if (f > 0)
338 { 347 {
339 retval(0) = 0.5 * pos(0) * f; 348 retval(0) = 0.5 * pos(0) * f;
340 retval(1) = pos(1) * f; 349 retval(1) = pos(1) * f;
341 retval(2) = 0.5 * pos(2) * f; 350 if (is_rectangle)
342 retval(3) = pos(3) * f; 351 {
352 retval(2) = 0.5 * pos(2) * f;
353 retval(3) = pos(3) * f;
354 }
355 else
356 retval(2) = 0;
343 } 357 }
344 } 358 }
345 else 359 else
346 { 360 {
347 if (res <= 0) 361 if (res <= 0)
358 372
359 if (f > 0) 373 if (f > 0)
360 { 374 {
361 retval(0) = pos(0) * f + 1; 375 retval(0) = pos(0) * f + 1;
362 retval(1) = pos(1) * f + 1; 376 retval(1) = pos(1) * f + 1;
363 retval(2) = pos(2) * f; 377 if (is_rectangle)
364 retval(3) = pos(3) * f; 378 {
379 retval(2) = pos(2) * f;
380 retval(3) = pos(3) * f;
381 }
382 else
383 retval(2) = 0;
365 } 384 }
366 } 385 }
367 386
368 if (! to_units.compare ("pixels")) 387 if (! to_units.compare ("pixels"))
369 { 388 {
370 if (to_units.compare ("normalized")) 389 if (to_units.compare ("normalized"))
371 { 390 {
372 retval(0) = (retval(0) - 1) / parent_dim(0); 391 retval(0) = (retval(0) - 1) / parent_dim(0);
373 retval(1) = (retval(1) - 1) / parent_dim(1); 392 retval(1) = (retval(1) - 1) / parent_dim(1);
374 retval(2) /= parent_dim(0); 393 if (is_rectangle)
375 retval(3) /= parent_dim(1); 394 {
395 retval(2) /= parent_dim(0);
396 retval(3) /= parent_dim(1);
397 }
398 else
399 retval(2) = 0;
376 } 400 }
377 else if (to_units.compare ("characters")) 401 else if (to_units.compare ("characters"))
378 { 402 {
379 if (res <= 0) 403 if (res <= 0)
380 res = xget (0, "screenpixelsperinch").double_value (); 404 res = xget (0, "screenpixelsperinch").double_value ();
385 409
386 if (f > 0) 410 if (f > 0)
387 { 411 {
388 retval(0) = 2 * retval(0) / f; 412 retval(0) = 2 * retval(0) / f;
389 retval(1) = retval(1) / f; 413 retval(1) = retval(1) / f;
390 retval(2) = 2 * retval(2) / f; 414 if (is_rectangle)
391 retval(3) = retval(3) / f; 415 {
416 retval(2) = 2 * retval(2) / f;
417 retval(3) = retval(3) / f;
418 }
419 else
420 retval(2) = 0;
392 } 421 }
393 } 422 }
394 else 423 else
395 { 424 {
396 if (res <= 0) 425 if (res <= 0)
407 436
408 if (f > 0) 437 if (f > 0)
409 { 438 {
410 retval(0) = (retval(0) - 1) / f; 439 retval(0) = (retval(0) - 1) / f;
411 retval(1) = (retval(1) - 1) / f; 440 retval(1) = (retval(1) - 1) / f;
412 retval(2) /= f; 441 if (is_rectangle)
413 retval(3) /= f; 442 {
414 } 443 retval(2) /= f;
444 retval(3) /= f;
445 }
446 else
447 retval(2) = 0;
448 }
449 }
450 }
451 else if (! is_rectangle)
452 retval(2) = 0;
453
454 return retval;
455 }
456
457 static Matrix
458 convert_text_position (const Matrix& pos, const text::properties& props,
459 const caseless_str& from_units,
460 const caseless_str& to_units)
461 {
462 graphics_object go = gh_manager::get_object (props.get___myhandle__ ());
463 graphics_object ax = xget_ancestor (go, "axes");
464
465 Matrix retval (1, pos.numel (), 0);
466
467 if (ax.valid_object ())
468 {
469 const axes::properties& ax_props =
470 dynamic_cast<const axes::properties&> (ax.get_properties ());
471 graphics_xform ax_xform = ax_props.get_transform ();
472 bool is_rectangle = (pos.numel () == 4);
473 Matrix ax_bbox = ax_props.get_boundingbox (true),
474 ax_size = ax_bbox.extract_n (0, 2, 1, 2);
475
476 if (from_units.compare ("data"))
477 {
478 if (is_rectangle)
479 {
480 ColumnVector v1 = ax_xform.transform (pos(0), pos(1), 0),
481 v2 = ax_xform.transform (pos(0) + pos(2),
482 pos(1) + pos(3), 0);
483
484 retval(0) = v1(0) - ax_bbox(0) + 1;
485 retval(1) = ax_bbox(1) + ax_bbox(3) - v1(1) + 1;
486 retval(2) = v2(0) - v1(0);
487 retval(3) = v1(1) - v2(1);
488 }
489 else
490 {
491 ColumnVector v = ax_xform.transform (pos(0), pos(1), pos(2));
492
493 retval(0) = v(0) - ax_bbox(0) + 1;
494 retval(1) = ax_bbox(1) + ax_bbox(3) - v(1) + 1;
495 retval(2) = 0;
496 }
497 }
498 else
499 retval = convert_position (pos, from_units, "pixels", ax_size);
500
501 if (! to_units.compare ("pixels"))
502 {
503 if (to_units.compare ("data"))
504 {
505 if (is_rectangle)
506 {
507 ColumnVector v1 = ax_xform.untransform (retval(0) + ax_bbox(0) - 1,
508 ax_bbox(1) + ax_bbox(3) - retval(1) + 1),
509 v2 = ax_xform.untransform (retval(0) + retval(2) + ax_bbox(0) - 1,
510 ax_bbox(1) + ax_bbox(3) - (retval(1) + retval(3)) + 1);
511
512 retval(0) = v1(0);
513 retval(1) = v1(1);
514 retval(2) = v2(0) - v1(0);
515 retval(3) = v2(1) - v1(1);
516 }
517 else
518 {
519 ColumnVector v = ax_xform.untransform (retval(0) + ax_bbox(0) - 1,
520 ax_bbox(1) + ax_bbox(3) - retval(1) + 1);
521
522 retval(0) = v(0);
523 retval(1) = v(1);
524 retval(2) = v(2);
525 }
526 }
527 else
528 retval = convert_position (retval, "pixels", to_units, ax_size);
415 } 529 }
416 } 530 }
417 531
418 return retval; 532 return retval;
419 } 533 }
3376 : get_outerposition ().matrix_value ()); 3490 : get_outerposition ().matrix_value ());
3377 3491
3378 3492
3379 pos = convert_position (pos, get_units (), "pixels", 3493 pos = convert_position (pos, get_units (), "pixels",
3380 parent_bb.extract_n (0, 2, 1, 2)); 3494 parent_bb.extract_n (0, 2, 1, 2));
3495
3381 pos(0)--; 3496 pos(0)--;
3382 pos(1)--; 3497 pos(1)--;
3383 pos(1) = parent_bb(3) - pos(1) - pos(3); 3498 pos(1) = parent_bb(3) - pos(1) - pos(3);
3384 3499
3385 return pos; 3500 return pos;
4097 return m; 4212 return m;
4098 } 4213 }
4099 4214
4100 // --------------------------------------------------------------------- 4215 // ---------------------------------------------------------------------
4101 4216
4102 // Note: "text" code is entirely auto-generated 4217 Matrix
4218 text::properties::get_data_position (void) const
4219 {
4220 Matrix pos = get_position ().matrix_value ();
4221
4222 if (! units_is ("data"))
4223 pos = convert_text_position (pos, *this, get_units (), "data");
4224
4225 return pos;
4226 }
4227
4228 octave_value
4229 text::properties::get_extent (void) const
4230 {
4231 Matrix m = extent.get ().matrix_value ();
4232
4233 return convert_text_position (m, *this, "pixels", get_units ());
4234 }
4235
4236 void
4237 text::properties::update_text_extent (void)
4238 {
4239 #ifdef HAVE_FREETYPE
4240
4241 text_element *elt;
4242 ft_render text_renderer;
4243 Matrix box;
4244
4245 // FIXME: parsed content should be cached for efficiency
4246
4247 elt = text_parser_none ().parse (get_string ());
4248 text_renderer.set_font (*this);
4249 box = text_renderer.get_extent (elt, get_rotation ());
4250
4251 Matrix extent (1, 4, 0.0);
4252
4253 // FIXME: also handle left and bottom components
4254
4255 extent(0) = extent(1) = 1;
4256 extent(2) = box(0);
4257 extent(3) = box(1);
4258
4259 set_extent (extent);
4260
4261 #endif
4262 }
4263
4264 void
4265 text::properties::update_units (void)
4266 {
4267 if (! units_is ("data"))
4268 {
4269 set_xliminclude ("off");
4270 set_yliminclude ("off");
4271 set_zliminclude ("off");
4272 }
4273
4274 Matrix pos = get_position ().matrix_value ();
4275
4276 pos = convert_text_position (pos, *this, cached_units, get_units ());
4277 // FIXME: if the current axes view is 2D, then one should
4278 // probably drop the z-component of "pos" and leave "zliminclude"
4279 // to "off".
4280 set_position (pos);
4281
4282 if (units_is ("data"))
4283 {
4284 set_xliminclude ("on");
4285 set_yliminclude ("on");
4286 // FIXME: see above
4287 set_zliminclude ("off");
4288 }
4289
4290 cached_units = get_units ();
4291 }
4103 4292
4104 // --------------------------------------------------------------------- 4293 // ---------------------------------------------------------------------
4105 4294
4106 octave_value 4295 octave_value
4107 image::properties::get_color_data (void) const 4296 image::properties::get_color_data (void) const