Mercurial > octave-nkf
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 |