2009-04-29 15 views
11

To jest długie ujęcie, ale czy ktoś wie o algorytmie do szacowania i kategoryzowania szerokości tekstu (dla czcionki o zmiennej szerokości) w oparciu o jego zawartość?Algorytm szacowania szerokości tekstu na podstawie zawartości

Na przykład, chciałbym wiedzieć, że iiiiiiii nie jest tak szeroki jak abcdefgh, co z kolei nie jest tak szeroki jak WWWWWWWW, chociaż wszystkie trzy struny osiem znaków.

Jest to właściwie próba zbudowania kilku sprytów w metodzie obcinania łańcuchów, która w chwili obecnej poprawnie obcina wizualnie szeroki ciąg znaków, ale także niepotrzebnie obcina wizualnie wąski ciąg znaków, ponieważ oba ciągi zawierają taką samą liczbę znaków . Prawdopodobnie wystarcza, aby algorytm zaklasyfikował ciąg wejściowy jako wąski, normalny lub szeroki, a następnie skrócić odpowiednio.

To pytanie nie jest w rzeczywistości związane z konkretnym językiem, ale jeśli istnieje algorytm, zaimplementuję go w Javie. To jest dla aplikacji internetowej. Jestem świadomy, że istnieją odpowiedzi na SO, które radzą sobie z tym problemem za pomocą JavaScript, aby uzyskać szerokość elementu zawierającego div, ale zastanawiałem się, czy możliwe jest rozwiązanie po stronie serwera.

Odpowiedz

15

Większość frameworków GUI zapewnia pewien sposób obliczania danych tekstowych dla czcionek na danych urządzeniach wyjściowych.

Korzystanie java.awt.FontMetrics na przykład uważam, że można to zrobić:

import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 

public int measureText(Graphics g, String text) { 
    g.setFont(new Font("TimesRoman", Font.PLAIN, 12)); 
    FontMetrics metrics = g.getFontMetrics(); 

    return metrics.stringWidth(text); 
} 

nie testowano, ale masz pomysł.


W .Net można użyć metody Graphics.MeasureString. W C#:

private void MeasureStringMin(PaintEventArgs e) 
{ 

    // Set up string. 
    string measureString = "Measure String"; 
    Font stringFont = new Font("Arial", 16); 

    // Measure string. 
    SizeF stringSize = new SizeF(); 
    stringSize = e.Graphics.MeasureString(measureString, stringFont); 

    // Draw rectangle representing size of string. 
    e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height); 

    // Draw string to screen. 
    e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0)); 
} 
+2

Maaaybe, ale w tym przypadku masz problem co wybrać kontekst Graphics na serwerze ... –

+0

Mam zaakceptował tę odpowiedź, ponieważ faktycznie próbowali zająć moje pytanie, o które pytano, nawet jeśli pytanie było śmieszne i najwyraźniej coś, czego nie próbowałbyś naprawdę! –

+0

Graphics2D g = new BufferedImage (100, 100, BufferedImage.TYPE_INT_ARGB) .createGraphics(); – jlarson

1

myślę, że należy wybrać jedno z następujących rozwiązań:

  • Dokładne rozwiązanie: Podsumowując szerokość każdego znaku w łańcuchu (większość API daje tę informację)
  • Szybkie oszacowanie: Podaj maksymalną lub minimalną szerokość i pomnóż ją liczbami znaków.

Oczywiście możliwe są różne prognozy mieszane, ale uważam, że jest to zbyt duży wysiłek w niewłaściwym kierunku.

1

Jest to właściwie próba zbudować kilka mądrość do metody ciąg obcięcia [...]

Czy to jest naprawdę warte wysiłku? Mieliśmy ten dokładny problem. I to było w różnych językach. Poprawka polegała na pozostawieniu go tak, jak jest. Złożoność utrzymywania tej inteligencji wzrasta szybko (i prawdopodobnie wykładniczo) przy każdym języku, do którego dodajesz wsparcie. Stąd nasza decyzja.

[...] algorytm do szacowania i kategoryzowania szerokości tekstu (dla czcionki o zmiennej szerokości) na podstawie jego zawartości?

Większość bibliotek czcionek podaje te informacje. Ale to są rzeczy na niskim poziomie. Podstawową ideą jest przekazanie ciągu znaków i odzyskanie szerokości w punktach.

+0

Nie, to nie jest warte wysiłku z powodu problemu, który muszę rozwiązać, ale pobudziło to moją intelektualną ciekawość! –

+0

Hm. FWIW, zaktualizowałem swoją odpowiedź z moim osobistym doświadczeniem. – dirkgently

1

Dla miłego rozwiązania po stronie klienta można wypróbować hybrydowe podejście CSS i JavaScript zgodnie z sugestią RichieHindle's answer to my question.

Zważywszy, że nie wiesz, jaką czcionkę użytkownik zobaczy na stronie (mogą one zawsze zastąpić wybór, Ctrl + strona itd.), "Właściwe" miejsce na to jest w przeglądarce. .. chociaż przeglądarki nie ułatwiają!

* kiedy mówię "miłe", mam na myśli "prawdopodobnie ładne, ale jeszcze nie próbowałem go jeszcze".

+0

Uważam, że język tutaj jest Java ... –

2

W przypadku aplikacji internetowej nie można (naprawdę) uzyskać właściwej oceny. Różne czcionki mają różne szerokości, więc zależy to nie tylko od klienta (przeglądarki) i jego ustawień zoom i DPI, ale także od czcionek obecnych na tym komputerze (i systemie operacyjnym) lub ich substytucji.

Jeśli potrzebujesz dokładnego pomiaru, utwórz grafikę (bitmapę, SVG, a nawet jakiś plik PDF lub cokolwiek innego), która będzie układana i renderowana na serwerze, a nie na kliencie.

2

Nie ma niezawodnego rozwiązania po stronie serwera do obliczania szerokości tekstu. (poza tworzeniem obrazu tekstu i prawdopodobnie SVG)

Jeśli wypróbujesz narzędzie takie jak browser-shots i uruchomisz je na stosunkowo prostych stronach, natychmiast zobaczysz, dlaczego. Trudno jest przewidzieć, jak szeroki, nawet najbardziej przyziemne przykłady się sprawdzą, znacznie mniej, jeśli użytkownik zdecyduje się powiększyć przeglądarkę itp. ...

Nie jest dokładnie określone, że możesz obciąć ciąg (może to być pomocne w dawaniu potencjalnych rozwiązań), ale często jest tak, ponieważ chcesz w pewnym momencie odciąć tekst i zapewnić elipsę.

This can be done reliably on many browser platforms by using a css property, and NO javascript:

http://www.jide.fr/emulate-text-overflowellipsis-in-firefox-with-css

2

Naprawdę nie ma możliwości dowiedzenia się, co przeglądarka, ustawienia czcionki, rozmiar ekranu itp klient korzysta. (OK, czasami nagłówki żądania stanowić wskazówkę, ale tak naprawdę nic spójne i wiarygodne.)

Więc chciałbym:

  • wyświetlacz jakiś przykładowy tekst w programie Internet Explorer z ustawieniami domyślnymi na ekranie/rozmiaru okna z 1024 x 768 (jest to zwykle najbardziej popularny rozmiar)
  • weź średnią liczbę znaków/linię za pomocą tej konfiguracji i użyj jej do oszacowania.

Ogólnie uważam, że to "wystarczająco dobre", na przykład do oszacowania liczby wierszy, które niektóre teksty będą pobierać w przeglądarce, w celu oszacowania liczby reklam wyświetlanych obok tekstu.

Jeśli to naprawdę było dla ciebie ważne, to mogę sobie wyobrazić skomplikowany schemat, w którym początkowo przesyłasz klientowi kod JavaScript, który następnie dokonuje pomiaru i odsyła go do serwera, a następnie używasz tych informacji do przyszłe strony dla tego klienta. Nie mogę sobie jednak wyobrazić, że zazwyczaj jest to warte wysiłku.

+0

Zamiast JavaScript JavaScript po stronie z powrotem do szerokości tekstu, nie byłoby łatwiej pop-up w okienku z pytaniem użytkownika, aby powiększyć 8x tekst w Paint, wydrukować go i wysłać go na podany adres? :-P –

+1

Jeśli to zrobisz, naprawdę zasugeruję serializację kontekstu graficznego w momencie drukowania, a następnie wysłanie go na serwer, oszczędzając w ten sposób istotny ruch e-mailowy - nie chcę przeciążać wielkiego brata w Wielkiej Brytanii baza danych z niepotrzebnymi wiadomościami e-mail! –

+0

Zdecydowanie! :) –

5

Ten pracował dla mnie:

AffineTransform af = new AffineTransform();  
FontRenderContext fr = new FontRenderContext(af,true,true);  
Font f = new Font("Arial", 0, 10); // use exact font 
double width= f.getStringBounds("my string", fr).getWidth();  
+0

Przez dwa dni szukałem czegoś takiego, dziękuję! – Natalia

Powiązane problemy