Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2010-2012. 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 #include "config.h"
     21 
     22 #include "core/rendering/svg/SVGTextMetrics.h"
     23 
     24 #include "core/rendering/svg/RenderSVGInlineText.h"
     25 #include "core/rendering/svg/SVGTextRunRenderingContext.h"
     26 
     27 namespace WebCore {
     28 
     29 SVGTextMetrics::SVGTextMetrics()
     30     : m_width(0)
     31     , m_height(0)
     32     , m_length(0)
     33     , m_glyph(0)
     34 {
     35 }
     36 
     37 SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
     38     : m_width(0)
     39     , m_height(0)
     40     , m_length(1)
     41     , m_glyph(0)
     42 {
     43 }
     44 
     45 SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run)
     46 {
     47     ASSERT(textRenderer);
     48 
     49     float scalingFactor = textRenderer->scalingFactor();
     50     ASSERT(scalingFactor);
     51 
     52     const Font& scaledFont = textRenderer->scaledFont();
     53     int length = 0;
     54 
     55     // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
     56     m_width = scaledFont.width(run, length, m_glyph) / scalingFactor;
     57     m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
     58 
     59     ASSERT(length >= 0);
     60     m_length = static_cast<unsigned>(length);
     61 }
     62 
     63 TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length)
     64 {
     65     ASSERT(text->style());
     66     return constructTextRun(text, position, length, text->style()->direction());
     67 }
     68 
     69 TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
     70 {
     71     RenderStyle* style = text->style();
     72     ASSERT(style);
     73 
     74     TextRun run(static_cast<const LChar*>(0) // characters, will be set below if non-zero.
     75                 , 0 // length, will be set below if non-zero.
     76                 , 0 // xPos, only relevant with allowTabs=true
     77                 , 0 // padding, only relevant for justified text, not relevant for SVG
     78                 , TextRun::AllowTrailingExpansion
     79                 , textDirection
     80                 , isOverride(style->unicodeBidi()) /* directionalOverride */);
     81 
     82     if (length) {
     83         if (text->is8Bit())
     84             run.setText(text->characters8() + position, length);
     85         else
     86             run.setText(text->characters16() + position, length);
     87     }
     88 
     89     if (textRunNeedsRenderingContext(style->font()))
     90         run.setRenderingContext(SVGTextRunRenderingContext::create(text));
     91 
     92     run.disableRoundingHacks();
     93 
     94     // We handle letter & word spacing ourselves.
     95     run.disableSpacing();
     96 
     97     // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
     98     run.setCharactersLength(text->textLength() - position);
     99     ASSERT(run.charactersLength() >= run.length());
    100     return run;
    101 }
    102 
    103 SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
    104 {
    105     ASSERT(text);
    106     return SVGTextMetrics(text, constructTextRun(text, position, length, textDirection));
    107 }
    108 
    109 SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length)
    110 {
    111     ASSERT(text);
    112     return SVGTextMetrics(text, constructTextRun(text, position, length));
    113 }
    114 
    115 SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, Glyph glyphNameGlyphId)
    116 {
    117     ASSERT(text);
    118 
    119     bool needsContext = textRunNeedsRenderingContext(text->style()->font());
    120     float scalingFactor = text->scalingFactor();
    121     ASSERT(scalingFactor);
    122 
    123     m_width = width / scalingFactor;
    124     m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
    125     m_glyph = needsContext ? glyphNameGlyphId : 0;
    126 
    127     m_length = length;
    128 }
    129 
    130 }
    131