Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #ifndef SVGTextFragment_h
     21 #define SVGTextFragment_h
     22 
     23 #include "platform/transforms/AffineTransform.h"
     24 
     25 namespace blink {
     26 
     27 // A SVGTextFragment describes a text fragment of a RenderSVGInlineText which can be rendered at once.
     28 struct SVGTextFragment {
     29     SVGTextFragment()
     30         : characterOffset(0)
     31         , metricsListOffset(0)
     32         , length(0)
     33         , isTextOnPath(false)
     34         , x(0)
     35         , y(0)
     36         , width(0)
     37         , height(0)
     38     {
     39     }
     40 
     41     enum TransformType {
     42         TransformRespectingTextLength,
     43         TransformIgnoringTextLength
     44     };
     45 
     46     void buildFragmentTransform(AffineTransform& result, TransformType type = TransformRespectingTextLength) const
     47     {
     48         if (type == TransformIgnoringTextLength) {
     49             result = transform;
     50             transformAroundOrigin(result);
     51             return;
     52         }
     53 
     54         if (isTextOnPath)
     55             buildTransformForTextOnPath(result);
     56         else
     57             buildTransformForTextOnLine(result);
     58     }
     59 
     60     // The first rendered character starts at RenderSVGInlineText::characters() + characterOffset.
     61     unsigned characterOffset;
     62     unsigned metricsListOffset;
     63     unsigned length : 31;
     64     bool isTextOnPath : 1;
     65 
     66     float x;
     67     float y;
     68     float width;
     69     float height;
     70 
     71     // Includes rotation/glyph-orientation-(horizontal|vertical) transforms, as well as orientation related shifts
     72     // (see SVGTextLayoutEngine, which builds this transformation).
     73     AffineTransform transform;
     74 
     75     // Contains lengthAdjust related transformations, which are not allowd to influence the SVGTextQuery code.
     76     AffineTransform lengthAdjustTransform;
     77 
     78 private:
     79     void transformAroundOrigin(AffineTransform& result) const
     80     {
     81         // Returns (translate(x, y) * result) * translate(-x, -y).
     82         result.setE(result.e() + x);
     83         result.setF(result.f() + y);
     84         result.translate(-x, -y);
     85     }
     86 
     87     void buildTransformForTextOnPath(AffineTransform& result) const
     88     {
     89         // For text-on-path layout, multiply the transform with the lengthAdjustTransform before orienting the resulting transform.
     90         result = lengthAdjustTransform.isIdentity() ? transform : transform * lengthAdjustTransform;
     91         if (!result.isIdentity())
     92             transformAroundOrigin(result);
     93     }
     94 
     95     void buildTransformForTextOnLine(AffineTransform& result) const
     96     {
     97         // For text-on-line layout, orient the transform first, then multiply the lengthAdjustTransform with the oriented transform.
     98         if (transform.isIdentity()) {
     99             result = lengthAdjustTransform;
    100             return;
    101         }
    102 
    103         result = transform;
    104         transformAroundOrigin(result);
    105 
    106         if (!lengthAdjustTransform.isIdentity())
    107             result = lengthAdjustTransform * result;
    108     }
    109 };
    110 
    111 } // namespace blink
    112 
    113 #endif
    114