Return-Path: X-Original-To: apmail-pdfbox-users-archive@www.apache.org Delivered-To: apmail-pdfbox-users-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CDCE9918D for ; Thu, 1 Mar 2012 19:13:02 +0000 (UTC) Received: (qmail 456 invoked by uid 500); 1 Mar 2012 19:13:02 -0000 Delivered-To: apmail-pdfbox-users-archive@pdfbox.apache.org Received: (qmail 404 invoked by uid 500); 1 Mar 2012 19:13:01 -0000 Mailing-List: contact users-help@pdfbox.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: users@pdfbox.apache.org Delivered-To: mailing list users@pdfbox.apache.org Received: (qmail 389 invoked by uid 99); 1 Mar 2012 19:13:01 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2012 19:13:01 +0000 X-ASF-Spam-Status: No, hits=0.7 required=5.0 tests=RCVD_IN_DNSWL_NONE,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [81.169.146.162] (HELO mo-p00-ob.rzone.de) (81.169.146.162) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2012 19:12:53 +0000 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; t=1330629152; l=6566; s=domk; d=lehmi.de; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References: Subject:To:MIME-Version:From:Date:X-RZG-CLASS-ID:X-RZG-AUTH; bh=+TLHQSMlMTjnrG+lEfFjpLEWO2E=; b=B9Q/84UplY1Mlvy0DEft9UPe7ur0+da5bXfb7IXRhuFi3BYvhFCKKce4qzPxRioVtOD cl2BW9GRcdvpz6P5zYSo1FhjqSKvSg0OWHalJtd/1+vAotVVBrmyC+I5I9YWqykXbI5As YpZHt045DsEz/TKrDlF1V6eijoJN798BCa0= X-RZG-AUTH: :LWIAZ0WpaN8UY5o8XRz0jOyrHsdEC+nAE10OdySrgHL6ku8V1wBfgHLvRjcg X-RZG-CLASS-ID: mo00 Received: from [192.168.1.10] (dslb-088-077-251-182.pools.arcor-ip.net [88.77.251.182]) by smtp.strato.de (fruni mo30) (RZmta 27.7 DYNA|AUTH) with ESMTPA id n0233eo21IPEdh for ; Thu, 1 Mar 2012 20:12:22 +0100 (MET) Message-ID: <4F4FCA15.8060607@lehmi.de> Date: Thu, 01 Mar 2012 20:12:21 +0100 From: Andreas Lehmkuehler User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.27) Gecko/20120216 Lightning/1.0b2 Thunderbird/3.1.19 MIME-Version: 1.0 To: users@pdfbox.apache.org Subject: Re: Help needed to resolve issue with converting Arabic characters to presentation forms References: <4F3FC536.6050507@lehmi.de> <4F3FFBDB.80800@lehmi.de> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Virus-Checked: Checked by ClamAV on apache.org Hi, Am 29.02.2012 09:49, schrieb Hamed Iravanchi: > Hi Andreas, > > Regarding the glyph-drawing issue, since I didn't hear anything from you I > decided to take a shot myself, so I checked out the code (1.6 release tag) > and started modifying it to see if I can get the result I expect, but I am > confused and need help :) Sorry, but I hadn't any free cycles in the last week .... > I managed to convert the sample PDF that I provided to image correctly, but > I made almost everything else corrupt! Here's what I did: > > I added a "drawGlyph" to PDFont, next to "drawString" like this: > > public abstract void drawString( String string, Graphics g, float > fontSize, > AffineTransform at, float x, float y ) throws IOException; > > public abstract void drawGlyph(int[] codeString, Graphics g, float > fontSize, > AffineTransform at, float x, float y) > throws IOException; > > I tried to use the codes extracted from page stream. In the PDFStreamEngine > -> processEncodedText -> for loop -> when "font.encode" succeeds, I use the > same code integer to draw glyphs, and I passed it along the string to > "processTextPosition" and I called "drawGlyph" in it, instead of > "drawString". > > Here's the drawGlyph code that I wrote, according to your guidance: > > @Override > public void drawGlyph(int[] codeString, Graphics g, float fontSize, > AffineTransform at, float x, float y) > throws IOException > { > Font _awtFont = getawtFont(); > Graphics2D g2d = (Graphics2D)g; > g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, > RenderingHints.VALUE_ANTIALIAS_ON); > writeFont(g2d, at, _awtFont, x, y, codeString); > } > > > Which uses an overload of writeFont similar to the original: > > > protected void writeFont(final Graphics2D g2d, final AffineTransform > at, final Font awtFont, > final float x, final float y, final int[] > codeString) > { > FontRenderContext frc = new FontRenderContext(null, true, true); > > // check if we have a rotation > if (!at.isIdentity()) > { > try > { > AffineTransform atInv = at.createInverse(); > // do only apply the size of the transform, rotation will > be realized by rotating the graphics, > // otherwise the hp printers will not render the font > Font derivedFont = awtFont.deriveFont(1f); > g2d.setFont(derivedFont); > > GlyphVector glyphs = derivedFont.createGlyphVector(frc, > codeString); > > // apply the inverse transformation to the graphics, which > should be the same as applying the > // transformation itself to the text > g2d.transform(at); > // translate the coordinates > Point2D.Float newXy = new Point2D.Float(x,y); > atInv.transform(new Point2D.Float( x, y), newXy); > g2d.drawGlyphVector(glyphs, (float)newXy.getX(), > (float)newXy.getY()); > > // restore the original transformation > g2d.transform(atInv); > } > catch (NoninvertibleTransformException e) > { > log.error("Error in " + getClass().getName() + > ".writeFont", e); > } > } > else > { > Font derivedFont = awtFont.deriveFont(at); > g2d.setFont(derivedFont); > > GlyphVector glyphs = derivedFont.createGlyphVector(frc, > codeString); > g2d.drawGlyphVector(glyphs, x, y); > } > > Well, that made everything work for the sample PDF that I was working on. > But then I realized that it is only because the "glyph" codes in the font > are equal to the codes used in the page stream. > > For example, in a simple English PDF, there is no "toUnicode" table, and > the same character codes are used in the page stream. But the glyph codes > in the font are different. > > In another PDF (which is RTL and uses connected characters) the code > sequence in the page stream start from 1 (like 1, 2, 3, 4, 5, 3, 6, ...) > but there is no "toUnicode" in it, and the glyph codes in the fonts are > different than those codes, and I didn't find any relation between the two. > > After all, I don't know how can I decide when to use glyphs and when to use > the extracted text (string) to draw the characters. Or, is there a way to > convert everything to glyph codes and draw all the text using glyphs? There are a lot of different ways to encode the text/glyph mapping as you already found out. ;-) I'm afraid it's too much to write it down here. I'm almost done, but I have to get rid of some unwanted side-effects. I hope to find some time at the weekend to finish my work. > BTW, in your sample code to draw glyphs (quoted below) there's a > "CIDstring" which I didn't understand and I thought maybe it has something > to do with my current trouble. The CIDstring in my example contains the codes for the glyphs and not the readable text. > Thanks in advance, > -Hamed > > > On Sat, Feb 18, 2012 at 10:58 PM, Andreas Lehmkuehlerwrote: > >> Hi, >> >> Am 18.02.2012 18:52, schrieb Hamed Iravanchi: >> >> Hi again. >>> >>> Thanks for ur attention to the issue. >>> I actually checked, and saw that the font itself (ttf stream) contains >>> the >>> correct cmap. If we can draw the text using glyph ID instead of >>> characters, the font knows the right characters to draw. >>> >>> I checked the Font class instance in the debugger, it contains a cmap >>> which is exactly right. First I was looking for ways to take the mapping >>> from the font (since it is private member, specific to Sun impl). >>> >>> But I realized we could ask the font to draw glyphs instead of characters. >>> But i couldn't still find a right way to draw a glyph on graphics. >>> >> That's exactly what I'm doing. It somehow lokks like the following: >> >> Create the needed glyphs: >> >> FontRenderContext frc = new FontRenderContext(null, true, true); >> int stringLength = CIDstring.length(); >> int[] codePoints = new int[stringLength]; >> for (int i=0;i> codePoints[i] = CIDstring.codePointAt(i); >> GlyphVector glyphs = awtFont.createGlyphVector(frc, codePoints); >> >> ... >> >> Draw the glyphs: >> >> g2d.drawGlyphVector(glyphs, x, y); >> >> >> BTW, I also can do the implementation and send u a patch once I realize >>> what to do. Thanks for ur encouragement :-) >>> >> Thanks for the offer, I'm already on that, I just have to clean up the >> code and to run some tests to avoid unwanted side effects. >> Once my code is available you might want to doublecheck it. >> >> >> - Hamed >>> On Feb 18, 2012 7:05 PM, "Andreas Lehmkuehler" wrote: >>> >>> >> >> BR >> Andreas Lehmk�hler BR Andreas Lehmk�hler