/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is websupergoo.com code.
 *
 * The Initial Developer of the Original Code is Finn International.
 * Portions created by the Initial Developer are Copyright (C) 2011
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Chris Yuen <chris@websupergoo.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "K2FontInjections.h"

#include "K2ICrystalCallback.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsStyleContext.h"

#include "gfxFont.h"

#include "nsTextRunTransformations.h"

namespace
{
	template <typename T, typename U>
	inline double ToDeviceUnits(T appUnits, U devUnitsPerAppUnits) {
		return static_cast<double>(appUnits) *
			static_cast<double>(devUnitsPerAppUnits);
	}
}

void K2Injections::TellCrystalAboutTextRun(
	K2ICrystalCallback & callback, gfxContext * context,
	gfxTextRun & textRun,
	gfxFontEntry & fontEntry, const gfxFontStyle & style,
	const gfxPoint & pt, gfxFloat runWidth,
	gfxFloat fontSize, double devUnitsPerAppUnit,
	PRUint32 start, PRUint32 end,
	cairo_glyph_t * glyphs, unsigned int numGlyphs)
{
	NS_ASSERTION(context, "No context!?");

	PRUint16 weight = style.weight;
	PRBool isItalic = style.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE);

    if(textRun.GetText8Bit()) {
        callback.SetFont(fontEntry.FamilyName(),
            fontSize, weight, isItalic, PR_FALSE);
        nsCString txt(
			reinterpret_cast<const char *>(textRun.GetText8Bit()),
			textRun.GetLength());
        callback.OnAddTextA(
            ToDeviceUnits(pt.x, devUnitsPerAppUnit),
            ToDeviceUnits(pt.y, devUnitsPerAppUnit),
            ToDeviceUnits(runWidth, devUnitsPerAppUnit),
            Substring(txt, start, end - start), textRun.IsRightToLeft(), glyphs, numGlyphs);
    }
    else if(textRun.GetTextUnicode()) {
		nsString txt(textRun.GetTextUnicode(), textRun.GetLength());

		// HACK I know that all transformed text runs will be UTF16, 
		// so no need to check above.

		// If we have case transformed, we need to reapply the 
		// transformation. Too bad Gecko only transforms the glyph 
		// but not the string but Crystal only feeds on text strings.
		if(textRun.GetFlags() & gfxTextRunFactory::TEXT_HAS_CASE_TRANSFORMED) {
			nsTransformedTextRun * ttr =
				reinterpret_cast<nsTransformedTextRun *>(&textRun);
			nsCaseTransformTextRunFactory * cttrf = 
				reinterpret_cast<nsCaseTransformTextRunFactory *>(ttr->mFactory);

			NS_ASSERTION(cttrf, "nsTransformedTextRun has no factory!?");

			cttrf->UsefulRebuildTextRun(ttr, context, &txt);

			if(txt.IsEmpty()) {
				NS_ASSERTION(0, "The text has not been transformed "
					"as needed. Using untransformed text");
				txt.Assign(textRun.GetTextUnicode());
			}
		}

		// BIG HACK We we have small-caps, we just need to transform 
		// all letters into capital letters. Obviously this is not 
		// strictly correct but works for ABCpdf-ABCGecko scenario
		if(textRun.GetFlags() & gfxTextRunFactory::TEXT_IS_SMALL_CAPS)
			ToUpperCase(txt);

        callback.SetFont(fontEntry.FamilyName(),
            fontSize, weight, isItalic, PR_TRUE);

        nsDependentSubstring substr(txt, start, end - start);
        callback.OnAddText(
            ToDeviceUnits(pt.x, devUnitsPerAppUnit),
            ToDeviceUnits(pt.y, devUnitsPerAppUnit),
            ToDeviceUnits(runWidth, devUnitsPerAppUnit),
            substr, textRun.IsRightToLeft(), glyphs, numGlyphs);
    }
}
