]> git.imager.perl.org - imager.git/commitdiff
- Imager::Font::BBox objects now have right_bearing() and display_width()
authorTony Cook <tony@develop=help.com>
Tue, 26 Apr 2005 10:45:21 +0000 (10:45 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 26 Apr 2005 10:45:21 +0000 (10:45 +0000)
  methods.  Hopefully this and the advance_width() method fills out
  the Imager bounding box interface to a useful state.
  Implemented for all four font drivers.
- Win32 font bounding_box() method now supports the advance width
  and right bearing values.

Changes
Imager.xs
image.h
t/t37w32font.t
win32.c

diff --git a/Changes b/Changes
index 9591b7f7c41371a4f2802d7a69b4996e391b66e8..daec8e3785870f5e21c11d8d259687d56b40d831 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1069,7 +1069,9 @@ Revision history for Perl extension Imager.
 - Imager::Font::BBox objects now have right_bearing() and display_width()
   methods.  Hopefully this and the advance_width() method fills out
   the Imager bounding box interface to a useful state.
-  Implemented for FT2, FT1.x, T1Lib so far.
+  Implemented for all four font drivers.
+- Win32 font bounding_box() method now supports the advance width
+  and right bearing values.
 
 =================================================================
 
index b0666a45fb71b30687d49757030f5634e00ef4ee..63b981ed2c0f34e0c2b4126565e0a6a43b98ac35 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -4019,6 +4019,9 @@ i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
       OUTPUT:
        RETVAL
 
+undef_int
+i_wf_addfont(font)
+        char *font
 
 #endif
 
diff --git a/image.h b/image.h
index 52f507177013a294815862bb3e22c0ec81cdfea3..e908c99271a20c361558d1d2e2727119e61a1e74 100644 (file)
--- a/image.h
+++ b/image.h
@@ -356,6 +356,7 @@ extern int i_wf_text(char *face, i_img *im, int tx, int ty, i_color *cl,
                     int size, char *text, int len, int align, int aa);
 extern int i_wf_cp(char *face, i_img *im, int tx, int ty, int channel, 
                   int size, char *text, int len, int align, int aa);
+extern int i_wf_addfont(char const *file);
 
 #endif
 
index 2d9c8de0eec27813f623787a00858be315ea1477..435dc576f0b90d99914ee41d5faf1d068c1424ca 100644 (file)
@@ -1,14 +1,15 @@
 #!perl -w
 use strict;
 use lib 't';
-use Test::More tests => 7;
+use Test::More tests => 18;
 BEGIN { use_ok(Imager => ':all') }
+++$|;
 
 init_log("testout/t37w32font.log",1);
 
 SKIP:
 {
-  i_has_format('w32') or skip("no MS Windows", 6);
+  i_has_format('w32') or skip("no MS Windows", 17);
   print "# has w32\n";
 
   my $fontname=$ENV{'TTFONTTEST'} || 'Times New Roman Bold';
@@ -52,7 +53,7 @@ SKIP:
     or print "# ",$img->errstr,"\n";
   $img->write(file=>'testout/t37_oo.ppm') or print "not ";
   my @bbox2 = $font->bounding_box(string=>'Imager');
-  is(@bbox2, 6, "got 6 values from bounding_box");
+  is(@bbox2, 8, "got 8 values from bounding_box");
 
   # this only applies while the Win32 driver returns 6 values
   # at this point we don't return the advance width from the low level
@@ -62,4 +63,42 @@ SKIP:
   ok($bbox, "got the bounding box object");
   is($bbox->advance_width, $bbox->end_offset, 
      "check advance_width fallback correct");
+
+  ok(Imager::i_wf_addfont("fontfiles/ExistenceTest.ttf"), "add test font");
+
+  my $namefont = Imager::Font->new(face=>"ExistenceTest");
+  ok($namefont, "create font based on added font");
+
+  # the test font is known to have a shorter advance width for that char
+  @bbox = $namefont->bounding_box(string=>"/", size=>100);
+  print "# / box: @bbox\n";
+  is(@bbox, 8, "should be 8 entries");
+  isnt($bbox[6], $bbox[2], "different advance width");
+  $bbox = $namefont->bounding_box(string=>"/", size=>100);
+  ok($bbox->pos_width != $bbox->advance_width, "OO check");
+  
+  cmp_ok($bbox->right_bearing, '<', 0, "check right bearing");
+  
+  cmp_ok($bbox->display_width, '>', $bbox->advance_width,
+        "check display width (roughly)");
+
+  my $im = Imager->new(xsize=>200, ysize=>200);
+  $im->string(font=>$namefont, text=>"/", x=>20, y=>100, color=>'white', size=>100);
+  $im->line(color=>'blue', x1=>20, y1=>0, x2=>20, y2=>199);
+  my $right = 20 + $bbox->advance_width;
+  $im->line(color=>'blue', x1=>$right, y1=>0, x2=>$right, y2=>199);
+  $im->write(file=>'testout/t37w32_slash.ppm');
+
+  # check with a char that fits inside the box
+  $bbox = $namefont->bounding_box(string=>"!", size=>100);
+  print "# pos width ", $bbox->pos_width, "\n";
+  print "# ! box: @$bbox\n";
+  is($bbox->pos_width, $bbox->advance_width, 
+     "check backwards compatibility");
+  cmp_ok($bbox->left_bearing, '>', 0, "left bearing positive");
+  cmp_ok($bbox->right_bearing, '>', 0, "right bearing positive");
+  cmp_ok($bbox->display_width, '<', $bbox->advance_width,
+        "display smaller than advance");
+
+
 }
diff --git a/win32.c b/win32.c
index f04cb06c5b16f29e3a6297eecf2f5acccd28b7f4..61a4e6511c1251a117efb29caaf03c01a33bbc9f 100644 (file)
--- a/win32.c
+++ b/win32.c
@@ -1,3 +1,4 @@
+#define _WIN32_WINNT 0x500
 #include "image.h"
 #define STRICT
 #include <windows.h>
@@ -51,6 +52,8 @@ int i_wf_bbox(char *face, int size, char *text, int length, int *bbox) {
   int i;
   MAT2 mat;
 
+  mm_log((1, "i_wf_bbox(face %s, size %d, text %p, length %d, bbox %p)\n", face, size, text, length, bbox));
+
   set_logfont(face, size, &lf);
   font = CreateFontIndirect(&lf);
   if (!font) 
@@ -58,6 +61,13 @@ int i_wf_bbox(char *face, int size, char *text, int length, int *bbox) {
   dc = GetDC(NULL);
   oldFont = (HFONT)SelectObject(dc, font);
 
+  {
+    char facename[100];
+    if (GetTextFace(dc, sizeof(facename), facename)) {
+      mm_log((1, "  face: %s\n", facename));
+    }
+  }
+
   if (!GetTextExtentPoint32(dc, text, length, &sz)
       || !GetTextMetrics(dc, &tm)) {
     SelectObject(dc, oldFont);
@@ -69,25 +79,35 @@ int i_wf_bbox(char *face, int size, char *text, int length, int *bbox) {
      see it.  GetGlyphOutline() seems to return the same size for
      all characters.
   */
-  bbox[1] = bbox[4] = tm.tmDescent;
-  bbox[2] = sz.cx;
-  bbox[3] = bbox[5] = tm.tmAscent;
+  bbox[BBOX_GLOBAL_DESCENT] = bbox[BBOX_DESCENT] = tm.tmDescent;
+  bbox[BBOX_POS_WIDTH] = sz.cx;
+  bbox[BBOX_ADVANCE_WIDTH] = sz.cx;
+  bbox[BBOX_GLOBAL_ASCENT] = bbox[BBOX_ASCENT] = tm.tmAscent;
   
-  if (GetCharABCWidths(dc, text[0], text[0], &first)
+  if (length
+      && GetCharABCWidths(dc, text[0], text[0], &first)
       && GetCharABCWidths(dc, text[length-1], text[length-1], &last)) {
-    bbox[0] = first.abcA;
+    mm_log((1, "first: %d A: %d  B: %d  C: %d\n", text[0],
+           first.abcA, first.abcB, first.abcC));
+    mm_log((1, "first: %d A: %d  B: %d  C: %d\n", text[length-1],
+           last.abcA, last.abcB, last.abcC));
+    bbox[BBOX_NEG_WIDTH] = first.abcA;
+    bbox[BBOX_RIGHT_BEARING] = last.abcC;
     if (last.abcC < 0)
-      bbox[2] -= last.abcC;
+      bbox[BBOX_POS_WIDTH] -= last.abcC;
   }
   else {
-    bbox[0] = 0;
+    bbox[BBOX_NEG_WIDTH] = 0;
+    bbox[BBOX_RIGHT_BEARING] = 0;
   }
 
   SelectObject(dc, oldFont);
   ReleaseDC(NULL, dc);
   DeleteObject(font);
 
-  return 6;
+  mm_log((1, " bbox=> negw=%d glob_desc=%d pos_wid=%d glob_asc=%d desc=%d asc=%d adv_width=%d rightb=%d\n", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], bbox[7]));
+
+  return BBOX_RIGHT_BEARING + 1;
 }
 
 /*
@@ -183,6 +203,28 @@ i_wf_cp(char *face, i_img *im, int tx, int ty, int channel, int size,
   return 1;
 }
 
+/*
+=item i_wf_addfont(char const *filename, char const *resource_file)
+
+Adds a TTF font file as usable by the application.
+
+The font is always added as private to the application.
+
+=cut
+ */
+int
+i_wf_addfont(char const *filename) {
+  i_clear_error();
+
+  if (AddFontResourceEx(filename, FR_PRIVATE, 0)) {
+    return 1;
+  }
+  else {
+    i_push_errorf(0, "Could not add resource: %ld", GetLastError());
+    return 0;
+  }
+}
+
 /*
 =back