summaryrefslogtreecommitdiff
authorsimon <simon>2002-11-08 15:20:59 (UTC)
committer simon <simon>2002-11-08 15:20:59 (UTC)
commitd8ac5b68b504536136347547816992b1cf605cd4 (patch) (unidiff)
tree7e90b9c23b78c7c67b5433bebd6a29e3e98e4bac
parent447735be20fad2642617e3ba4f7ef0b598f597db (diff)
downloadopie-d8ac5b68b504536136347547816992b1cf605cd4.zip
opie-d8ac5b68b504536136347547816992b1cf605cd4.tar.gz
opie-d8ac5b68b504536136347547816992b1cf605cd4.tar.bz2
- a couple of fixes like this one:
- fprintf(f, "%g", real); + fprintf(f, "%g", static_cast<double>(real)); with 'real' being a fouble object. as fprintf is a c function with variable arguments one cannot pass non-primitive objects through it and there is no way for the compiler to figure out the right conversion operator, so we give it a helping hand :)
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/Gfx.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Object.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Page.cc4
3 files changed, 4 insertions, 4 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/Gfx.cc b/noncore/unsupported/qpdf/xpdf/Gfx.cc
index 17d613e..f016c0e 100644
--- a/noncore/unsupported/qpdf/xpdf/Gfx.cc
+++ b/noncore/unsupported/qpdf/xpdf/Gfx.cc
@@ -843,1918 +843,1918 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
843 } 843 }
844 for (i = 0; i < gfxColorMaxComps; ++i) { 844 for (i = 0; i < gfxColorMaxComps; ++i) {
845 color.c[i] = 0; 845 color.c[i] = 0;
846 } 846 }
847 state->setFillColor(&color); 847 state->setFillColor(&color);
848 out->updateFillColor(state); 848 out->updateFillColor(state);
849} 849}
850 850
851void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { 851void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
852 Object obj; 852 Object obj;
853 GfxColorSpace *colorSpace; 853 GfxColorSpace *colorSpace;
854 GfxColor color; 854 GfxColor color;
855 int i; 855 int i;
856 856
857 state->setStrokePattern(NULL); 857 state->setStrokePattern(NULL);
858 res->lookupColorSpace(args[0].getName(), &obj); 858 res->lookupColorSpace(args[0].getName(), &obj);
859 if (obj.isNull()) { 859 if (obj.isNull()) {
860 colorSpace = GfxColorSpace::parse(&args[0]); 860 colorSpace = GfxColorSpace::parse(&args[0]);
861 } else { 861 } else {
862 colorSpace = GfxColorSpace::parse(&obj); 862 colorSpace = GfxColorSpace::parse(&obj);
863 } 863 }
864 obj.free(); 864 obj.free();
865 if (colorSpace) { 865 if (colorSpace) {
866 state->setStrokeColorSpace(colorSpace); 866 state->setStrokeColorSpace(colorSpace);
867 } else { 867 } else {
868 error(getPos(), "Bad color space (stroke)"); 868 error(getPos(), "Bad color space (stroke)");
869 } 869 }
870 for (i = 0; i < gfxColorMaxComps; ++i) { 870 for (i = 0; i < gfxColorMaxComps; ++i) {
871 color.c[i] = 0; 871 color.c[i] = 0;
872 } 872 }
873 state->setStrokeColor(&color); 873 state->setStrokeColor(&color);
874 out->updateStrokeColor(state); 874 out->updateStrokeColor(state);
875} 875}
876 876
877void Gfx::opSetFillColor(Object args[], int numArgs) { 877void Gfx::opSetFillColor(Object args[], int numArgs) {
878 GfxColor color; 878 GfxColor color;
879 int i; 879 int i;
880 880
881 state->setFillPattern(NULL); 881 state->setFillPattern(NULL);
882 for (i = 0; i < numArgs; ++i) { 882 for (i = 0; i < numArgs; ++i) {
883 color.c[i] = args[i].getNum(); 883 color.c[i] = args[i].getNum();
884 } 884 }
885 state->setFillColor(&color); 885 state->setFillColor(&color);
886 out->updateFillColor(state); 886 out->updateFillColor(state);
887} 887}
888 888
889void Gfx::opSetStrokeColor(Object args[], int numArgs) { 889void Gfx::opSetStrokeColor(Object args[], int numArgs) {
890 GfxColor color; 890 GfxColor color;
891 int i; 891 int i;
892 892
893 state->setStrokePattern(NULL); 893 state->setStrokePattern(NULL);
894 for (i = 0; i < numArgs; ++i) { 894 for (i = 0; i < numArgs; ++i) {
895 color.c[i] = args[i].getNum(); 895 color.c[i] = args[i].getNum();
896 } 896 }
897 state->setStrokeColor(&color); 897 state->setStrokeColor(&color);
898 out->updateStrokeColor(state); 898 out->updateStrokeColor(state);
899} 899}
900 900
901void Gfx::opSetFillColorN(Object args[], int numArgs) { 901void Gfx::opSetFillColorN(Object args[], int numArgs) {
902 GfxColor color; 902 GfxColor color;
903 GfxPattern *pattern; 903 GfxPattern *pattern;
904 int i; 904 int i;
905 905
906 if (state->getFillColorSpace()->getMode() == csPattern) { 906 if (state->getFillColorSpace()->getMode() == csPattern) {
907 if (numArgs > 1) { 907 if (numArgs > 1) {
908 for (i = 0; i < numArgs && i < 4; ++i) { 908 for (i = 0; i < numArgs && i < 4; ++i) {
909 if (args[i].isNum()) { 909 if (args[i].isNum()) {
910 color.c[i] = args[i].getNum(); 910 color.c[i] = args[i].getNum();
911 } 911 }
912 } 912 }
913 state->setFillColor(&color); 913 state->setFillColor(&color);
914 out->updateFillColor(state); 914 out->updateFillColor(state);
915 } 915 }
916 if (args[numArgs-1].isName() && 916 if (args[numArgs-1].isName() &&
917 (pattern = res->lookupPattern(args[numArgs-1].getName()))) { 917 (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
918 state->setFillPattern(pattern); 918 state->setFillPattern(pattern);
919 } 919 }
920 920
921 } else { 921 } else {
922 state->setFillPattern(NULL); 922 state->setFillPattern(NULL);
923 for (i = 0; i < numArgs && i < 4; ++i) { 923 for (i = 0; i < numArgs && i < 4; ++i) {
924 if (args[i].isNum()) { 924 if (args[i].isNum()) {
925 color.c[i] = args[i].getNum(); 925 color.c[i] = args[i].getNum();
926 } 926 }
927 } 927 }
928 state->setFillColor(&color); 928 state->setFillColor(&color);
929 out->updateFillColor(state); 929 out->updateFillColor(state);
930 } 930 }
931} 931}
932 932
933void Gfx::opSetStrokeColorN(Object args[], int numArgs) { 933void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
934 GfxColor color; 934 GfxColor color;
935 GfxPattern *pattern; 935 GfxPattern *pattern;
936 int i; 936 int i;
937 937
938 if (state->getStrokeColorSpace()->getMode() == csPattern) { 938 if (state->getStrokeColorSpace()->getMode() == csPattern) {
939 if (numArgs > 1) { 939 if (numArgs > 1) {
940 for (i = 0; i < numArgs && i < 4; ++i) { 940 for (i = 0; i < numArgs && i < 4; ++i) {
941 if (args[i].isNum()) { 941 if (args[i].isNum()) {
942 color.c[i] = args[i].getNum(); 942 color.c[i] = args[i].getNum();
943 } 943 }
944 } 944 }
945 state->setStrokeColor(&color); 945 state->setStrokeColor(&color);
946 out->updateStrokeColor(state); 946 out->updateStrokeColor(state);
947 } 947 }
948 if (args[numArgs-1].isName() && 948 if (args[numArgs-1].isName() &&
949 (pattern = res->lookupPattern(args[numArgs-1].getName()))) { 949 (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
950 state->setStrokePattern(pattern); 950 state->setStrokePattern(pattern);
951 } 951 }
952 952
953 } else { 953 } else {
954 state->setStrokePattern(NULL); 954 state->setStrokePattern(NULL);
955 for (i = 0; i < numArgs && i < 4; ++i) { 955 for (i = 0; i < numArgs && i < 4; ++i) {
956 if (args[i].isNum()) { 956 if (args[i].isNum()) {
957 color.c[i] = args[i].getNum(); 957 color.c[i] = args[i].getNum();
958 } 958 }
959 } 959 }
960 state->setStrokeColor(&color); 960 state->setStrokeColor(&color);
961 out->updateStrokeColor(state); 961 out->updateStrokeColor(state);
962 } 962 }
963} 963}
964 964
965//------------------------------------------------------------------------ 965//------------------------------------------------------------------------
966// path segment operators 966// path segment operators
967//------------------------------------------------------------------------ 967//------------------------------------------------------------------------
968 968
969void Gfx::opMoveTo(Object args[], int numArgs) { 969void Gfx::opMoveTo(Object args[], int numArgs) {
970 state->moveTo(args[0].getNum(), args[1].getNum()); 970 state->moveTo(args[0].getNum(), args[1].getNum());
971} 971}
972 972
973void Gfx::opLineTo(Object args[], int numArgs) { 973void Gfx::opLineTo(Object args[], int numArgs) {
974 if (!state->isCurPt()) { 974 if (!state->isCurPt()) {
975 error(getPos(), "No current point in lineto"); 975 error(getPos(), "No current point in lineto");
976 return; 976 return;
977 } 977 }
978 state->lineTo(args[0].getNum(), args[1].getNum()); 978 state->lineTo(args[0].getNum(), args[1].getNum());
979} 979}
980 980
981void Gfx::opCurveTo(Object args[], int numArgs) { 981void Gfx::opCurveTo(Object args[], int numArgs) {
982 fouble x1, y1, x2, y2, x3, y3; 982 fouble x1, y1, x2, y2, x3, y3;
983 983
984 if (!state->isCurPt()) { 984 if (!state->isCurPt()) {
985 error(getPos(), "No current point in curveto"); 985 error(getPos(), "No current point in curveto");
986 return; 986 return;
987 } 987 }
988 x1 = args[0].getNum(); 988 x1 = args[0].getNum();
989 y1 = args[1].getNum(); 989 y1 = args[1].getNum();
990 x2 = args[2].getNum(); 990 x2 = args[2].getNum();
991 y2 = args[3].getNum(); 991 y2 = args[3].getNum();
992 x3 = args[4].getNum(); 992 x3 = args[4].getNum();
993 y3 = args[5].getNum(); 993 y3 = args[5].getNum();
994 state->curveTo(x1, y1, x2, y2, x3, y3); 994 state->curveTo(x1, y1, x2, y2, x3, y3);
995} 995}
996 996
997void Gfx::opCurveTo1(Object args[], int numArgs) { 997void Gfx::opCurveTo1(Object args[], int numArgs) {
998 fouble x1, y1, x2, y2, x3, y3; 998 fouble x1, y1, x2, y2, x3, y3;
999 999
1000 if (!state->isCurPt()) { 1000 if (!state->isCurPt()) {
1001 error(getPos(), "No current point in curveto1"); 1001 error(getPos(), "No current point in curveto1");
1002 return; 1002 return;
1003 } 1003 }
1004 x1 = state->getCurX(); 1004 x1 = state->getCurX();
1005 y1 = state->getCurY(); 1005 y1 = state->getCurY();
1006 x2 = args[0].getNum(); 1006 x2 = args[0].getNum();
1007 y2 = args[1].getNum(); 1007 y2 = args[1].getNum();
1008 x3 = args[2].getNum(); 1008 x3 = args[2].getNum();
1009 y3 = args[3].getNum(); 1009 y3 = args[3].getNum();
1010 state->curveTo(x1, y1, x2, y2, x3, y3); 1010 state->curveTo(x1, y1, x2, y2, x3, y3);
1011} 1011}
1012 1012
1013void Gfx::opCurveTo2(Object args[], int numArgs) { 1013void Gfx::opCurveTo2(Object args[], int numArgs) {
1014 fouble x1, y1, x2, y2, x3, y3; 1014 fouble x1, y1, x2, y2, x3, y3;
1015 1015
1016 if (!state->isCurPt()) { 1016 if (!state->isCurPt()) {
1017 error(getPos(), "No current point in curveto2"); 1017 error(getPos(), "No current point in curveto2");
1018 return; 1018 return;
1019 } 1019 }
1020 x1 = args[0].getNum(); 1020 x1 = args[0].getNum();
1021 y1 = args[1].getNum(); 1021 y1 = args[1].getNum();
1022 x2 = args[2].getNum(); 1022 x2 = args[2].getNum();
1023 y2 = args[3].getNum(); 1023 y2 = args[3].getNum();
1024 x3 = x2; 1024 x3 = x2;
1025 y3 = y2; 1025 y3 = y2;
1026 state->curveTo(x1, y1, x2, y2, x3, y3); 1026 state->curveTo(x1, y1, x2, y2, x3, y3);
1027} 1027}
1028 1028
1029void Gfx::opRectangle(Object args[], int numArgs) { 1029void Gfx::opRectangle(Object args[], int numArgs) {
1030 fouble x, y, w, h; 1030 fouble x, y, w, h;
1031 1031
1032 x = args[0].getNum(); 1032 x = args[0].getNum();
1033 y = args[1].getNum(); 1033 y = args[1].getNum();
1034 w = args[2].getNum(); 1034 w = args[2].getNum();
1035 h = args[3].getNum(); 1035 h = args[3].getNum();
1036 state->moveTo(x, y); 1036 state->moveTo(x, y);
1037 state->lineTo(x + w, y); 1037 state->lineTo(x + w, y);
1038 state->lineTo(x + w, y + h); 1038 state->lineTo(x + w, y + h);
1039 state->lineTo(x, y + h); 1039 state->lineTo(x, y + h);
1040 state->closePath(); 1040 state->closePath();
1041} 1041}
1042 1042
1043void Gfx::opClosePath(Object args[], int numArgs) { 1043void Gfx::opClosePath(Object args[], int numArgs) {
1044 if (!state->isCurPt()) { 1044 if (!state->isCurPt()) {
1045 error(getPos(), "No current point in closepath"); 1045 error(getPos(), "No current point in closepath");
1046 return; 1046 return;
1047 } 1047 }
1048 state->closePath(); 1048 state->closePath();
1049} 1049}
1050 1050
1051//------------------------------------------------------------------------ 1051//------------------------------------------------------------------------
1052// path painting operators 1052// path painting operators
1053//------------------------------------------------------------------------ 1053//------------------------------------------------------------------------
1054 1054
1055void Gfx::opEndPath(Object args[], int numArgs) { 1055void Gfx::opEndPath(Object args[], int numArgs) {
1056 doEndPath(); 1056 doEndPath();
1057} 1057}
1058 1058
1059void Gfx::opStroke(Object args[], int numArgs) { 1059void Gfx::opStroke(Object args[], int numArgs) {
1060 if (!state->isCurPt()) { 1060 if (!state->isCurPt()) {
1061 //error(getPos(), "No path in stroke"); 1061 //error(getPos(), "No path in stroke");
1062 return; 1062 return;
1063 } 1063 }
1064 if (state->isPath()) 1064 if (state->isPath())
1065 out->stroke(state); 1065 out->stroke(state);
1066 doEndPath(); 1066 doEndPath();
1067} 1067}
1068 1068
1069void Gfx::opCloseStroke(Object args[], int numArgs) { 1069void Gfx::opCloseStroke(Object args[], int numArgs) {
1070 if (!state->isCurPt()) { 1070 if (!state->isCurPt()) {
1071 //error(getPos(), "No path in closepath/stroke"); 1071 //error(getPos(), "No path in closepath/stroke");
1072 return; 1072 return;
1073 } 1073 }
1074 if (state->isPath()) { 1074 if (state->isPath()) {
1075 state->closePath(); 1075 state->closePath();
1076 out->stroke(state); 1076 out->stroke(state);
1077 } 1077 }
1078 doEndPath(); 1078 doEndPath();
1079} 1079}
1080 1080
1081void Gfx::opFill(Object args[], int numArgs) { 1081void Gfx::opFill(Object args[], int numArgs) {
1082 if (!state->isCurPt()) { 1082 if (!state->isCurPt()) {
1083 //error(getPos(), "No path in fill"); 1083 //error(getPos(), "No path in fill");
1084 return; 1084 return;
1085 } 1085 }
1086 if (state->isPath()) { 1086 if (state->isPath()) {
1087 if (state->getFillColorSpace()->getMode() == csPattern) { 1087 if (state->getFillColorSpace()->getMode() == csPattern) {
1088 doPatternFill(gFalse); 1088 doPatternFill(gFalse);
1089 } else { 1089 } else {
1090 out->fill(state); 1090 out->fill(state);
1091 } 1091 }
1092 } 1092 }
1093 doEndPath(); 1093 doEndPath();
1094} 1094}
1095 1095
1096void Gfx::opEOFill(Object args[], int numArgs) { 1096void Gfx::opEOFill(Object args[], int numArgs) {
1097 if (!state->isCurPt()) { 1097 if (!state->isCurPt()) {
1098 //error(getPos(), "No path in eofill"); 1098 //error(getPos(), "No path in eofill");
1099 return; 1099 return;
1100 } 1100 }
1101 if (state->isPath()) { 1101 if (state->isPath()) {
1102 if (state->getFillColorSpace()->getMode() == csPattern) { 1102 if (state->getFillColorSpace()->getMode() == csPattern) {
1103 doPatternFill(gTrue); 1103 doPatternFill(gTrue);
1104 } else { 1104 } else {
1105 out->eoFill(state); 1105 out->eoFill(state);
1106 } 1106 }
1107 } 1107 }
1108 doEndPath(); 1108 doEndPath();
1109} 1109}
1110 1110
1111void Gfx::opFillStroke(Object args[], int numArgs) { 1111void Gfx::opFillStroke(Object args[], int numArgs) {
1112 if (!state->isCurPt()) { 1112 if (!state->isCurPt()) {
1113 //error(getPos(), "No path in fill/stroke"); 1113 //error(getPos(), "No path in fill/stroke");
1114 return; 1114 return;
1115 } 1115 }
1116 if (state->isPath()) { 1116 if (state->isPath()) {
1117 if (state->getFillColorSpace()->getMode() == csPattern) { 1117 if (state->getFillColorSpace()->getMode() == csPattern) {
1118 doPatternFill(gFalse); 1118 doPatternFill(gFalse);
1119 } else { 1119 } else {
1120 out->fill(state); 1120 out->fill(state);
1121 } 1121 }
1122 out->stroke(state); 1122 out->stroke(state);
1123 } 1123 }
1124 doEndPath(); 1124 doEndPath();
1125} 1125}
1126 1126
1127void Gfx::opCloseFillStroke(Object args[], int numArgs) { 1127void Gfx::opCloseFillStroke(Object args[], int numArgs) {
1128 if (!state->isCurPt()) { 1128 if (!state->isCurPt()) {
1129 //error(getPos(), "No path in closepath/fill/stroke"); 1129 //error(getPos(), "No path in closepath/fill/stroke");
1130 return; 1130 return;
1131 } 1131 }
1132 if (state->isPath()) { 1132 if (state->isPath()) {
1133 state->closePath(); 1133 state->closePath();
1134 if (state->getFillColorSpace()->getMode() == csPattern) { 1134 if (state->getFillColorSpace()->getMode() == csPattern) {
1135 doPatternFill(gFalse); 1135 doPatternFill(gFalse);
1136 } else { 1136 } else {
1137 out->fill(state); 1137 out->fill(state);
1138 } 1138 }
1139 out->stroke(state); 1139 out->stroke(state);
1140 } 1140 }
1141 doEndPath(); 1141 doEndPath();
1142} 1142}
1143 1143
1144void Gfx::opEOFillStroke(Object args[], int numArgs) { 1144void Gfx::opEOFillStroke(Object args[], int numArgs) {
1145 if (!state->isCurPt()) { 1145 if (!state->isCurPt()) {
1146 //error(getPos(), "No path in eofill/stroke"); 1146 //error(getPos(), "No path in eofill/stroke");
1147 return; 1147 return;
1148 } 1148 }
1149 if (state->isPath()) { 1149 if (state->isPath()) {
1150 if (state->getFillColorSpace()->getMode() == csPattern) { 1150 if (state->getFillColorSpace()->getMode() == csPattern) {
1151 doPatternFill(gTrue); 1151 doPatternFill(gTrue);
1152 } else { 1152 } else {
1153 out->eoFill(state); 1153 out->eoFill(state);
1154 } 1154 }
1155 out->stroke(state); 1155 out->stroke(state);
1156 } 1156 }
1157 doEndPath(); 1157 doEndPath();
1158} 1158}
1159 1159
1160void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { 1160void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
1161 if (!state->isCurPt()) { 1161 if (!state->isCurPt()) {
1162 //error(getPos(), "No path in closepath/eofill/stroke"); 1162 //error(getPos(), "No path in closepath/eofill/stroke");
1163 return; 1163 return;
1164 } 1164 }
1165 if (state->isPath()) { 1165 if (state->isPath()) {
1166 state->closePath(); 1166 state->closePath();
1167 if (state->getFillColorSpace()->getMode() == csPattern) { 1167 if (state->getFillColorSpace()->getMode() == csPattern) {
1168 doPatternFill(gTrue); 1168 doPatternFill(gTrue);
1169 } else { 1169 } else {
1170 out->eoFill(state); 1170 out->eoFill(state);
1171 } 1171 }
1172 out->stroke(state); 1172 out->stroke(state);
1173 } 1173 }
1174 doEndPath(); 1174 doEndPath();
1175} 1175}
1176 1176
1177void Gfx::doPatternFill(GBool eoFill) { 1177void Gfx::doPatternFill(GBool eoFill) {
1178 GfxPatternColorSpace *patCS; 1178 GfxPatternColorSpace *patCS;
1179 GfxPattern *pattern; 1179 GfxPattern *pattern;
1180 GfxTilingPattern *tPat; 1180 GfxTilingPattern *tPat;
1181 GfxColorSpace *cs; 1181 GfxColorSpace *cs;
1182 fouble xMin, yMin, xMax, yMax, x, y, x1, y1; 1182 fouble xMin, yMin, xMax, yMax, x, y, x1, y1;
1183 fouble cxMin, cyMin, cxMax, cyMax; 1183 fouble cxMin, cyMin, cxMax, cyMax;
1184 int xi0, yi0, xi1, yi1, xi, yi; 1184 int xi0, yi0, xi1, yi1, xi, yi;
1185 fouble *ctm, *btm, *ptm; 1185 fouble *ctm, *btm, *ptm;
1186 fouble m[6], ictm[6], m1[6], imb[6]; 1186 fouble m[6], ictm[6], m1[6], imb[6];
1187 fouble det; 1187 fouble det;
1188 fouble xstep, ystep; 1188 fouble xstep, ystep;
1189 int i; 1189 int i;
1190 1190
1191 // this is a bit of a kludge -- patterns can be really slow, so we 1191 // this is a bit of a kludge -- patterns can be really slow, so we
1192 // skip them if we're only doing text extraction, since they almost 1192 // skip them if we're only doing text extraction, since they almost
1193 // certainly don't contain any text 1193 // certainly don't contain any text
1194 if (!out->needNonText()) { 1194 if (!out->needNonText()) {
1195 return; 1195 return;
1196 } 1196 }
1197 1197
1198 // get color space 1198 // get color space
1199 patCS = (GfxPatternColorSpace *)state->getFillColorSpace(); 1199 patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
1200 1200
1201 // get pattern 1201 // get pattern
1202 if (!(pattern = state->getFillPattern())) { 1202 if (!(pattern = state->getFillPattern())) {
1203 return; 1203 return;
1204 } 1204 }
1205 if (pattern->getType() != 1) { 1205 if (pattern->getType() != 1) {
1206 return; 1206 return;
1207 } 1207 }
1208 tPat = (GfxTilingPattern *)pattern; 1208 tPat = (GfxTilingPattern *)pattern;
1209 1209
1210 // construct a (pattern space) -> (current space) transform matrix 1210 // construct a (pattern space) -> (current space) transform matrix
1211 ctm = state->getCTM(); 1211 ctm = state->getCTM();
1212 btm = baseMatrix; 1212 btm = baseMatrix;
1213 ptm = tPat->getMatrix(); 1213 ptm = tPat->getMatrix();
1214 // iCTM = invert CTM 1214 // iCTM = invert CTM
1215 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); 1215 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
1216 ictm[0] = ctm[3] * det; 1216 ictm[0] = ctm[3] * det;
1217 ictm[1] = -ctm[1] * det; 1217 ictm[1] = -ctm[1] * det;
1218 ictm[2] = -ctm[2] * det; 1218 ictm[2] = -ctm[2] * det;
1219 ictm[3] = ctm[0] * det; 1219 ictm[3] = ctm[0] * det;
1220 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; 1220 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
1221 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; 1221 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
1222 // m1 = PTM * BTM = PTM * base transform matrix 1222 // m1 = PTM * BTM = PTM * base transform matrix
1223 m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; 1223 m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
1224 m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; 1224 m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
1225 m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; 1225 m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
1226 m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; 1226 m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
1227 m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; 1227 m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
1228 m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; 1228 m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
1229 // m = m1 * iCTM = (PTM * BTM) * (iCTM) 1229 // m = m1 * iCTM = (PTM * BTM) * (iCTM)
1230 m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; 1230 m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
1231 m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; 1231 m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
1232 m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; 1232 m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
1233 m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; 1233 m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
1234 m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; 1234 m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
1235 m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; 1235 m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
1236 1236
1237 // construct a (base space) -> (pattern space) transform matrix 1237 // construct a (base space) -> (pattern space) transform matrix
1238 det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]); 1238 det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
1239 imb[0] = m1[3] * det; 1239 imb[0] = m1[3] * det;
1240 imb[1] = -m1[1] * det; 1240 imb[1] = -m1[1] * det;
1241 imb[2] = -m1[2] * det; 1241 imb[2] = -m1[2] * det;
1242 imb[3] = m1[0] * det; 1242 imb[3] = m1[0] * det;
1243 imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det; 1243 imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
1244 imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; 1244 imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
1245 1245
1246 // save current graphics state 1246 // save current graphics state
1247 out->saveState(state); 1247 out->saveState(state);
1248 state = state->save(); 1248 state = state->save();
1249 1249
1250 // set underlying color space (for uncolored tiling patterns) 1250 // set underlying color space (for uncolored tiling patterns)
1251 if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { 1251 if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
1252 state->setFillColorSpace(cs->copy()); 1252 state->setFillColorSpace(cs->copy());
1253 } else { 1253 } else {
1254 state->setFillColorSpace(new GfxDeviceGrayColorSpace()); 1254 state->setFillColorSpace(new GfxDeviceGrayColorSpace());
1255 } 1255 }
1256 state->setFillPattern(NULL); 1256 state->setFillPattern(NULL);
1257 out->updateFillColor(state); 1257 out->updateFillColor(state);
1258 1258
1259 // clip to current path 1259 // clip to current path
1260 state->clip(); 1260 state->clip();
1261 if (eoFill) { 1261 if (eoFill) {
1262 out->eoClip(state); 1262 out->eoClip(state);
1263 } else { 1263 } else {
1264 out->clip(state); 1264 out->clip(state);
1265 } 1265 }
1266 state->clearPath(); 1266 state->clearPath();
1267 1267
1268 // transform clip region bbox to pattern space 1268 // transform clip region bbox to pattern space
1269 state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax); 1269 state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
1270 xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4]; 1270 xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
1271 yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5]; 1271 yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
1272 x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4]; 1272 x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
1273 y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5]; 1273 y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
1274 if (x1 < xMin) { 1274 if (x1 < xMin) {
1275 xMin = x1; 1275 xMin = x1;
1276 } else if (x1 > xMax) { 1276 } else if (x1 > xMax) {
1277 xMax = x1; 1277 xMax = x1;
1278 } 1278 }
1279 if (y1 < yMin) { 1279 if (y1 < yMin) {
1280 yMin = y1; 1280 yMin = y1;
1281 } else if (y1 > yMax) { 1281 } else if (y1 > yMax) {
1282 yMax = y1; 1282 yMax = y1;
1283 } 1283 }
1284 x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4]; 1284 x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
1285 y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5]; 1285 y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
1286 if (x1 < xMin) { 1286 if (x1 < xMin) {
1287 xMin = x1; 1287 xMin = x1;
1288 } else if (x1 > xMax) { 1288 } else if (x1 > xMax) {
1289 xMax = x1; 1289 xMax = x1;
1290 } 1290 }
1291 if (y1 < yMin) { 1291 if (y1 < yMin) {
1292 yMin = y1; 1292 yMin = y1;
1293 } else if (y1 > yMax) { 1293 } else if (y1 > yMax) {
1294 yMax = y1; 1294 yMax = y1;
1295 } 1295 }
1296 x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4]; 1296 x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
1297 y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5]; 1297 y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
1298 if (x1 < xMin) { 1298 if (x1 < xMin) {
1299 xMin = x1; 1299 xMin = x1;
1300 } else if (x1 > xMax) { 1300 } else if (x1 > xMax) {
1301 xMax = x1; 1301 xMax = x1;
1302 } 1302 }
1303 if (y1 < yMin) { 1303 if (y1 < yMin) {
1304 yMin = y1; 1304 yMin = y1;
1305 } else if (y1 > yMax) { 1305 } else if (y1 > yMax) {
1306 yMax = y1; 1306 yMax = y1;
1307 } 1307 }
1308 1308
1309 // draw the pattern 1309 // draw the pattern
1310 //~ this should treat negative steps differently -- start at right/top 1310 //~ this should treat negative steps differently -- start at right/top
1311 //~ edge instead of left/bottom (?) 1311 //~ edge instead of left/bottom (?)
1312 xstep = fabs(tPat->getXStep()); 1312 xstep = fabs(tPat->getXStep());
1313 ystep = fabs(tPat->getYStep()); 1313 ystep = fabs(tPat->getYStep());
1314 xi0 = (int)floor(xMin / xstep); 1314 xi0 = (int)floor(xMin / xstep);
1315 xi1 = (int)ceil(xMax / xstep); 1315 xi1 = (int)ceil(xMax / xstep);
1316 yi0 = (int)floor(yMin / ystep); 1316 yi0 = (int)floor(yMin / ystep);
1317 yi1 = (int)ceil(yMax / ystep); 1317 yi1 = (int)ceil(yMax / ystep);
1318 for (i = 0; i < 4; ++i) { 1318 for (i = 0; i < 4; ++i) {
1319 m1[i] = m[i]; 1319 m1[i] = m[i];
1320 } 1320 }
1321 for (yi = yi0; yi < yi1; ++yi) { 1321 for (yi = yi0; yi < yi1; ++yi) {
1322 for (xi = xi0; xi < xi1; ++xi) { 1322 for (xi = xi0; xi < xi1; ++xi) {
1323 x = xi * xstep; 1323 x = xi * xstep;
1324 y = yi * ystep; 1324 y = yi * ystep;
1325 m1[4] = x * m[0] + y * m[2] + m[4]; 1325 m1[4] = x * m[0] + y * m[2] + m[4];
1326 m1[5] = x * m[1] + y * m[3] + m[5]; 1326 m1[5] = x * m[1] + y * m[3] + m[5];
1327 doForm1(tPat->getContentStream(), tPat->getResDict(), 1327 doForm1(tPat->getContentStream(), tPat->getResDict(),
1328 m1, tPat->getBBox()); 1328 m1, tPat->getBBox());
1329 } 1329 }
1330 } 1330 }
1331 1331
1332 // restore graphics state 1332 // restore graphics state
1333 state = state->restore(); 1333 state = state->restore();
1334 out->restoreState(state); 1334 out->restoreState(state);
1335} 1335}
1336 1336
1337void Gfx::opShFill(Object args[], int numArgs) { 1337void Gfx::opShFill(Object args[], int numArgs) {
1338 GfxShading *shading; 1338 GfxShading *shading;
1339 fouble xMin, yMin, xMax, yMax; 1339 fouble xMin, yMin, xMax, yMax;
1340 1340
1341 if (!(shading = res->lookupShading(args[0].getName()))) { 1341 if (!(shading = res->lookupShading(args[0].getName()))) {
1342 return; 1342 return;
1343 } 1343 }
1344 1344
1345 // save current graphics state 1345 // save current graphics state
1346 out->saveState(state); 1346 out->saveState(state);
1347 state = state->save(); 1347 state = state->save();
1348 1348
1349 // clip to bbox 1349 // clip to bbox
1350 if (shading->getHasBBox()) { 1350 if (shading->getHasBBox()) {
1351 shading->getBBox(&xMin, &yMin, &xMax, &yMax); 1351 shading->getBBox(&xMin, &yMin, &xMax, &yMax);
1352 state->moveTo(xMin, yMin); 1352 state->moveTo(xMin, yMin);
1353 state->lineTo(xMax, yMin); 1353 state->lineTo(xMax, yMin);
1354 state->lineTo(xMax, yMax); 1354 state->lineTo(xMax, yMax);
1355 state->lineTo(xMin, yMax); 1355 state->lineTo(xMin, yMax);
1356 state->closePath(); 1356 state->closePath();
1357 state->clip(); 1357 state->clip();
1358 out->clip(state); 1358 out->clip(state);
1359 state->clearPath(); 1359 state->clearPath();
1360 } 1360 }
1361 1361
1362 // set the color space 1362 // set the color space
1363 state->setFillColorSpace(shading->getColorSpace()->copy()); 1363 state->setFillColorSpace(shading->getColorSpace()->copy());
1364 1364
1365 // do shading type-specific operations 1365 // do shading type-specific operations
1366 switch (shading->getType()) { 1366 switch (shading->getType()) {
1367 case 2: 1367 case 2:
1368 doAxialShFill((GfxAxialShading *)shading); 1368 doAxialShFill((GfxAxialShading *)shading);
1369 break; 1369 break;
1370 case 3: 1370 case 3:
1371 doRadialShFill((GfxRadialShading *)shading); 1371 doRadialShFill((GfxRadialShading *)shading);
1372 break; 1372 break;
1373 } 1373 }
1374 1374
1375 // restore graphics state 1375 // restore graphics state
1376 state = state->restore(); 1376 state = state->restore();
1377 out->restoreState(state); 1377 out->restoreState(state);
1378 1378
1379 delete shading; 1379 delete shading;
1380} 1380}
1381 1381
1382void Gfx::doAxialShFill(GfxAxialShading *shading) { 1382void Gfx::doAxialShFill(GfxAxialShading *shading) {
1383 fouble xMin, yMin, xMax, yMax; 1383 fouble xMin, yMin, xMax, yMax;
1384 fouble x0, y0, x1, y1; 1384 fouble x0, y0, x1, y1;
1385 fouble dx, dy, mul; 1385 fouble dx, dy, mul;
1386 fouble tMin, tMax, t, tx, ty; 1386 fouble tMin, tMax, t, tx, ty;
1387 fouble s[4], sMin, sMax, tmp; 1387 fouble s[4], sMin, sMax, tmp;
1388 fouble ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1; 1388 fouble ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
1389 fouble t0, t1, tt; 1389 fouble t0, t1, tt;
1390 fouble ta[axialMaxSplits + 1]; 1390 fouble ta[axialMaxSplits + 1];
1391 int next[axialMaxSplits + 1]; 1391 int next[axialMaxSplits + 1];
1392 GfxColor color0, color1; 1392 GfxColor color0, color1;
1393 int nComps; 1393 int nComps;
1394 int i, j, k, kk; 1394 int i, j, k, kk;
1395 1395
1396 // get the clip region bbox 1396 // get the clip region bbox
1397 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); 1397 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
1398 1398
1399 // compute min and max t values, based on the four corners of the 1399 // compute min and max t values, based on the four corners of the
1400 // clip region bbox 1400 // clip region bbox
1401 shading->getCoords(&x0, &y0, &x1, &y1); 1401 shading->getCoords(&x0, &y0, &x1, &y1);
1402 dx = x1 - x0; 1402 dx = x1 - x0;
1403 dy = y1 - y0; 1403 dy = y1 - y0;
1404 mul = 1 / (dx * dx + dy * dy); 1404 mul = 1 / (dx * dx + dy * dy);
1405 tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; 1405 tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
1406 t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; 1406 t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
1407 if (t < tMin) { 1407 if (t < tMin) {
1408 tMin = t; 1408 tMin = t;
1409 } else if (t > tMax) { 1409 } else if (t > tMax) {
1410 tMax = t; 1410 tMax = t;
1411 } 1411 }
1412 t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; 1412 t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
1413 if (t < tMin) { 1413 if (t < tMin) {
1414 tMin = t; 1414 tMin = t;
1415 } else if (t > tMax) { 1415 } else if (t > tMax) {
1416 tMax = t; 1416 tMax = t;
1417 } 1417 }
1418 t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; 1418 t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
1419 if (t < tMin) { 1419 if (t < tMin) {
1420 tMin = t; 1420 tMin = t;
1421 } else if (t > tMax) { 1421 } else if (t > tMax) {
1422 tMax = t; 1422 tMax = t;
1423 } 1423 }
1424 if (tMin < 0 && !shading->getExtend0()) { 1424 if (tMin < 0 && !shading->getExtend0()) {
1425 tMin = 0; 1425 tMin = 0;
1426 } 1426 }
1427 if (tMax > 1 && !shading->getExtend1()) { 1427 if (tMax > 1 && !shading->getExtend1()) {
1428 tMax = 1; 1428 tMax = 1;
1429 } 1429 }
1430 1430
1431 // get the function domain 1431 // get the function domain
1432 t0 = shading->getDomain0(); 1432 t0 = shading->getDomain0();
1433 t1 = shading->getDomain1(); 1433 t1 = shading->getDomain1();
1434 1434
1435 // Traverse the t axis and do the shading. 1435 // Traverse the t axis and do the shading.
1436 // 1436 //
1437 // For each point (tx, ty) on the t axis, consider a line through 1437 // For each point (tx, ty) on the t axis, consider a line through
1438 // that point perpendicular to the t axis: 1438 // that point perpendicular to the t axis:
1439 // 1439 //
1440 // x(s) = tx + s * -dy --> s = (x - tx) / -dy 1440 // x(s) = tx + s * -dy --> s = (x - tx) / -dy
1441 // y(s) = ty + s * dx --> s = (y - ty) / dx 1441 // y(s) = ty + s * dx --> s = (y - ty) / dx
1442 // 1442 //
1443 // Then look at the intersection of this line with the bounding box 1443 // Then look at the intersection of this line with the bounding box
1444 // (xMin, yMin, xMax, yMax). In the general case, there are four 1444 // (xMin, yMin, xMax, yMax). In the general case, there are four
1445 // intersection points: 1445 // intersection points:
1446 // 1446 //
1447 // s0 = (xMin - tx) / -dy 1447 // s0 = (xMin - tx) / -dy
1448 // s1 = (xMax - tx) / -dy 1448 // s1 = (xMax - tx) / -dy
1449 // s2 = (yMin - ty) / dx 1449 // s2 = (yMin - ty) / dx
1450 // s3 = (yMax - ty) / dx 1450 // s3 = (yMax - ty) / dx
1451 // 1451 //
1452 // and we want the middle two s values. 1452 // and we want the middle two s values.
1453 // 1453 //
1454 // In the case where dx = 0, take s0 and s1; in the case where dy = 1454 // In the case where dx = 0, take s0 and s1; in the case where dy =
1455 // 0, take s2 and s3. 1455 // 0, take s2 and s3.
1456 // 1456 //
1457 // Each filled polygon is bounded by two of these line segments 1457 // Each filled polygon is bounded by two of these line segments
1458 // perpdendicular to the t axis. 1458 // perpdendicular to the t axis.
1459 // 1459 //
1460 // The t axis is bisected into smaller regions until the color 1460 // The t axis is bisected into smaller regions until the color
1461 // difference across a region is small enough, and then the region 1461 // difference across a region is small enough, and then the region
1462 // is painted with a single color. 1462 // is painted with a single color.
1463 1463
1464 // set up 1464 // set up
1465 nComps = shading->getColorSpace()->getNComps(); 1465 nComps = shading->getColorSpace()->getNComps();
1466 ta[0] = tMin; 1466 ta[0] = tMin;
1467 ta[axialMaxSplits] = tMax; 1467 ta[axialMaxSplits] = tMax;
1468 next[0] = axialMaxSplits; 1468 next[0] = axialMaxSplits;
1469 1469
1470 // compute the color at t = tMin 1470 // compute the color at t = tMin
1471 if (tMin < 0) { 1471 if (tMin < 0) {
1472 tt = t0; 1472 tt = t0;
1473 } else if (tMin > 1) { 1473 } else if (tMin > 1) {
1474 tt = t1; 1474 tt = t1;
1475 } else { 1475 } else {
1476 tt = t0 + (t1 - t0) * tMin; 1476 tt = t0 + (t1 - t0) * tMin;
1477 } 1477 }
1478 shading->getColor(tt, &color0); 1478 shading->getColor(tt, &color0);
1479 1479
1480 // compute the coordinates of the point on the t axis at t = tMin; 1480 // compute the coordinates of the point on the t axis at t = tMin;
1481 // then compute the intersection of the perpendicular line with the 1481 // then compute the intersection of the perpendicular line with the
1482 // bounding box 1482 // bounding box
1483 tx = x0 + tMin * dx; 1483 tx = x0 + tMin * dx;
1484 ty = y0 + tMin * dy; 1484 ty = y0 + tMin * dy;
1485 if (dx == 0 && dy == 0) { 1485 if (dx == 0 && dy == 0) {
1486 sMin = sMax = 0; 1486 sMin = sMax = 0;
1487 } if (dx == 0) { 1487 } if (dx == 0) {
1488 sMin = (xMin - tx) / -dy; 1488 sMin = (xMin - tx) / -dy;
1489 sMax = (xMax - tx) / -dy; 1489 sMax = (xMax - tx) / -dy;
1490 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } 1490 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1491 } else if (dy == 0) { 1491 } else if (dy == 0) {
1492 sMin = (yMin - ty) / dx; 1492 sMin = (yMin - ty) / dx;
1493 sMax = (yMax - ty) / dx; 1493 sMax = (yMax - ty) / dx;
1494 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } 1494 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1495 } else { 1495 } else {
1496 s[0] = (yMin - ty) / dx; 1496 s[0] = (yMin - ty) / dx;
1497 s[1] = (yMax - ty) / dx; 1497 s[1] = (yMax - ty) / dx;
1498 s[2] = (xMin - tx) / -dy; 1498 s[2] = (xMin - tx) / -dy;
1499 s[3] = (xMax - tx) / -dy; 1499 s[3] = (xMax - tx) / -dy;
1500 for (j = 0; j < 3; ++j) { 1500 for (j = 0; j < 3; ++j) {
1501 kk = j; 1501 kk = j;
1502 for (k = j + 1; k < 4; ++k) { 1502 for (k = j + 1; k < 4; ++k) {
1503 if (s[k] < s[kk]) { 1503 if (s[k] < s[kk]) {
1504 kk = k; 1504 kk = k;
1505 } 1505 }
1506 } 1506 }
1507 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; 1507 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
1508 } 1508 }
1509 sMin = s[1]; 1509 sMin = s[1];
1510 sMax = s[2]; 1510 sMax = s[2];
1511 } 1511 }
1512 ux0 = tx - sMin * dy; 1512 ux0 = tx - sMin * dy;
1513 uy0 = ty + sMin * dx; 1513 uy0 = ty + sMin * dx;
1514 vx0 = tx - sMax * dy; 1514 vx0 = tx - sMax * dy;
1515 vy0 = ty + sMax * dx; 1515 vy0 = ty + sMax * dx;
1516 1516
1517 i = 0; 1517 i = 0;
1518 while (i < axialMaxSplits) { 1518 while (i < axialMaxSplits) {
1519 1519
1520 // bisect until color difference is small enough or we hit the 1520 // bisect until color difference is small enough or we hit the
1521 // bisection limit 1521 // bisection limit
1522 j = next[i]; 1522 j = next[i];
1523 while (j > i + 1) { 1523 while (j > i + 1) {
1524 if (ta[j] < 0) { 1524 if (ta[j] < 0) {
1525 tt = t0; 1525 tt = t0;
1526 } else if (ta[j] > 1) { 1526 } else if (ta[j] > 1) {
1527 tt = t1; 1527 tt = t1;
1528 } else { 1528 } else {
1529 tt = t0 + (t1 - t0) * ta[j]; 1529 tt = t0 + (t1 - t0) * ta[j];
1530 } 1530 }
1531 shading->getColor(tt, &color1); 1531 shading->getColor(tt, &color1);
1532 for (k = 0; k < nComps; ++k) { 1532 for (k = 0; k < nComps; ++k) {
1533 if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) { 1533 if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {
1534 break; 1534 break;
1535 } 1535 }
1536 } 1536 }
1537 if (k == nComps) { 1537 if (k == nComps) {
1538 break; 1538 break;
1539 } 1539 }
1540 k = (i + j) / 2; 1540 k = (i + j) / 2;
1541 ta[k] = 0.5 * (ta[i] + ta[j]); 1541 ta[k] = 0.5 * (ta[i] + ta[j]);
1542 next[i] = k; 1542 next[i] = k;
1543 next[k] = j; 1543 next[k] = j;
1544 j = k; 1544 j = k;
1545 } 1545 }
1546 1546
1547 // use the average of the colors of the two sides of the region 1547 // use the average of the colors of the two sides of the region
1548 for (k = 0; k < nComps; ++k) { 1548 for (k = 0; k < nComps; ++k) {
1549 color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]); 1549 color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]);
1550 } 1550 }
1551 1551
1552 // compute the coordinates of the point on the t axis; then 1552 // compute the coordinates of the point on the t axis; then
1553 // compute the intersection of the perpendicular line with the 1553 // compute the intersection of the perpendicular line with the
1554 // bounding box 1554 // bounding box
1555 tx = x0 + ta[j] * dx; 1555 tx = x0 + ta[j] * dx;
1556 ty = y0 + ta[j] * dy; 1556 ty = y0 + ta[j] * dy;
1557 if (dx == 0 && dy == 0) { 1557 if (dx == 0 && dy == 0) {
1558 sMin = sMax = 0; 1558 sMin = sMax = 0;
1559 } if (dx == 0) { 1559 } if (dx == 0) {
1560 sMin = (xMin - tx) / -dy; 1560 sMin = (xMin - tx) / -dy;
1561 sMax = (xMax - tx) / -dy; 1561 sMax = (xMax - tx) / -dy;
1562 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } 1562 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1563 } else if (dy == 0) { 1563 } else if (dy == 0) {
1564 sMin = (yMin - ty) / dx; 1564 sMin = (yMin - ty) / dx;
1565 sMax = (yMax - ty) / dx; 1565 sMax = (yMax - ty) / dx;
1566 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } 1566 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1567 } else { 1567 } else {
1568 s[0] = (yMin - ty) / dx; 1568 s[0] = (yMin - ty) / dx;
1569 s[1] = (yMax - ty) / dx; 1569 s[1] = (yMax - ty) / dx;
1570 s[2] = (xMin - tx) / -dy; 1570 s[2] = (xMin - tx) / -dy;
1571 s[3] = (xMax - tx) / -dy; 1571 s[3] = (xMax - tx) / -dy;
1572 for (j = 0; j < 3; ++j) { 1572 for (j = 0; j < 3; ++j) {
1573 kk = j; 1573 kk = j;
1574 for (k = j + 1; k < 4; ++k) { 1574 for (k = j + 1; k < 4; ++k) {
1575 if (s[k] < s[kk]) { 1575 if (s[k] < s[kk]) {
1576 kk = k; 1576 kk = k;
1577 } 1577 }
1578 } 1578 }
1579 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; 1579 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
1580 } 1580 }
1581 sMin = s[1]; 1581 sMin = s[1];
1582 sMax = s[2]; 1582 sMax = s[2];
1583 } 1583 }
1584 ux1 = tx - sMin * dy; 1584 ux1 = tx - sMin * dy;
1585 uy1 = ty + sMin * dx; 1585 uy1 = ty + sMin * dx;
1586 vx1 = tx - sMax * dy; 1586 vx1 = tx - sMax * dy;
1587 vy1 = ty + sMax * dx; 1587 vy1 = ty + sMax * dx;
1588 1588
1589 // set the color 1589 // set the color
1590 state->setFillColor(&color0); 1590 state->setFillColor(&color0);
1591 out->updateFillColor(state); 1591 out->updateFillColor(state);
1592 1592
1593 // fill the region 1593 // fill the region
1594 state->moveTo(ux0, uy0); 1594 state->moveTo(ux0, uy0);
1595 state->lineTo(vx0, vy0); 1595 state->lineTo(vx0, vy0);
1596 state->lineTo(vx1, vy1); 1596 state->lineTo(vx1, vy1);
1597 state->lineTo(ux1, uy1); 1597 state->lineTo(ux1, uy1);
1598 state->closePath(); 1598 state->closePath();
1599 out->fill(state); 1599 out->fill(state);
1600 state->clearPath(); 1600 state->clearPath();
1601 1601
1602 // set up for next region 1602 // set up for next region
1603 ux0 = ux1; 1603 ux0 = ux1;
1604 uy0 = uy1; 1604 uy0 = uy1;
1605 vx0 = vx1; 1605 vx0 = vx1;
1606 vy0 = vy1; 1606 vy0 = vy1;
1607 color0 = color1; 1607 color0 = color1;
1608 i = next[i]; 1608 i = next[i];
1609 } 1609 }
1610} 1610}
1611 1611
1612void Gfx::doRadialShFill(GfxRadialShading *shading) { 1612void Gfx::doRadialShFill(GfxRadialShading *shading) {
1613 fouble sMin, sMax, xMin, yMin, xMax, yMax; 1613 fouble sMin, sMax, xMin, yMin, xMax, yMax;
1614 fouble x0, y0, r0, x1, y1, r1, t0, t1; 1614 fouble x0, y0, r0, x1, y1, r1, t0, t1;
1615 int nComps; 1615 int nComps;
1616 GfxColor colorA, colorB; 1616 GfxColor colorA, colorB;
1617 fouble xa, ya, xb, yb, ra, rb; 1617 fouble xa, ya, xb, yb, ra, rb;
1618 fouble ta, tb, sa, sb; 1618 fouble ta, tb, sa, sb;
1619 int ia, ib, k, n; 1619 int ia, ib, k, n;
1620 fouble *ctm; 1620 fouble *ctm;
1621 fouble angle, t; 1621 fouble angle, t;
1622 1622
1623 // get the shading info 1623 // get the shading info
1624 shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); 1624 shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
1625 t0 = shading->getDomain0(); 1625 t0 = shading->getDomain0();
1626 t1 = shading->getDomain1(); 1626 t1 = shading->getDomain1();
1627 nComps = shading->getColorSpace()->getNComps(); 1627 nComps = shading->getColorSpace()->getNComps();
1628 1628
1629 // compute the (possibly extended) s range 1629 // compute the (possibly extended) s range
1630 sMin = 0; 1630 sMin = 0;
1631 sMax = 1; 1631 sMax = 1;
1632 if (shading->getExtend0()) { 1632 if (shading->getExtend0()) {
1633 if (r0 < r1) { 1633 if (r0 < r1) {
1634 // extend the smaller end 1634 // extend the smaller end
1635 sMin = -r0 / (r1 - r0); 1635 sMin = -r0 / (r1 - r0);
1636 } else { 1636 } else {
1637 // extend the larger end 1637 // extend the larger end
1638 //~ this computes the diagonal of the bounding box -- we should 1638 //~ this computes the diagonal of the bounding box -- we should
1639 //~ really compute the intersection of the moving/expanding 1639 //~ really compute the intersection of the moving/expanding
1640 //~ circles with each of the four corners and look for the max 1640 //~ circles with each of the four corners and look for the max
1641 //~ radius 1641 //~ radius
1642 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); 1642 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
1643 sMin = (sqrt((xMax - xMin) * (xMax - xMin) + 1643 sMin = (sqrt((xMax - xMin) * (xMax - xMin) +
1644 (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0); 1644 (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
1645 if (sMin > 0) { 1645 if (sMin > 0) {
1646 sMin = 0; 1646 sMin = 0;
1647 } else if (sMin < -20) { 1647 } else if (sMin < -20) {
1648 // sanity check 1648 // sanity check
1649 sMin = -20; 1649 sMin = -20;
1650 } 1650 }
1651 } 1651 }
1652 } 1652 }
1653 if (shading->getExtend1()) { 1653 if (shading->getExtend1()) {
1654 if (r1 < r0) { 1654 if (r1 < r0) {
1655 // extend the smaller end 1655 // extend the smaller end
1656 sMax = -r0 / (r1 - r0); 1656 sMax = -r0 / (r1 - r0);
1657 } else if (r1 > r0) { 1657 } else if (r1 > r0) {
1658 // extend the larger end 1658 // extend the larger end
1659 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); 1659 state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
1660 sMax = (sqrt((xMax - xMin) * (xMax - xMin) + 1660 sMax = (sqrt((xMax - xMin) * (xMax - xMin) +
1661 (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0); 1661 (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
1662 if (sMax < 1) { 1662 if (sMax < 1) {
1663 sMin = 1; 1663 sMin = 1;
1664 } else if (sMax > 20) { 1664 } else if (sMax > 20) {
1665 // sanity check 1665 // sanity check
1666 sMax = 20; 1666 sMax = 20;
1667 } 1667 }
1668 } 1668 }
1669 } 1669 }
1670 1670
1671 // compute the number of steps into which circles must be divided to 1671 // compute the number of steps into which circles must be divided to
1672 // achieve a curve flatness of 0.1 pixel in device space for the 1672 // achieve a curve flatness of 0.1 pixel in device space for the
1673 // largest circle (note that "device space" is 72 dpi when generating 1673 // largest circle (note that "device space" is 72 dpi when generating
1674 // PostScript, hence the relatively small 0.1 pixel accuracy) 1674 // PostScript, hence the relatively small 0.1 pixel accuracy)
1675 ctm = state->getCTM(); 1675 ctm = state->getCTM();
1676 t = fabs(ctm[0]); 1676 t = fabs(ctm[0]);
1677 if (fabs(ctm[1]) > t) { 1677 if (fabs(ctm[1]) > t) {
1678 t = fabs(ctm[1]); 1678 t = fabs(ctm[1]);
1679 } 1679 }
1680 if (fabs(ctm[2]) > t) { 1680 if (fabs(ctm[2]) > t) {
1681 t = fabs(ctm[2]); 1681 t = fabs(ctm[2]);
1682 } 1682 }
1683 if (fabs(ctm[3]) > t) { 1683 if (fabs(ctm[3]) > t) {
1684 t = fabs(ctm[3]); 1684 t = fabs(ctm[3]);
1685 } 1685 }
1686 if (r0 > r1) { 1686 if (r0 > r1) {
1687 t *= r0; 1687 t *= r0;
1688 } else { 1688 } else {
1689 t *= r1; 1689 t *= r1;
1690 } 1690 }
1691 if (t < 1) { 1691 if (t < 1) {
1692 n = 3; 1692 n = 3;
1693 } else { 1693 } else {
1694 n = (int)(M_PI / acos(1 - 0.1 / t)); 1694 n = (int)(M_PI / acos(1 - 0.1 / t));
1695 if (n < 3) { 1695 if (n < 3) {
1696 n = 3; 1696 n = 3;
1697 } else if (n > 200) { 1697 } else if (n > 200) {
1698 n = 200; 1698 n = 200;
1699 } 1699 }
1700 } 1700 }
1701 1701
1702 // Traverse the t axis and do the shading. 1702 // Traverse the t axis and do the shading.
1703 // 1703 //
1704 // This generates and fills a series of rings. Each ring is defined 1704 // This generates and fills a series of rings. Each ring is defined
1705 // by two circles: 1705 // by two circles:
1706 // sa, ta, xa, ya, ra, colorA 1706 // sa, ta, xa, ya, ra, colorA
1707 // sb, tb, xb, yb, rb, colorB 1707 // sb, tb, xb, yb, rb, colorB
1708 // 1708 //
1709 // The s/t axis is divided into radialMaxSplits parts; these parts 1709 // The s/t axis is divided into radialMaxSplits parts; these parts
1710 // are combined as much as possible while respecting the 1710 // are combined as much as possible while respecting the
1711 // radialColorDelta parameter. 1711 // radialColorDelta parameter.
1712 1712
1713 // setup for the start circle 1713 // setup for the start circle
1714 ia = 0; 1714 ia = 0;
1715 sa = sMin; 1715 sa = sMin;
1716 ta = t0 + sa * (t1 - t0); 1716 ta = t0 + sa * (t1 - t0);
1717 xa = x0 + sa * (x1 - x0); 1717 xa = x0 + sa * (x1 - x0);
1718 ya = y0 + sa * (y1 - y0); 1718 ya = y0 + sa * (y1 - y0);
1719 ra = r0 + sa * (r1 - r0); 1719 ra = r0 + sa * (r1 - r0);
1720 if (ta < t0) { 1720 if (ta < t0) {
1721 shading->getColor(t0, &colorA); 1721 shading->getColor(t0, &colorA);
1722 } else if (ta > t1) { 1722 } else if (ta > t1) {
1723 shading->getColor(t1, &colorA); 1723 shading->getColor(t1, &colorA);
1724 } else { 1724 } else {
1725 shading->getColor(ta, &colorA); 1725 shading->getColor(ta, &colorA);
1726 } 1726 }
1727 1727
1728 while (ia < radialMaxSplits) { 1728 while (ia < radialMaxSplits) {
1729 1729
1730 // go as far along the t axis (toward t1) as we can, such that the 1730 // go as far along the t axis (toward t1) as we can, such that the
1731 // color difference is within the tolerance (radialColorDelta) -- 1731 // color difference is within the tolerance (radialColorDelta) --
1732 // this uses bisection (between the current value, t, and t1), 1732 // this uses bisection (between the current value, t, and t1),
1733 // limited to radialMaxSplits points along the t axis 1733 // limited to radialMaxSplits points along the t axis
1734 ib = radialMaxSplits; 1734 ib = radialMaxSplits;
1735 sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin); 1735 sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin);
1736 tb = t0 + sb * (t1 - t0); 1736 tb = t0 + sb * (t1 - t0);
1737 if (tb < t0) { 1737 if (tb < t0) {
1738 shading->getColor(t0, &colorB); 1738 shading->getColor(t0, &colorB);
1739 } else if (tb > t1) { 1739 } else if (tb > t1) {
1740 shading->getColor(t1, &colorB); 1740 shading->getColor(t1, &colorB);
1741 } else { 1741 } else {
1742 shading->getColor(tb, &colorB); 1742 shading->getColor(tb, &colorB);
1743 } 1743 }
1744 while (ib - ia > 1) { 1744 while (ib - ia > 1) {
1745 for (k = 0; k < nComps; ++k) { 1745 for (k = 0; k < nComps; ++k) {
1746 if (fabs(colorB.c[k] - colorA.c[k]) > radialColorDelta) { 1746 if (fabs(colorB.c[k] - colorA.c[k]) > radialColorDelta) {
1747 break; 1747 break;
1748 } 1748 }
1749 } 1749 }
1750 if (k == nComps) { 1750 if (k == nComps) {
1751 break; 1751 break;
1752 } 1752 }
1753 ib = (ia + ib) / 2; 1753 ib = (ia + ib) / 2;
1754 sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin); 1754 sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin);
1755 tb = t0 + sb * (t1 - t0); 1755 tb = t0 + sb * (t1 - t0);
1756 if (tb < t0) { 1756 if (tb < t0) {
1757 shading->getColor(t0, &colorB); 1757 shading->getColor(t0, &colorB);
1758 } else if (tb > t1) { 1758 } else if (tb > t1) {
1759 shading->getColor(t1, &colorB); 1759 shading->getColor(t1, &colorB);
1760 } else { 1760 } else {
1761 shading->getColor(tb, &colorB); 1761 shading->getColor(tb, &colorB);
1762 } 1762 }
1763 } 1763 }
1764 1764
1765 // compute center and radius of the circle 1765 // compute center and radius of the circle
1766 xb = x0 + sb * (x1 - x0); 1766 xb = x0 + sb * (x1 - x0);
1767 yb = y0 + sb * (y1 - y0); 1767 yb = y0 + sb * (y1 - y0);
1768 rb = r0 + sb * (r1 - r0); 1768 rb = r0 + sb * (r1 - r0);
1769 1769
1770 // use the average of the colors at the two circles 1770 // use the average of the colors at the two circles
1771 for (k = 0; k < nComps; ++k) { 1771 for (k = 0; k < nComps; ++k) {
1772 colorA.c[k] = 0.5 * (colorA.c[k] + colorB.c[k]); 1772 colorA.c[k] = 0.5 * (colorA.c[k] + colorB.c[k]);
1773 } 1773 }
1774 state->setFillColor(&colorA); 1774 state->setFillColor(&colorA);
1775 out->updateFillColor(state); 1775 out->updateFillColor(state);
1776 1776
1777 // construct path for first circle 1777 // construct path for first circle
1778 state->moveTo(xa + ra, ya); 1778 state->moveTo(xa + ra, ya);
1779 for (k = 1; k < n; ++k) { 1779 for (k = 1; k < n; ++k) {
1780 angle = ((fouble)k / (fouble)n) * 2 * M_PI; 1780 angle = ((fouble)k / (fouble)n) * 2 * M_PI;
1781 state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); 1781 state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
1782 } 1782 }
1783 state->closePath(); 1783 state->closePath();
1784 1784
1785 // construct and append path for second circle 1785 // construct and append path for second circle
1786 state->moveTo(xb + rb, yb); 1786 state->moveTo(xb + rb, yb);
1787 for (k = 1; k < n; ++k) { 1787 for (k = 1; k < n; ++k) {
1788 angle = ((fouble)k / (fouble)n) * 2 * M_PI; 1788 angle = ((fouble)k / (fouble)n) * 2 * M_PI;
1789 state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); 1789 state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
1790 } 1790 }
1791 state->closePath(); 1791 state->closePath();
1792 1792
1793 // fill the ring 1793 // fill the ring
1794 out->eoFill(state); 1794 out->eoFill(state);
1795 state->clearPath(); 1795 state->clearPath();
1796 1796
1797 // step to the next value of t 1797 // step to the next value of t
1798 ia = ib; 1798 ia = ib;
1799 sa = sb; 1799 sa = sb;
1800 ta = tb; 1800 ta = tb;
1801 xa = xb; 1801 xa = xb;
1802 ya = yb; 1802 ya = yb;
1803 ra = rb; 1803 ra = rb;
1804 colorA = colorB; 1804 colorA = colorB;
1805 } 1805 }
1806} 1806}
1807 1807
1808void Gfx::doEndPath() { 1808void Gfx::doEndPath() {
1809 if (state->isPath() && clip != clipNone) { 1809 if (state->isPath() && clip != clipNone) {
1810 state->clip(); 1810 state->clip();
1811 if (clip == clipNormal) { 1811 if (clip == clipNormal) {
1812 out->clip(state); 1812 out->clip(state);
1813 } else { 1813 } else {
1814 out->eoClip(state); 1814 out->eoClip(state);
1815 } 1815 }
1816 } 1816 }
1817 clip = clipNone; 1817 clip = clipNone;
1818 state->clearPath(); 1818 state->clearPath();
1819} 1819}
1820 1820
1821//------------------------------------------------------------------------ 1821//------------------------------------------------------------------------
1822// path clipping operators 1822// path clipping operators
1823//------------------------------------------------------------------------ 1823//------------------------------------------------------------------------
1824 1824
1825void Gfx::opClip(Object args[], int numArgs) { 1825void Gfx::opClip(Object args[], int numArgs) {
1826 clip = clipNormal; 1826 clip = clipNormal;
1827} 1827}
1828 1828
1829void Gfx::opEOClip(Object args[], int numArgs) { 1829void Gfx::opEOClip(Object args[], int numArgs) {
1830 clip = clipEO; 1830 clip = clipEO;
1831} 1831}
1832 1832
1833//------------------------------------------------------------------------ 1833//------------------------------------------------------------------------
1834// text object operators 1834// text object operators
1835//------------------------------------------------------------------------ 1835//------------------------------------------------------------------------
1836 1836
1837void Gfx::opBeginText(Object args[], int numArgs) { 1837void Gfx::opBeginText(Object args[], int numArgs) {
1838 state->setTextMat(1, 0, 0, 1, 0, 0); 1838 state->setTextMat(1, 0, 0, 1, 0, 0);
1839 state->textMoveTo(0, 0); 1839 state->textMoveTo(0, 0);
1840 out->updateTextMat(state); 1840 out->updateTextMat(state);
1841 out->updateTextPos(state); 1841 out->updateTextPos(state);
1842 fontChanged = gTrue; 1842 fontChanged = gTrue;
1843} 1843}
1844 1844
1845void Gfx::opEndText(Object args[], int numArgs) { 1845void Gfx::opEndText(Object args[], int numArgs) {
1846} 1846}
1847 1847
1848//------------------------------------------------------------------------ 1848//------------------------------------------------------------------------
1849// text state operators 1849// text state operators
1850//------------------------------------------------------------------------ 1850//------------------------------------------------------------------------
1851 1851
1852void Gfx::opSetCharSpacing(Object args[], int numArgs) { 1852void Gfx::opSetCharSpacing(Object args[], int numArgs) {
1853 state->setCharSpace(args[0].getNum()); 1853 state->setCharSpace(args[0].getNum());
1854 out->updateCharSpace(state); 1854 out->updateCharSpace(state);
1855} 1855}
1856 1856
1857void Gfx::opSetFont(Object args[], int numArgs) { 1857void Gfx::opSetFont(Object args[], int numArgs) {
1858 GfxFont *font; 1858 GfxFont *font;
1859 1859
1860 if (!(font = res->lookupFont(args[0].getName()))) { 1860 if (!(font = res->lookupFont(args[0].getName()))) {
1861 return; 1861 return;
1862 } 1862 }
1863 if (printCommands) { 1863 if (printCommands) {
1864 printf(" font: tag=%s name='%s' %g\n", 1864 printf(" font: tag=%s name='%s' %g\n",
1865 font->getTag()->getCString(), 1865 font->getTag()->getCString(),
1866 font->getName() ? font->getName()->getCString() : "???", 1866 font->getName() ? font->getName()->getCString() : "???",
1867 args[1].getNum()); 1867 static_cast<double>(args[1].getNum()));
1868 fflush(stdout); 1868 fflush(stdout);
1869 } 1869 }
1870 state->setFont(font, args[1].getNum()); 1870 state->setFont(font, args[1].getNum());
1871 fontChanged = gTrue; 1871 fontChanged = gTrue;
1872} 1872}
1873 1873
1874void Gfx::opSetTextLeading(Object args[], int numArgs) { 1874void Gfx::opSetTextLeading(Object args[], int numArgs) {
1875 state->setLeading(args[0].getNum()); 1875 state->setLeading(args[0].getNum());
1876} 1876}
1877 1877
1878void Gfx::opSetTextRender(Object args[], int numArgs) { 1878void Gfx::opSetTextRender(Object args[], int numArgs) {
1879 state->setRender(args[0].getInt()); 1879 state->setRender(args[0].getInt());
1880 out->updateRender(state); 1880 out->updateRender(state);
1881} 1881}
1882 1882
1883void Gfx::opSetTextRise(Object args[], int numArgs) { 1883void Gfx::opSetTextRise(Object args[], int numArgs) {
1884 state->setRise(args[0].getNum()); 1884 state->setRise(args[0].getNum());
1885 out->updateRise(state); 1885 out->updateRise(state);
1886} 1886}
1887 1887
1888void Gfx::opSetWordSpacing(Object args[], int numArgs) { 1888void Gfx::opSetWordSpacing(Object args[], int numArgs) {
1889 state->setWordSpace(args[0].getNum()); 1889 state->setWordSpace(args[0].getNum());
1890 out->updateWordSpace(state); 1890 out->updateWordSpace(state);
1891} 1891}
1892 1892
1893void Gfx::opSetHorizScaling(Object args[], int numArgs) { 1893void Gfx::opSetHorizScaling(Object args[], int numArgs) {
1894 state->setHorizScaling(args[0].getNum()); 1894 state->setHorizScaling(args[0].getNum());
1895 out->updateHorizScaling(state); 1895 out->updateHorizScaling(state);
1896 fontChanged = gTrue; 1896 fontChanged = gTrue;
1897} 1897}
1898 1898
1899//------------------------------------------------------------------------ 1899//------------------------------------------------------------------------
1900// text positioning operators 1900// text positioning operators
1901//------------------------------------------------------------------------ 1901//------------------------------------------------------------------------
1902 1902
1903void Gfx::opTextMove(Object args[], int numArgs) { 1903void Gfx::opTextMove(Object args[], int numArgs) {
1904 fouble tx, ty; 1904 fouble tx, ty;
1905 1905
1906 tx = state->getLineX() + args[0].getNum(); 1906 tx = state->getLineX() + args[0].getNum();
1907 ty = state->getLineY() + args[1].getNum(); 1907 ty = state->getLineY() + args[1].getNum();
1908 state->textMoveTo(tx, ty); 1908 state->textMoveTo(tx, ty);
1909 out->updateTextPos(state); 1909 out->updateTextPos(state);
1910} 1910}
1911 1911
1912void Gfx::opTextMoveSet(Object args[], int numArgs) { 1912void Gfx::opTextMoveSet(Object args[], int numArgs) {
1913 fouble tx, ty; 1913 fouble tx, ty;
1914 1914
1915 tx = state->getLineX() + args[0].getNum(); 1915 tx = state->getLineX() + args[0].getNum();
1916 ty = args[1].getNum(); 1916 ty = args[1].getNum();
1917 state->setLeading(-ty); 1917 state->setLeading(-ty);
1918 ty += state->getLineY(); 1918 ty += state->getLineY();
1919 state->textMoveTo(tx, ty); 1919 state->textMoveTo(tx, ty);
1920 out->updateTextPos(state); 1920 out->updateTextPos(state);
1921} 1921}
1922 1922
1923void Gfx::opSetTextMatrix(Object args[], int numArgs) { 1923void Gfx::opSetTextMatrix(Object args[], int numArgs) {
1924 state->setTextMat(args[0].getNum(), args[1].getNum(), 1924 state->setTextMat(args[0].getNum(), args[1].getNum(),
1925 args[2].getNum(), args[3].getNum(), 1925 args[2].getNum(), args[3].getNum(),
1926 args[4].getNum(), args[5].getNum()); 1926 args[4].getNum(), args[5].getNum());
1927 state->textMoveTo(0, 0); 1927 state->textMoveTo(0, 0);
1928 out->updateTextMat(state); 1928 out->updateTextMat(state);
1929 out->updateTextPos(state); 1929 out->updateTextPos(state);
1930 fontChanged = gTrue; 1930 fontChanged = gTrue;
1931} 1931}
1932 1932
1933void Gfx::opTextNextLine(Object args[], int numArgs) { 1933void Gfx::opTextNextLine(Object args[], int numArgs) {
1934 fouble tx, ty; 1934 fouble tx, ty;
1935 1935
1936 tx = state->getLineX(); 1936 tx = state->getLineX();
1937 ty = state->getLineY() - state->getLeading(); 1937 ty = state->getLineY() - state->getLeading();
1938 state->textMoveTo(tx, ty); 1938 state->textMoveTo(tx, ty);
1939 out->updateTextPos(state); 1939 out->updateTextPos(state);
1940} 1940}
1941 1941
1942//------------------------------------------------------------------------ 1942//------------------------------------------------------------------------
1943// text string operators 1943// text string operators
1944//------------------------------------------------------------------------ 1944//------------------------------------------------------------------------
1945 1945
1946void Gfx::opShowText(Object args[], int numArgs) { 1946void Gfx::opShowText(Object args[], int numArgs) {
1947 if (!state->getFont()) { 1947 if (!state->getFont()) {
1948 error(getPos(), "No font in show"); 1948 error(getPos(), "No font in show");
1949 return; 1949 return;
1950 } 1950 }
1951 doShowText(args[0].getString()); 1951 doShowText(args[0].getString());
1952} 1952}
1953 1953
1954void Gfx::opMoveShowText(Object args[], int numArgs) { 1954void Gfx::opMoveShowText(Object args[], int numArgs) {
1955 fouble tx, ty; 1955 fouble tx, ty;
1956 1956
1957 if (!state->getFont()) { 1957 if (!state->getFont()) {
1958 error(getPos(), "No font in move/show"); 1958 error(getPos(), "No font in move/show");
1959 return; 1959 return;
1960 } 1960 }
1961 tx = state->getLineX(); 1961 tx = state->getLineX();
1962 ty = state->getLineY() - state->getLeading(); 1962 ty = state->getLineY() - state->getLeading();
1963 state->textMoveTo(tx, ty); 1963 state->textMoveTo(tx, ty);
1964 out->updateTextPos(state); 1964 out->updateTextPos(state);
1965 doShowText(args[0].getString()); 1965 doShowText(args[0].getString());
1966} 1966}
1967 1967
1968void Gfx::opMoveSetShowText(Object args[], int numArgs) { 1968void Gfx::opMoveSetShowText(Object args[], int numArgs) {
1969 fouble tx, ty; 1969 fouble tx, ty;
1970 1970
1971 if (!state->getFont()) { 1971 if (!state->getFont()) {
1972 error(getPos(), "No font in move/set/show"); 1972 error(getPos(), "No font in move/set/show");
1973 return; 1973 return;
1974 } 1974 }
1975 state->setWordSpace(args[0].getNum()); 1975 state->setWordSpace(args[0].getNum());
1976 state->setCharSpace(args[1].getNum()); 1976 state->setCharSpace(args[1].getNum());
1977 tx = state->getLineX(); 1977 tx = state->getLineX();
1978 ty = state->getLineY() - state->getLeading(); 1978 ty = state->getLineY() - state->getLeading();
1979 state->textMoveTo(tx, ty); 1979 state->textMoveTo(tx, ty);
1980 out->updateWordSpace(state); 1980 out->updateWordSpace(state);
1981 out->updateCharSpace(state); 1981 out->updateCharSpace(state);
1982 out->updateTextPos(state); 1982 out->updateTextPos(state);
1983 doShowText(args[2].getString()); 1983 doShowText(args[2].getString());
1984} 1984}
1985 1985
1986void Gfx::opShowSpaceText(Object args[], int numArgs) { 1986void Gfx::opShowSpaceText(Object args[], int numArgs) {
1987 Array *a; 1987 Array *a;
1988 Object obj; 1988 Object obj;
1989 int wMode; 1989 int wMode;
1990 int i; 1990 int i;
1991 1991
1992 if (!state->getFont()) { 1992 if (!state->getFont()) {
1993 error(getPos(), "No font in show/space"); 1993 error(getPos(), "No font in show/space");
1994 return; 1994 return;
1995 } 1995 }
1996 wMode = state->getFont()->getWMode(); 1996 wMode = state->getFont()->getWMode();
1997 a = args[0].getArray(); 1997 a = args[0].getArray();
1998 for (i = 0; i < a->getLength(); ++i) { 1998 for (i = 0; i < a->getLength(); ++i) {
1999 a->get(i, &obj); 1999 a->get(i, &obj);
2000 if (obj.isNum()) { 2000 if (obj.isNum()) {
2001 if (wMode) { 2001 if (wMode) {
2002 state->textShift(0, -obj.getNum() * 0.001 * state->getFontSize()); 2002 state->textShift(0, -obj.getNum() * 0.001 * state->getFontSize());
2003 } else { 2003 } else {
2004 state->textShift(-obj.getNum() * 0.001 * state->getFontSize(), 0); 2004 state->textShift(-obj.getNum() * 0.001 * state->getFontSize(), 0);
2005 } 2005 }
2006 out->updateTextShift(state, obj.getNum()); 2006 out->updateTextShift(state, obj.getNum());
2007 } else if (obj.isString()) { 2007 } else if (obj.isString()) {
2008 doShowText(obj.getString()); 2008 doShowText(obj.getString());
2009 } else { 2009 } else {
2010 error(getPos(), "Element of show/space array must be number or string"); 2010 error(getPos(), "Element of show/space array must be number or string");
2011 } 2011 }
2012 obj.free(); 2012 obj.free();
2013 } 2013 }
2014} 2014}
2015 2015
2016void Gfx::doShowText(GString *s) { 2016void Gfx::doShowText(GString *s) {
2017 GfxFont *font; 2017 GfxFont *font;
2018 int wMode; 2018 int wMode;
2019 fouble riseX, riseY; 2019 fouble riseX, riseY;
2020 CharCode code; 2020 CharCode code;
2021 Unicode u[8]; 2021 Unicode u[8];
2022 fouble x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy; 2022 fouble x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy;
2023 fouble originX, originY, tOriginX, tOriginY; 2023 fouble originX, originY, tOriginX, tOriginY;
2024 fouble oldCTM[6], newCTM[6]; 2024 fouble oldCTM[6], newCTM[6];
2025 fouble *mat; 2025 fouble *mat;
2026 Object charProc; 2026 Object charProc;
2027 Dict *resDict; 2027 Dict *resDict;
2028 Parser *oldParser; 2028 Parser *oldParser;
2029 char *p; 2029 char *p;
2030 int len, n, uLen, nChars, nSpaces, i; 2030 int len, n, uLen, nChars, nSpaces, i;
2031 2031
2032 if (fontChanged) { 2032 if (fontChanged) {
2033 out->updateFont(state); 2033 out->updateFont(state);
2034 fontChanged = gFalse; 2034 fontChanged = gFalse;
2035 } 2035 }
2036 font = state->getFont(); 2036 font = state->getFont();
2037 wMode = font->getWMode(); 2037 wMode = font->getWMode();
2038 2038
2039 if (out->useDrawChar()) { 2039 if (out->useDrawChar()) {
2040 out->beginString(state, s); 2040 out->beginString(state, s);
2041 } 2041 }
2042 2042
2043 // handle a Type 3 char 2043 // handle a Type 3 char
2044 if (font->getType() == fontType3 && out->interpretType3Chars()) { 2044 if (font->getType() == fontType3 && out->interpretType3Chars()) {
2045 mat = state->getCTM(); 2045 mat = state->getCTM();
2046 for (i = 0; i < 6; ++i) { 2046 for (i = 0; i < 6; ++i) {
2047 oldCTM[i] = mat[i]; 2047 oldCTM[i] = mat[i];
2048 } 2048 }
2049 mat = state->getTextMat(); 2049 mat = state->getTextMat();
2050 newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; 2050 newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2];
2051 newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; 2051 newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3];
2052 newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; 2052 newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2];
2053 newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3]; 2053 newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
2054 mat = font->getFontMatrix(); 2054 mat = font->getFontMatrix();
2055 newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; 2055 newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2];
2056 newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; 2056 newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3];
2057 newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; 2057 newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
2058 newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; 2058 newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
2059 newCTM[0] *= state->getFontSize(); 2059 newCTM[0] *= state->getFontSize();
2060 newCTM[3] *= state->getFontSize(); 2060 newCTM[3] *= state->getFontSize();
2061 newCTM[0] *= state->getHorizScaling(); 2061 newCTM[0] *= state->getHorizScaling();
2062 newCTM[2] *= state->getHorizScaling(); 2062 newCTM[2] *= state->getHorizScaling();
2063 state->textTransformDelta(0, state->getRise(), &riseX, &riseY); 2063 state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
2064 curX = state->getCurX(); 2064 curX = state->getCurX();
2065 curY = state->getCurY(); 2065 curY = state->getCurY();
2066 oldParser = parser; 2066 oldParser = parser;
2067 p = s->getCString(); 2067 p = s->getCString();
2068 len = s->getLength(); 2068 len = s->getLength();
2069 while (len > 0) { 2069 while (len > 0) {
2070 n = font->getNextChar(p, len, &code, 2070 n = font->getNextChar(p, len, &code,
2071 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, 2071 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
2072 &dx, &dy, &originX, &originY); 2072 &dx, &dy, &originX, &originY);
2073 dx = dx * state->getFontSize() + state->getCharSpace(); 2073 dx = dx * state->getFontSize() + state->getCharSpace();
2074 if (n == 1 && *p == ' ') { 2074 if (n == 1 && *p == ' ') {
2075 dx += state->getWordSpace(); 2075 dx += state->getWordSpace();
2076 } 2076 }
2077 dx *= state->getHorizScaling(); 2077 dx *= state->getHorizScaling();
2078 dy *= state->getFontSize(); 2078 dy *= state->getFontSize();
2079 state->textTransformDelta(dx, dy, &tdx, &tdy); 2079 state->textTransformDelta(dx, dy, &tdx, &tdy);
2080 state->transform(curX + riseX, curY + riseY, &x, &y); 2080 state->transform(curX + riseX, curY + riseY, &x, &y);
2081 out->saveState(state); 2081 out->saveState(state);
2082 state = state->save(); 2082 state = state->save();
2083 state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); 2083 state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
2084 //~ out->updateCTM(???) 2084 //~ out->updateCTM(???)
2085 if (!out->beginType3Char(state, code, u, uLen)) { 2085 if (!out->beginType3Char(state, code, u, uLen)) {
2086 ((Gfx8BitFont *)font)->getCharProc(code, &charProc); 2086 ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
2087 if ((resDict = ((Gfx8BitFont *)font)->getResources())) { 2087 if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
2088 pushResources(resDict); 2088 pushResources(resDict);
2089 } 2089 }
2090 if (charProc.isStream()) { 2090 if (charProc.isStream()) {
2091 display(&charProc, gFalse); 2091 display(&charProc, gFalse);
2092 } else { 2092 } else {
2093 error(getPos(), "Missing or bad Type3 CharProc entry"); 2093 error(getPos(), "Missing or bad Type3 CharProc entry");
2094 } 2094 }
2095 out->endType3Char(state); 2095 out->endType3Char(state);
2096 if (resDict) { 2096 if (resDict) {
2097 popResources(); 2097 popResources();
2098 } 2098 }
2099 charProc.free(); 2099 charProc.free();
2100 } 2100 }
2101 state = state->restore(); 2101 state = state->restore();
2102 out->restoreState(state); 2102 out->restoreState(state);
2103 // GfxState::restore() does *not* restore the current position, 2103 // GfxState::restore() does *not* restore the current position,
2104 // so we track it here with (curX, curY) 2104 // so we track it here with (curX, curY)
2105 curX += tdx; 2105 curX += tdx;
2106 curY += tdy; 2106 curY += tdy;
2107 state->moveTo(curX, curY); 2107 state->moveTo(curX, curY);
2108 p += n; 2108 p += n;
2109 len -= n; 2109 len -= n;
2110 } 2110 }
2111 parser = oldParser; 2111 parser = oldParser;
2112 2112
2113 } else if (out->useDrawChar()) { 2113 } else if (out->useDrawChar()) {
2114 state->textTransformDelta(0, state->getRise(), &riseX, &riseY); 2114 state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
2115 p = s->getCString(); 2115 p = s->getCString();
2116 len = s->getLength(); 2116 len = s->getLength();
2117 while (len > 0) { 2117 while (len > 0) {
2118 n = font->getNextChar(p, len, &code, 2118 n = font->getNextChar(p, len, &code,
2119 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, 2119 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
2120 &dx, &dy, &originX, &originY); 2120 &dx, &dy, &originX, &originY);
2121 if (wMode) { 2121 if (wMode) {
2122 dx *= state->getFontSize(); 2122 dx *= state->getFontSize();
2123 dy = dy * state->getFontSize() + state->getCharSpace(); 2123 dy = dy * state->getFontSize() + state->getCharSpace();
2124 if (n == 1 && *p == ' ') { 2124 if (n == 1 && *p == ' ') {
2125 dy += state->getWordSpace(); 2125 dy += state->getWordSpace();
2126 } 2126 }
2127 } else { 2127 } else {
2128 dx = dx * state->getFontSize() + state->getCharSpace(); 2128 dx = dx * state->getFontSize() + state->getCharSpace();
2129 if (n == 1 && *p == ' ') { 2129 if (n == 1 && *p == ' ') {
2130 dx += state->getWordSpace(); 2130 dx += state->getWordSpace();
2131 } 2131 }
2132 dx *= state->getHorizScaling(); 2132 dx *= state->getHorizScaling();
2133 dy *= state->getFontSize(); 2133 dy *= state->getFontSize();
2134 } 2134 }
2135 state->textTransformDelta(dx, dy, &tdx, &tdy); 2135 state->textTransformDelta(dx, dy, &tdx, &tdy);
2136 originX *= state->getFontSize(); 2136 originX *= state->getFontSize();
2137 originY *= state->getFontSize(); 2137 originY *= state->getFontSize();
2138 state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); 2138 state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
2139 out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, 2139 out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
2140 tdx, tdy, tOriginX, tOriginY, code, u, uLen); 2140 tdx, tdy, tOriginX, tOriginY, code, u, uLen);
2141 state->shift(tdx, tdy); 2141 state->shift(tdx, tdy);
2142 p += n; 2142 p += n;
2143 len -= n; 2143 len -= n;
2144 } 2144 }
2145 2145
2146 } else { 2146 } else {
2147 dx = dy = 0; 2147 dx = dy = 0;
2148 p = s->getCString(); 2148 p = s->getCString();
2149 len = s->getLength(); 2149 len = s->getLength();
2150 nChars = nSpaces = 0; 2150 nChars = nSpaces = 0;
2151 while (len > 0) { 2151 while (len > 0) {
2152 n = font->getNextChar(p, len, &code, 2152 n = font->getNextChar(p, len, &code,
2153 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, 2153 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
2154 &dx2, &dy2, &originX, &originY); 2154 &dx2, &dy2, &originX, &originY);
2155 dx += dx2; 2155 dx += dx2;
2156 dy += dy2; 2156 dy += dy2;
2157 if (n == 1 && *p == ' ') { 2157 if (n == 1 && *p == ' ') {
2158 ++nSpaces; 2158 ++nSpaces;
2159 } 2159 }
2160 ++nChars; 2160 ++nChars;
2161 p += n; 2161 p += n;
2162 len -= n; 2162 len -= n;
2163 } 2163 }
2164 if (wMode) { 2164 if (wMode) {
2165 dx *= state->getFontSize(); 2165 dx *= state->getFontSize();
2166 dy = dy * state->getFontSize() 2166 dy = dy * state->getFontSize()
2167 + nChars * state->getCharSpace() 2167 + nChars * state->getCharSpace()
2168 + nSpaces * state->getWordSpace(); 2168 + nSpaces * state->getWordSpace();
2169 } else { 2169 } else {
2170 dx = dx * state->getFontSize() 2170 dx = dx * state->getFontSize()
2171 + nChars * state->getCharSpace() 2171 + nChars * state->getCharSpace()
2172 + nSpaces * state->getWordSpace(); 2172 + nSpaces * state->getWordSpace();
2173 dx *= state->getHorizScaling(); 2173 dx *= state->getHorizScaling();
2174 dy *= state->getFontSize(); 2174 dy *= state->getFontSize();
2175 } 2175 }
2176 state->textTransformDelta(dx, dy, &tdx, &tdy); 2176 state->textTransformDelta(dx, dy, &tdx, &tdy);
2177 out->drawString(state, s); 2177 out->drawString(state, s);
2178 state->shift(tdx, tdy); 2178 state->shift(tdx, tdy);
2179 } 2179 }
2180 2180
2181 if (out->useDrawChar()) { 2181 if (out->useDrawChar()) {
2182 out->endString(state); 2182 out->endString(state);
2183 } 2183 }
2184 2184
2185 updateLevel += 10 * s->getLength(); 2185 updateLevel += 10 * s->getLength();
2186} 2186}
2187 2187
2188//------------------------------------------------------------------------ 2188//------------------------------------------------------------------------
2189// XObject operators 2189// XObject operators
2190//------------------------------------------------------------------------ 2190//------------------------------------------------------------------------
2191 2191
2192void Gfx::opXObject(Object args[], int numArgs) { 2192void Gfx::opXObject(Object args[], int numArgs) {
2193 Object obj1, obj2, obj3, refObj; 2193 Object obj1, obj2, obj3, refObj;
2194#if OPI_SUPPORT 2194#if OPI_SUPPORT
2195 Object opiDict; 2195 Object opiDict;
2196#endif 2196#endif
2197 2197
2198 if (!res->lookupXObject(args[0].getName(), &obj1)) { 2198 if (!res->lookupXObject(args[0].getName(), &obj1)) {
2199 return; 2199 return;
2200 } 2200 }
2201 if (!obj1.isStream()) { 2201 if (!obj1.isStream()) {
2202 error(getPos(), "XObject '%s' is wrong type", args[0].getName()); 2202 error(getPos(), "XObject '%s' is wrong type", args[0].getName());
2203 obj1.free(); 2203 obj1.free();
2204 return; 2204 return;
2205 } 2205 }
2206#if OPI_SUPPORT 2206#if OPI_SUPPORT
2207 obj1.streamGetDict()->lookup("OPI", &opiDict); 2207 obj1.streamGetDict()->lookup("OPI", &opiDict);
2208 if (opiDict.isDict()) { 2208 if (opiDict.isDict()) {
2209 out->opiBegin(state, opiDict.getDict()); 2209 out->opiBegin(state, opiDict.getDict());
2210 } 2210 }
2211#endif 2211#endif
2212 obj1.streamGetDict()->lookup("Subtype", &obj2); 2212 obj1.streamGetDict()->lookup("Subtype", &obj2);
2213 if (obj2.isName("Image")) { 2213 if (obj2.isName("Image")) {
2214 res->lookupXObjectNF(args[0].getName(), &refObj); 2214 res->lookupXObjectNF(args[0].getName(), &refObj);
2215 doImage(&refObj, obj1.getStream(), gFalse); 2215 doImage(&refObj, obj1.getStream(), gFalse);
2216 refObj.free(); 2216 refObj.free();
2217 } else if (obj2.isName("Form")) { 2217 } else if (obj2.isName("Form")) {
2218 doForm(&obj1); 2218 doForm(&obj1);
2219 } else if (obj2.isName("PS")) { 2219 } else if (obj2.isName("PS")) {
2220 obj1.streamGetDict()->lookup("Level1", &obj3); 2220 obj1.streamGetDict()->lookup("Level1", &obj3);
2221 out->psXObject(obj1.getStream(), 2221 out->psXObject(obj1.getStream(),
2222 obj3.isStream() ? obj3.getStream() : (Stream *)NULL); 2222 obj3.isStream() ? obj3.getStream() : (Stream *)NULL);
2223 } else if (obj2.isName()) { 2223 } else if (obj2.isName()) {
2224 error(getPos(), "Unknown XObject subtype '%s'", obj2.getName()); 2224 error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
2225 } else { 2225 } else {
2226 error(getPos(), "XObject subtype is missing or wrong type"); 2226 error(getPos(), "XObject subtype is missing or wrong type");
2227 } 2227 }
2228 obj2.free(); 2228 obj2.free();
2229#if OPI_SUPPORT 2229#if OPI_SUPPORT
2230 if (opiDict.isDict()) { 2230 if (opiDict.isDict()) {
2231 out->opiEnd(state, opiDict.getDict()); 2231 out->opiEnd(state, opiDict.getDict());
2232 } 2232 }
2233 opiDict.free(); 2233 opiDict.free();
2234#endif 2234#endif
2235 obj1.free(); 2235 obj1.free();
2236} 2236}
2237 2237
2238void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { 2238void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
2239 Dict *dict; 2239 Dict *dict;
2240 int width, height; 2240 int width, height;
2241 int bits; 2241 int bits;
2242 GBool mask; 2242 GBool mask;
2243 GBool invert; 2243 GBool invert;
2244 GfxColorSpace *colorSpace; 2244 GfxColorSpace *colorSpace;
2245 GfxImageColorMap *colorMap; 2245 GfxImageColorMap *colorMap;
2246 Object maskObj; 2246 Object maskObj;
2247 GBool haveMask; 2247 GBool haveMask;
2248 int maskColors[2*gfxColorMaxComps]; 2248 int maskColors[2*gfxColorMaxComps];
2249 Object obj1, obj2; 2249 Object obj1, obj2;
2250 int i; 2250 int i;
2251 2251
2252 // get stream dict 2252 // get stream dict
2253 dict = str->getDict(); 2253 dict = str->getDict();
2254 2254
2255 // get size 2255 // get size
2256 dict->lookup("Width", &obj1); 2256 dict->lookup("Width", &obj1);
2257 if (obj1.isNull()) { 2257 if (obj1.isNull()) {
2258 obj1.free(); 2258 obj1.free();
2259 dict->lookup("W", &obj1); 2259 dict->lookup("W", &obj1);
2260 } 2260 }
2261 if (!obj1.isInt()) 2261 if (!obj1.isInt())
2262 goto err2; 2262 goto err2;
2263 width = obj1.getInt(); 2263 width = obj1.getInt();
2264 obj1.free(); 2264 obj1.free();
2265 dict->lookup("Height", &obj1); 2265 dict->lookup("Height", &obj1);
2266 if (obj1.isNull()) { 2266 if (obj1.isNull()) {
2267 obj1.free(); 2267 obj1.free();
2268 dict->lookup("H", &obj1); 2268 dict->lookup("H", &obj1);
2269 } 2269 }
2270 if (!obj1.isInt()) 2270 if (!obj1.isInt())
2271 goto err2; 2271 goto err2;
2272 height = obj1.getInt(); 2272 height = obj1.getInt();
2273 obj1.free(); 2273 obj1.free();
2274 2274
2275 // image or mask? 2275 // image or mask?
2276 dict->lookup("ImageMask", &obj1); 2276 dict->lookup("ImageMask", &obj1);
2277 if (obj1.isNull()) { 2277 if (obj1.isNull()) {
2278 obj1.free(); 2278 obj1.free();
2279 dict->lookup("IM", &obj1); 2279 dict->lookup("IM", &obj1);
2280 } 2280 }
2281 mask = gFalse; 2281 mask = gFalse;
2282 if (obj1.isBool()) 2282 if (obj1.isBool())
2283 mask = obj1.getBool(); 2283 mask = obj1.getBool();
2284 else if (!obj1.isNull()) 2284 else if (!obj1.isNull())
2285 goto err2; 2285 goto err2;
2286 obj1.free(); 2286 obj1.free();
2287 2287
2288 // bit depth 2288 // bit depth
2289 dict->lookup("BitsPerComponent", &obj1); 2289 dict->lookup("BitsPerComponent", &obj1);
2290 if (obj1.isNull()) { 2290 if (obj1.isNull()) {
2291 obj1.free(); 2291 obj1.free();
2292 dict->lookup("BPC", &obj1); 2292 dict->lookup("BPC", &obj1);
2293 } 2293 }
2294 if (!obj1.isInt()) 2294 if (!obj1.isInt())
2295 goto err2; 2295 goto err2;
2296 bits = obj1.getInt(); 2296 bits = obj1.getInt();
2297 obj1.free(); 2297 obj1.free();
2298 2298
2299 // display a mask 2299 // display a mask
2300 if (mask) { 2300 if (mask) {
2301 2301
2302 // check for inverted mask 2302 // check for inverted mask
2303 if (bits != 1) 2303 if (bits != 1)
2304 goto err1; 2304 goto err1;
2305 invert = gFalse; 2305 invert = gFalse;
2306 dict->lookup("Decode", &obj1); 2306 dict->lookup("Decode", &obj1);
2307 if (obj1.isNull()) { 2307 if (obj1.isNull()) {
2308 obj1.free(); 2308 obj1.free();
2309 dict->lookup("D", &obj1); 2309 dict->lookup("D", &obj1);
2310 } 2310 }
2311 if (obj1.isArray()) { 2311 if (obj1.isArray()) {
2312 obj1.arrayGet(0, &obj2); 2312 obj1.arrayGet(0, &obj2);
2313 if (obj2.isInt() && obj2.getInt() == 1) 2313 if (obj2.isInt() && obj2.getInt() == 1)
2314 invert = gTrue; 2314 invert = gTrue;
2315 obj2.free(); 2315 obj2.free();
2316 } else if (!obj1.isNull()) { 2316 } else if (!obj1.isNull()) {
2317 goto err2; 2317 goto err2;
2318 } 2318 }
2319 obj1.free(); 2319 obj1.free();
2320 2320
2321 // draw it 2321 // draw it
2322 out->drawImageMask(state, ref, str, width, height, invert, inlineImg); 2322 out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
2323 2323
2324 } else { 2324 } else {
2325 2325
2326 // get color space and color map 2326 // get color space and color map
2327 dict->lookup("ColorSpace", &obj1); 2327 dict->lookup("ColorSpace", &obj1);
2328 if (obj1.isNull()) { 2328 if (obj1.isNull()) {
2329 obj1.free(); 2329 obj1.free();
2330 dict->lookup("CS", &obj1); 2330 dict->lookup("CS", &obj1);
2331 } 2331 }
2332 if (obj1.isName()) { 2332 if (obj1.isName()) {
2333 res->lookupColorSpace(obj1.getName(), &obj2); 2333 res->lookupColorSpace(obj1.getName(), &obj2);
2334 if (!obj2.isNull()) { 2334 if (!obj2.isNull()) {
2335 obj1.free(); 2335 obj1.free();
2336 obj1 = obj2; 2336 obj1 = obj2;
2337 } else { 2337 } else {
2338 obj2.free(); 2338 obj2.free();
2339 } 2339 }
2340 } 2340 }
2341 colorSpace = GfxColorSpace::parse(&obj1); 2341 colorSpace = GfxColorSpace::parse(&obj1);
2342 obj1.free(); 2342 obj1.free();
2343 if (!colorSpace) { 2343 if (!colorSpace) {
2344 goto err1; 2344 goto err1;
2345 } 2345 }
2346 dict->lookup("Decode", &obj1); 2346 dict->lookup("Decode", &obj1);
2347 if (obj1.isNull()) { 2347 if (obj1.isNull()) {
2348 obj1.free(); 2348 obj1.free();
2349 dict->lookup("D", &obj1); 2349 dict->lookup("D", &obj1);
2350 } 2350 }
2351 colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); 2351 colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
2352 obj1.free(); 2352 obj1.free();
2353 if (!colorMap->isOk()) { 2353 if (!colorMap->isOk()) {
2354 delete colorMap; 2354 delete colorMap;
2355 goto err1; 2355 goto err1;
2356 } 2356 }
2357 2357
2358 // get the mask 2358 // get the mask
2359 haveMask = gFalse; 2359 haveMask = gFalse;
2360 dict->lookup("Mask", &maskObj); 2360 dict->lookup("Mask", &maskObj);
2361 if (maskObj.isArray()) { 2361 if (maskObj.isArray()) {
2362 for (i = 0; i < maskObj.arrayGetLength(); ++i) { 2362 for (i = 0; i < maskObj.arrayGetLength(); ++i) {
2363 maskObj.arrayGet(i, &obj1); 2363 maskObj.arrayGet(i, &obj1);
2364 maskColors[i] = obj1.getInt(); 2364 maskColors[i] = obj1.getInt();
2365 obj1.free(); 2365 obj1.free();
2366 } 2366 }
2367 haveMask = gTrue; 2367 haveMask = gTrue;
2368 } 2368 }
2369 2369
2370 // draw it 2370 // draw it
2371 out->drawImage(state, ref, str, width, height, colorMap, 2371 out->drawImage(state, ref, str, width, height, colorMap,
2372 haveMask ? maskColors : (int *)NULL, inlineImg); 2372 haveMask ? maskColors : (int *)NULL, inlineImg);
2373 delete colorMap; 2373 delete colorMap;
2374 2374
2375 maskObj.free(); 2375 maskObj.free();
2376 } 2376 }
2377 2377
2378 if ((i = width * height) > 1000) { 2378 if ((i = width * height) > 1000) {
2379 i = 1000; 2379 i = 1000;
2380 } 2380 }
2381 updateLevel += i; 2381 updateLevel += i;
2382 2382
2383 return; 2383 return;
2384 2384
2385 err2: 2385 err2:
2386 obj1.free(); 2386 obj1.free();
2387 err1: 2387 err1:
2388 error(getPos(), "Bad image parameters"); 2388 error(getPos(), "Bad image parameters");
2389} 2389}
2390 2390
2391void Gfx::doForm(Object *str) { 2391void Gfx::doForm(Object *str) {
2392 Dict *dict; 2392 Dict *dict;
2393 Object matrixObj, bboxObj; 2393 Object matrixObj, bboxObj;
2394 fouble m[6], bbox[6]; 2394 fouble m[6], bbox[6];
2395 Object resObj; 2395 Object resObj;
2396 Dict *resDict; 2396 Dict *resDict;
2397 Object obj1; 2397 Object obj1;
2398 int i; 2398 int i;
2399 2399
2400 // get stream dict 2400 // get stream dict
2401 dict = str->streamGetDict(); 2401 dict = str->streamGetDict();
2402 2402
2403 // check form type 2403 // check form type
2404 dict->lookup("FormType", &obj1); 2404 dict->lookup("FormType", &obj1);
2405 if (!(obj1.isInt() && obj1.getInt() == 1)) { 2405 if (!(obj1.isInt() && obj1.getInt() == 1)) {
2406 error(getPos(), "Unknown form type"); 2406 error(getPos(), "Unknown form type");
2407 } 2407 }
2408 obj1.free(); 2408 obj1.free();
2409 2409
2410 // get bounding box 2410 // get bounding box
2411 dict->lookup("BBox", &bboxObj); 2411 dict->lookup("BBox", &bboxObj);
2412 if (!bboxObj.isArray()) { 2412 if (!bboxObj.isArray()) {
2413 matrixObj.free(); 2413 matrixObj.free();
2414 bboxObj.free(); 2414 bboxObj.free();
2415 error(getPos(), "Bad form bounding box"); 2415 error(getPos(), "Bad form bounding box");
2416 return; 2416 return;
2417 } 2417 }
2418 for (i = 0; i < 4; ++i) { 2418 for (i = 0; i < 4; ++i) {
2419 bboxObj.arrayGet(i, &obj1); 2419 bboxObj.arrayGet(i, &obj1);
2420 bbox[i] = obj1.getNum(); 2420 bbox[i] = obj1.getNum();
2421 obj1.free(); 2421 obj1.free();
2422 } 2422 }
2423 bboxObj.free(); 2423 bboxObj.free();
2424 2424
2425 // get matrix 2425 // get matrix
2426 dict->lookup("Matrix", &matrixObj); 2426 dict->lookup("Matrix", &matrixObj);
2427 if (matrixObj.isArray()) { 2427 if (matrixObj.isArray()) {
2428 for (i = 0; i < 6; ++i) { 2428 for (i = 0; i < 6; ++i) {
2429 matrixObj.arrayGet(i, &obj1); 2429 matrixObj.arrayGet(i, &obj1);
2430 m[i] = obj1.getNum(); 2430 m[i] = obj1.getNum();
2431 obj1.free(); 2431 obj1.free();
2432 } 2432 }
2433 } else { 2433 } else {
2434 m[0] = 1; m[1] = 0; 2434 m[0] = 1; m[1] = 0;
2435 m[2] = 0; m[3] = 1; 2435 m[2] = 0; m[3] = 1;
2436 m[4] = 0; m[5] = 0; 2436 m[4] = 0; m[5] = 0;
2437 } 2437 }
2438 matrixObj.free(); 2438 matrixObj.free();
2439 2439
2440 // get resources 2440 // get resources
2441 dict->lookup("Resources", &resObj); 2441 dict->lookup("Resources", &resObj);
2442 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; 2442 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
2443 2443
2444 // draw it 2444 // draw it
2445 doForm1(str, resDict, m, bbox); 2445 doForm1(str, resDict, m, bbox);
2446 2446
2447 resObj.free(); 2447 resObj.free();
2448} 2448}
2449 2449
2450void Gfx::doAnnot(Object *str, fouble xMin, fouble yMin, 2450void Gfx::doAnnot(Object *str, fouble xMin, fouble yMin,
2451 fouble xMax, fouble yMax) { 2451 fouble xMax, fouble yMax) {
2452 Dict *dict, *resDict; 2452 Dict *dict, *resDict;
2453 Object matrixObj, bboxObj, resObj; 2453 Object matrixObj, bboxObj, resObj;
2454 Object obj1; 2454 Object obj1;
2455 fouble m[6], bbox[6], ictm[6]; 2455 fouble m[6], bbox[6], ictm[6];
2456 fouble *ctm; 2456 fouble *ctm;
2457 fouble formX0, formY0, formX1, formY1; 2457 fouble formX0, formY0, formX1, formY1;
2458 fouble annotX0, annotY0, annotX1, annotY1; 2458 fouble annotX0, annotY0, annotX1, annotY1;
2459 fouble det, x, y, sx, sy; 2459 fouble det, x, y, sx, sy;
2460 int i; 2460 int i;
2461 2461
2462 // get stream dict 2462 // get stream dict
2463 dict = str->streamGetDict(); 2463 dict = str->streamGetDict();
2464 2464
2465 // get the form bounding box 2465 // get the form bounding box
2466 dict->lookup("BBox", &bboxObj); 2466 dict->lookup("BBox", &bboxObj);
2467 if (!bboxObj.isArray()) { 2467 if (!bboxObj.isArray()) {
2468 bboxObj.free(); 2468 bboxObj.free();
2469 error(getPos(), "Bad form bounding box"); 2469 error(getPos(), "Bad form bounding box");
2470 return; 2470 return;
2471 } 2471 }
2472 for (i = 0; i < 4; ++i) { 2472 for (i = 0; i < 4; ++i) {
2473 bboxObj.arrayGet(i, &obj1); 2473 bboxObj.arrayGet(i, &obj1);
2474 bbox[i] = obj1.getNum(); 2474 bbox[i] = obj1.getNum();
2475 obj1.free(); 2475 obj1.free();
2476 } 2476 }
2477 bboxObj.free(); 2477 bboxObj.free();
2478 2478
2479 // get the form matrix 2479 // get the form matrix
2480 dict->lookup("Matrix", &matrixObj); 2480 dict->lookup("Matrix", &matrixObj);
2481 if (matrixObj.isArray()) { 2481 if (matrixObj.isArray()) {
2482 for (i = 0; i < 6; ++i) { 2482 for (i = 0; i < 6; ++i) {
2483 matrixObj.arrayGet(i, &obj1); 2483 matrixObj.arrayGet(i, &obj1);
2484 m[i] = obj1.getNum(); 2484 m[i] = obj1.getNum();
2485 obj1.free(); 2485 obj1.free();
2486 } 2486 }
2487 } else { 2487 } else {
2488 m[0] = 1; m[1] = 0; 2488 m[0] = 1; m[1] = 0;
2489 m[2] = 0; m[3] = 1; 2489 m[2] = 0; m[3] = 1;
2490 m[4] = 0; m[5] = 0; 2490 m[4] = 0; m[5] = 0;
2491 } 2491 }
2492 matrixObj.free(); 2492 matrixObj.free();
2493 2493
2494 // transform the form bbox from form space to user space 2494 // transform the form bbox from form space to user space
2495 formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4]; 2495 formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
2496 formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5]; 2496 formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
2497 formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4]; 2497 formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
2498 formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5]; 2498 formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
2499 2499
2500 // transform the annotation bbox from default user space to user 2500 // transform the annotation bbox from default user space to user
2501 // space: (bbox * baseMatrix) * iCTM 2501 // space: (bbox * baseMatrix) * iCTM
2502 ctm = state->getCTM(); 2502 ctm = state->getCTM();
2503 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); 2503 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
2504 ictm[0] = ctm[3] * det; 2504 ictm[0] = ctm[3] * det;
2505 ictm[1] = -ctm[1] * det; 2505 ictm[1] = -ctm[1] * det;
2506 ictm[2] = -ctm[2] * det; 2506 ictm[2] = -ctm[2] * det;
2507 ictm[3] = ctm[0] * det; 2507 ictm[3] = ctm[0] * det;
2508 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; 2508 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
2509 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; 2509 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
2510 x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4]; 2510 x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4];
2511 y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5]; 2511 y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5];
2512 annotX0 = ictm[0] * x + ictm[2] * y + ictm[4]; 2512 annotX0 = ictm[0] * x + ictm[2] * y + ictm[4];
2513 annotY0 = ictm[1] * x + ictm[3] * y + ictm[5]; 2513 annotY0 = ictm[1] * x + ictm[3] * y + ictm[5];
2514 x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4]; 2514 x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4];
2515 y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5]; 2515 y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5];
2516 annotX1 = ictm[0] * x + ictm[2] * y + ictm[4]; 2516 annotX1 = ictm[0] * x + ictm[2] * y + ictm[4];
2517 annotY1 = ictm[1] * x + ictm[3] * y + ictm[5]; 2517 annotY1 = ictm[1] * x + ictm[3] * y + ictm[5];
2518 2518
2519 // swap min/max coords 2519 // swap min/max coords
2520 if (formX0 > formX1) { 2520 if (formX0 > formX1) {
2521 x = formX0; formX0 = formX1; formX1 = x; 2521 x = formX0; formX0 = formX1; formX1 = x;
2522 } 2522 }
2523 if (formY0 > formY1) { 2523 if (formY0 > formY1) {
2524 y = formY0; formY0 = formY1; formY1 = y; 2524 y = formY0; formY0 = formY1; formY1 = y;
2525 } 2525 }
2526 if (annotX0 > annotX1) { 2526 if (annotX0 > annotX1) {
2527 x = annotX0; annotX0 = annotX1; annotX1 = x; 2527 x = annotX0; annotX0 = annotX1; annotX1 = x;
2528 } 2528 }
2529 if (annotY0 > annotY1) { 2529 if (annotY0 > annotY1) {
2530 y = annotY0; annotY0 = annotY1; annotY1 = y; 2530 y = annotY0; annotY0 = annotY1; annotY1 = y;
2531 } 2531 }
2532 2532
2533 // scale the form to fit the annotation bbox 2533 // scale the form to fit the annotation bbox
2534 if (formX1 == formX0) { 2534 if (formX1 == formX0) {
2535 // this shouldn't happen 2535 // this shouldn't happen
2536 sx = 1; 2536 sx = 1;
2537 } else { 2537 } else {
2538 sx = (annotX1 - annotX0) / (formX1 - formX0); 2538 sx = (annotX1 - annotX0) / (formX1 - formX0);
2539 } 2539 }
2540 if (formY1 == formY0) { 2540 if (formY1 == formY0) {
2541 // this shouldn't happen 2541 // this shouldn't happen
2542 sy = 1; 2542 sy = 1;
2543 } else { 2543 } else {
2544 sy = (annotY1 - annotY0) / (formY1 - formY0); 2544 sy = (annotY1 - annotY0) / (formY1 - formY0);
2545 } 2545 }
2546 m[0] *= sx; 2546 m[0] *= sx;
2547 m[2] *= sx; 2547 m[2] *= sx;
2548 m[4] = (m[4] - formX0) * sx + annotX0; 2548 m[4] = (m[4] - formX0) * sx + annotX0;
2549 m[1] *= sy; 2549 m[1] *= sy;
2550 m[3] *= sy; 2550 m[3] *= sy;
2551 m[5] = (m[5] - formY0) * sy + annotY0; 2551 m[5] = (m[5] - formY0) * sy + annotY0;
2552 2552
2553 // get resources 2553 // get resources
2554 dict->lookup("Resources", &resObj); 2554 dict->lookup("Resources", &resObj);
2555 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; 2555 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
2556 2556
2557 // draw it 2557 // draw it
2558 doForm1(str, resDict, m, bbox); 2558 doForm1(str, resDict, m, bbox);
2559 2559
2560 resObj.free(); 2560 resObj.free();
2561 bboxObj.free(); 2561 bboxObj.free();
2562} 2562}
2563 2563
2564void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) { 2564void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) {
2565 Parser *oldParser; 2565 Parser *oldParser;
2566 fouble oldBaseMatrix[6]; 2566 fouble oldBaseMatrix[6];
2567 int i; 2567 int i;
2568 2568
2569 // push new resources on stack 2569 // push new resources on stack
2570 pushResources(resDict); 2570 pushResources(resDict);
2571 2571
2572 // save current graphics state 2572 // save current graphics state
2573 out->saveState(state); 2573 out->saveState(state);
2574 state = state->save(); 2574 state = state->save();
2575 2575
2576 // save current parser 2576 // save current parser
2577 oldParser = parser; 2577 oldParser = parser;
2578 2578
2579 // set form transformation matrix 2579 // set form transformation matrix
2580 state->concatCTM(matrix[0], matrix[1], matrix[2], 2580 state->concatCTM(matrix[0], matrix[1], matrix[2],
2581 matrix[3], matrix[4], matrix[5]); 2581 matrix[3], matrix[4], matrix[5]);
2582 out->updateCTM(state, matrix[0], matrix[1], matrix[2], 2582 out->updateCTM(state, matrix[0], matrix[1], matrix[2],
2583 matrix[3], matrix[4], matrix[5]); 2583 matrix[3], matrix[4], matrix[5]);
2584 2584
2585 // set new base matrix 2585 // set new base matrix
2586 for (i = 0; i < 6; ++i) { 2586 for (i = 0; i < 6; ++i) {
2587 oldBaseMatrix[i] = baseMatrix[i]; 2587 oldBaseMatrix[i] = baseMatrix[i];
2588 baseMatrix[i] = state->getCTM()[i]; 2588 baseMatrix[i] = state->getCTM()[i];
2589 } 2589 }
2590 2590
2591 // set form bounding box 2591 // set form bounding box
2592 state->moveTo(bbox[0], bbox[1]); 2592 state->moveTo(bbox[0], bbox[1]);
2593 state->lineTo(bbox[2], bbox[1]); 2593 state->lineTo(bbox[2], bbox[1]);
2594 state->lineTo(bbox[2], bbox[3]); 2594 state->lineTo(bbox[2], bbox[3]);
2595 state->lineTo(bbox[0], bbox[3]); 2595 state->lineTo(bbox[0], bbox[3]);
2596 state->closePath(); 2596 state->closePath();
2597 state->clip(); 2597 state->clip();
2598 out->clip(state); 2598 out->clip(state);
2599 state->clearPath(); 2599 state->clearPath();
2600 2600
2601 // draw the form 2601 // draw the form
2602 display(str, gFalse); 2602 display(str, gFalse);
2603 2603
2604 // restore base matrix 2604 // restore base matrix
2605 for (i = 0; i < 6; ++i) { 2605 for (i = 0; i < 6; ++i) {
2606 baseMatrix[i] = oldBaseMatrix[i]; 2606 baseMatrix[i] = oldBaseMatrix[i];
2607 } 2607 }
2608 2608
2609 // restore parser 2609 // restore parser
2610 parser = oldParser; 2610 parser = oldParser;
2611 2611
2612 // restore graphics state 2612 // restore graphics state
2613 state = state->restore(); 2613 state = state->restore();
2614 out->restoreState(state); 2614 out->restoreState(state);
2615 2615
2616 // pop resource stack 2616 // pop resource stack
2617 popResources(); 2617 popResources();
2618 2618
2619 return; 2619 return;
2620} 2620}
2621 2621
2622void Gfx::pushResources(Dict *resDict) { 2622void Gfx::pushResources(Dict *resDict) {
2623 res = new GfxResources(xref, resDict, res); 2623 res = new GfxResources(xref, resDict, res);
2624} 2624}
2625 2625
2626void Gfx::popResources() { 2626void Gfx::popResources() {
2627 GfxResources *resPtr; 2627 GfxResources *resPtr;
2628 2628
2629 resPtr = res->getNext(); 2629 resPtr = res->getNext();
2630 delete res; 2630 delete res;
2631 res = resPtr; 2631 res = resPtr;
2632} 2632}
2633 2633
2634//------------------------------------------------------------------------ 2634//------------------------------------------------------------------------
2635// in-line image operators 2635// in-line image operators
2636//------------------------------------------------------------------------ 2636//------------------------------------------------------------------------
2637 2637
2638void Gfx::opBeginImage(Object args[], int numArgs) { 2638void Gfx::opBeginImage(Object args[], int numArgs) {
2639 Stream *str; 2639 Stream *str;
2640 int c1, c2; 2640 int c1, c2;
2641 2641
2642 // build dict/stream 2642 // build dict/stream
2643 str = buildImageStream(); 2643 str = buildImageStream();
2644 2644
2645 // display the image 2645 // display the image
2646 if (str) { 2646 if (str) {
2647 doImage(NULL, str, gTrue); 2647 doImage(NULL, str, gTrue);
2648 2648
2649 // skip 'EI' tag 2649 // skip 'EI' tag
2650 c1 = str->getBaseStream()->getChar(); 2650 c1 = str->getBaseStream()->getChar();
2651 c2 = str->getBaseStream()->getChar(); 2651 c2 = str->getBaseStream()->getChar();
2652 while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) { 2652 while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) {
2653 c1 = c2; 2653 c1 = c2;
2654 c2 = str->getBaseStream()->getChar(); 2654 c2 = str->getBaseStream()->getChar();
2655 } 2655 }
2656 delete str; 2656 delete str;
2657 } 2657 }
2658} 2658}
2659 2659
2660Stream *Gfx::buildImageStream() { 2660Stream *Gfx::buildImageStream() {
2661 Object dict; 2661 Object dict;
2662 Object obj; 2662 Object obj;
2663 char *key; 2663 char *key;
2664 Stream *str; 2664 Stream *str;
2665 2665
2666 // build dictionary 2666 // build dictionary
2667 dict.initDict(xref); 2667 dict.initDict(xref);
2668 parser->getObj(&obj); 2668 parser->getObj(&obj);
2669 while (!obj.isCmd("ID") && !obj.isEOF()) { 2669 while (!obj.isCmd("ID") && !obj.isEOF()) {
2670 if (!obj.isName()) { 2670 if (!obj.isName()) {
2671 error(getPos(), "Inline image dictionary key must be a name object"); 2671 error(getPos(), "Inline image dictionary key must be a name object");
2672 obj.free(); 2672 obj.free();
2673 } else { 2673 } else {
2674 key = copyString(obj.getName()); 2674 key = copyString(obj.getName());
2675 obj.free(); 2675 obj.free();
2676 parser->getObj(&obj); 2676 parser->getObj(&obj);
2677 if (obj.isEOF() || obj.isError()) { 2677 if (obj.isEOF() || obj.isError()) {
2678 gfree(key); 2678 gfree(key);
2679 break; 2679 break;
2680 } 2680 }
2681 dict.dictAdd(key, &obj); 2681 dict.dictAdd(key, &obj);
2682 } 2682 }
2683 parser->getObj(&obj); 2683 parser->getObj(&obj);
2684 } 2684 }
2685 if (obj.isEOF()) { 2685 if (obj.isEOF()) {
2686 error(getPos(), "End of file in inline image"); 2686 error(getPos(), "End of file in inline image");
2687 obj.free(); 2687 obj.free();
2688 dict.free(); 2688 dict.free();
2689 return NULL; 2689 return NULL;
2690 } 2690 }
2691 obj.free(); 2691 obj.free();
2692 2692
2693 // make stream 2693 // make stream
2694 str = new EmbedStream(parser->getStream(), &dict); 2694 str = new EmbedStream(parser->getStream(), &dict);
2695 str = str->addFilters(&dict); 2695 str = str->addFilters(&dict);
2696 2696
2697 return str; 2697 return str;
2698} 2698}
2699 2699
2700void Gfx::opImageData(Object args[], int numArgs) { 2700void Gfx::opImageData(Object args[], int numArgs) {
2701 error(getPos(), "Internal: got 'ID' operator"); 2701 error(getPos(), "Internal: got 'ID' operator");
2702} 2702}
2703 2703
2704void Gfx::opEndImage(Object args[], int numArgs) { 2704void Gfx::opEndImage(Object args[], int numArgs) {
2705 error(getPos(), "Internal: got 'EI' operator"); 2705 error(getPos(), "Internal: got 'EI' operator");
2706} 2706}
2707 2707
2708//------------------------------------------------------------------------ 2708//------------------------------------------------------------------------
2709// type 3 font operators 2709// type 3 font operators
2710//------------------------------------------------------------------------ 2710//------------------------------------------------------------------------
2711 2711
2712void Gfx::opSetCharWidth(Object args[], int numArgs) { 2712void Gfx::opSetCharWidth(Object args[], int numArgs) {
2713 out->type3D0(state, args[0].getNum(), args[1].getNum()); 2713 out->type3D0(state, args[0].getNum(), args[1].getNum());
2714} 2714}
2715 2715
2716void Gfx::opSetCacheDevice(Object args[], int numArgs) { 2716void Gfx::opSetCacheDevice(Object args[], int numArgs) {
2717 out->type3D1(state, args[0].getNum(), args[1].getNum(), 2717 out->type3D1(state, args[0].getNum(), args[1].getNum(),
2718 args[2].getNum(), args[3].getNum(), 2718 args[2].getNum(), args[3].getNum(),
2719 args[4].getNum(), args[5].getNum()); 2719 args[4].getNum(), args[5].getNum());
2720} 2720}
2721 2721
2722//------------------------------------------------------------------------ 2722//------------------------------------------------------------------------
2723// compatibility operators 2723// compatibility operators
2724//------------------------------------------------------------------------ 2724//------------------------------------------------------------------------
2725 2725
2726void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) { 2726void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
2727 ++ignoreUndef; 2727 ++ignoreUndef;
2728} 2728}
2729 2729
2730void Gfx::opEndIgnoreUndef(Object args[], int numArgs) { 2730void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
2731 if (ignoreUndef > 0) 2731 if (ignoreUndef > 0)
2732 --ignoreUndef; 2732 --ignoreUndef;
2733} 2733}
2734 2734
2735//------------------------------------------------------------------------ 2735//------------------------------------------------------------------------
2736// marked content operators 2736// marked content operators
2737//------------------------------------------------------------------------ 2737//------------------------------------------------------------------------
2738 2738
2739void Gfx::opBeginMarkedContent(Object args[], int numArgs) { 2739void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
2740 if (printCommands) { 2740 if (printCommands) {
2741 printf(" marked content: %s ", args[0].getName()); 2741 printf(" marked content: %s ", args[0].getName());
2742 if (numArgs == 2) 2742 if (numArgs == 2)
2743 args[2].print(stdout); 2743 args[2].print(stdout);
2744 printf("\n"); 2744 printf("\n");
2745 fflush(stdout); 2745 fflush(stdout);
2746 } 2746 }
2747} 2747}
2748 2748
2749void Gfx::opEndMarkedContent(Object args[], int numArgs) { 2749void Gfx::opEndMarkedContent(Object args[], int numArgs) {
2750} 2750}
2751 2751
2752void Gfx::opMarkPoint(Object args[], int numArgs) { 2752void Gfx::opMarkPoint(Object args[], int numArgs) {
2753 if (printCommands) { 2753 if (printCommands) {
2754 printf(" mark point: %s ", args[0].getName()); 2754 printf(" mark point: %s ", args[0].getName());
2755 if (numArgs == 2) 2755 if (numArgs == 2)
2756 args[2].print(stdout); 2756 args[2].print(stdout);
2757 printf("\n"); 2757 printf("\n");
2758 fflush(stdout); 2758 fflush(stdout);
2759 } 2759 }
2760} 2760}
diff --git a/noncore/unsupported/qpdf/xpdf/Object.cc b/noncore/unsupported/qpdf/xpdf/Object.cc
index 6d92c6a..77f1317 100644
--- a/noncore/unsupported/qpdf/xpdf/Object.cc
+++ b/noncore/unsupported/qpdf/xpdf/Object.cc
@@ -1,223 +1,223 @@
1//======================================================================== 1//========================================================================
2// 2//
3// Object.cc 3// Object.cc
4// 4//
5// Copyright 1996-2002 Glyph & Cog, LLC 5// Copyright 1996-2002 Glyph & Cog, LLC
6// 6//
7//======================================================================== 7//========================================================================
8 8
9#ifdef __GNUC__ 9#ifdef __GNUC__
10#pragma implementation 10#pragma implementation
11#endif 11#endif
12 12
13#include <aconf.h> 13#include <aconf.h>
14#include <stddef.h> 14#include <stddef.h>
15#include "Object.h" 15#include "Object.h"
16#include "Array.h" 16#include "Array.h"
17#include "Dict.h" 17#include "Dict.h"
18#include "Error.h" 18#include "Error.h"
19#include "Stream.h" 19#include "Stream.h"
20#include "XRef.h" 20#include "XRef.h"
21 21
22//------------------------------------------------------------------------ 22//------------------------------------------------------------------------
23// Object 23// Object
24//------------------------------------------------------------------------ 24//------------------------------------------------------------------------
25 25
26char *objTypeNames[numObjTypes] = { 26char *objTypeNames[numObjTypes] = {
27 "boolean", 27 "boolean",
28 "integer", 28 "integer",
29 "real", 29 "real",
30 "string", 30 "string",
31 "name", 31 "name",
32 "null", 32 "null",
33 "array", 33 "array",
34 "dictionary", 34 "dictionary",
35 "stream", 35 "stream",
36 "ref", 36 "ref",
37 "cmd", 37 "cmd",
38 "error", 38 "error",
39 "eof", 39 "eof",
40 "none" 40 "none"
41}; 41};
42 42
43#ifdef DEBUG_MEM 43#ifdef DEBUG_MEM
44int Object::numAlloc[numObjTypes] = 44int Object::numAlloc[numObjTypes] =
45 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 45 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
46#endif 46#endif
47 47
48Object *Object::initArray(XRef *xref) { 48Object *Object::initArray(XRef *xref) {
49 initObj(objArray); 49 initObj(objArray);
50 array = new Array(xref); 50 array = new Array(xref);
51 return this; 51 return this;
52} 52}
53 53
54Object *Object::initDict(XRef *xref) { 54Object *Object::initDict(XRef *xref) {
55 initObj(objDict); 55 initObj(objDict);
56 dict = new Dict(xref); 56 dict = new Dict(xref);
57 return this; 57 return this;
58} 58}
59 59
60Object *Object::initStream(Stream *streamA) { 60Object *Object::initStream(Stream *streamA) {
61 initObj(objStream); 61 initObj(objStream);
62 stream = streamA; 62 stream = streamA;
63 return this; 63 return this;
64} 64}
65 65
66Object *Object::copy(Object *obj) { 66Object *Object::copy(Object *obj) {
67 *obj = *this; 67 *obj = *this;
68 switch (type) { 68 switch (type) {
69 case objString: 69 case objString:
70 obj->string = string->copy(); 70 obj->string = string->copy();
71 break; 71 break;
72 case objName: 72 case objName:
73 obj->name = copyString(name); 73 obj->name = copyString(name);
74 break; 74 break;
75 case objArray: 75 case objArray:
76 array->incRef(); 76 array->incRef();
77 break; 77 break;
78 case objDict: 78 case objDict:
79 dict->incRef(); 79 dict->incRef();
80 break; 80 break;
81 case objStream: 81 case objStream:
82 stream->incRef(); 82 stream->incRef();
83 break; 83 break;
84 case objCmd: 84 case objCmd:
85 obj->cmd = copyString(cmd); 85 obj->cmd = copyString(cmd);
86 break; 86 break;
87 default: 87 default:
88 break; 88 break;
89 } 89 }
90#ifdef DEBUG_MEM 90#ifdef DEBUG_MEM
91 ++numAlloc[type]; 91 ++numAlloc[type];
92#endif 92#endif
93 return obj; 93 return obj;
94} 94}
95 95
96Object *Object::fetch(XRef *xref, Object *obj) { 96Object *Object::fetch(XRef *xref, Object *obj) {
97 return (type == objRef && xref) ? 97 return (type == objRef && xref) ?
98 xref->fetch(ref.num, ref.gen, obj) : copy(obj); 98 xref->fetch(ref.num, ref.gen, obj) : copy(obj);
99} 99}
100 100
101void Object::free() { 101void Object::free() {
102 switch (type) { 102 switch (type) {
103 case objString: 103 case objString:
104 delete string; 104 delete string;
105 break; 105 break;
106 case objName: 106 case objName:
107 gfree(name); 107 gfree(name);
108 break; 108 break;
109 case objArray: 109 case objArray:
110 if (!array->decRef()) { 110 if (!array->decRef()) {
111 delete array; 111 delete array;
112 } 112 }
113 break; 113 break;
114 case objDict: 114 case objDict:
115 if (!dict->decRef()) { 115 if (!dict->decRef()) {
116 delete dict; 116 delete dict;
117 } 117 }
118 break; 118 break;
119 case objStream: 119 case objStream:
120 if (!stream->decRef()) { 120 if (!stream->decRef()) {
121 delete stream; 121 delete stream;
122 } 122 }
123 break; 123 break;
124 case objCmd: 124 case objCmd:
125 gfree(cmd); 125 gfree(cmd);
126 break; 126 break;
127 default: 127 default:
128 break; 128 break;
129 } 129 }
130#ifdef DEBUG_MEM 130#ifdef DEBUG_MEM
131 --numAlloc[type]; 131 --numAlloc[type];
132#endif 132#endif
133 type = objNone; 133 type = objNone;
134} 134}
135 135
136char *Object::getTypeName() { 136char *Object::getTypeName() {
137 return objTypeNames[type]; 137 return objTypeNames[type];
138} 138}
139 139
140void Object::print(FILE *f) { 140void Object::print(FILE *f) {
141 Object obj; 141 Object obj;
142 int i; 142 int i;
143 143
144 switch (type) { 144 switch (type) {
145 case objBool: 145 case objBool:
146 fprintf(f, "%s", booln ? "true" : "false"); 146 fprintf(f, "%s", booln ? "true" : "false");
147 break; 147 break;
148 case objInt: 148 case objInt:
149 fprintf(f, "%d", intg); 149 fprintf(f, "%d", intg);
150 break; 150 break;
151 case objReal: 151 case objReal:
152 fprintf(f, "%g", real); 152 fprintf(f, "%g", static_cast<double>(real));
153 break; 153 break;
154 case objString: 154 case objString:
155 fprintf(f, "("); 155 fprintf(f, "(");
156 fwrite(string->getCString(), 1, string->getLength(), stdout); 156 fwrite(string->getCString(), 1, string->getLength(), stdout);
157 fprintf(f, ")"); 157 fprintf(f, ")");
158 break; 158 break;
159 case objName: 159 case objName:
160 fprintf(f, "/%s", name); 160 fprintf(f, "/%s", name);
161 break; 161 break;
162 case objNull: 162 case objNull:
163 fprintf(f, "null"); 163 fprintf(f, "null");
164 break; 164 break;
165 case objArray: 165 case objArray:
166 fprintf(f, "["); 166 fprintf(f, "[");
167 for (i = 0; i < arrayGetLength(); ++i) { 167 for (i = 0; i < arrayGetLength(); ++i) {
168 if (i > 0) 168 if (i > 0)
169 fprintf(f, " "); 169 fprintf(f, " ");
170 arrayGetNF(i, &obj); 170 arrayGetNF(i, &obj);
171 obj.print(f); 171 obj.print(f);
172 obj.free(); 172 obj.free();
173 } 173 }
174 fprintf(f, "]"); 174 fprintf(f, "]");
175 break; 175 break;
176 case objDict: 176 case objDict:
177 fprintf(f, "<<"); 177 fprintf(f, "<<");
178 for (i = 0; i < dictGetLength(); ++i) { 178 for (i = 0; i < dictGetLength(); ++i) {
179 fprintf(f, " /%s ", dictGetKey(i)); 179 fprintf(f, " /%s ", dictGetKey(i));
180 dictGetValNF(i, &obj); 180 dictGetValNF(i, &obj);
181 obj.print(f); 181 obj.print(f);
182 obj.free(); 182 obj.free();
183 } 183 }
184 fprintf(f, " >>"); 184 fprintf(f, " >>");
185 break; 185 break;
186 case objStream: 186 case objStream:
187 fprintf(f, "<stream>"); 187 fprintf(f, "<stream>");
188 break; 188 break;
189 case objRef: 189 case objRef:
190 fprintf(f, "%d %d R", ref.num, ref.gen); 190 fprintf(f, "%d %d R", ref.num, ref.gen);
191 break; 191 break;
192 case objCmd: 192 case objCmd:
193 fprintf(f, "%s", cmd); 193 fprintf(f, "%s", cmd);
194 break; 194 break;
195 case objError: 195 case objError:
196 fprintf(f, "<error>"); 196 fprintf(f, "<error>");
197 break; 197 break;
198 case objEOF: 198 case objEOF:
199 fprintf(f, "<EOF>"); 199 fprintf(f, "<EOF>");
200 break; 200 break;
201 case objNone: 201 case objNone:
202 fprintf(f, "<none>"); 202 fprintf(f, "<none>");
203 break; 203 break;
204 } 204 }
205} 205}
206 206
207void Object::memCheck(FILE *f) { 207void Object::memCheck(FILE *f) {
208#ifdef DEBUG_MEM 208#ifdef DEBUG_MEM
209 int i; 209 int i;
210 int t; 210 int t;
211 211
212 t = 0; 212 t = 0;
213 for (i = 0; i < numObjTypes; ++i) 213 for (i = 0; i < numObjTypes; ++i)
214 t += numAlloc[i]; 214 t += numAlloc[i];
215 if (t > 0) { 215 if (t > 0) {
216 fprintf(f, "Allocated objects:\n"); 216 fprintf(f, "Allocated objects:\n");
217 for (i = 0; i < numObjTypes; ++i) { 217 for (i = 0; i < numObjTypes; ++i) {
218 if (numAlloc[i] > 0) 218 if (numAlloc[i] > 0)
219 fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]); 219 fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
220 } 220 }
221 } 221 }
222#endif 222#endif
223} 223}
diff --git a/noncore/unsupported/qpdf/xpdf/Page.cc b/noncore/unsupported/qpdf/xpdf/Page.cc
index 9cc08c4..aead7da 100644
--- a/noncore/unsupported/qpdf/xpdf/Page.cc
+++ b/noncore/unsupported/qpdf/xpdf/Page.cc
@@ -1,281 +1,281 @@
1//======================================================================== 1//========================================================================
2// 2//
3// Page.cc 3// Page.cc
4// 4//
5// Copyright 1996-2002 Glyph & Cog, LLC 5// Copyright 1996-2002 Glyph & Cog, LLC
6// 6//
7//======================================================================== 7//========================================================================
8 8
9#ifdef __GNUC__ 9#ifdef __GNUC__
10#pragma implementation 10#pragma implementation
11#endif 11#endif
12 12
13#include <aconf.h> 13#include <aconf.h>
14#include <stddef.h> 14#include <stddef.h>
15#include "Object.h" 15#include "Object.h"
16#include "Array.h" 16#include "Array.h"
17#include "Dict.h" 17#include "Dict.h"
18#include "XRef.h" 18#include "XRef.h"
19#include "Link.h" 19#include "Link.h"
20#include "OutputDev.h" 20#include "OutputDev.h"
21#ifndef PDF_PARSER_ONLY 21#ifndef PDF_PARSER_ONLY
22#include "Gfx.h" 22#include "Gfx.h"
23#include "Annot.h" 23#include "Annot.h"
24#endif 24#endif
25#include "Error.h" 25#include "Error.h"
26#include "Page.h" 26#include "Page.h"
27 27
28//------------------------------------------------------------------------ 28//------------------------------------------------------------------------
29// PageAttrs 29// PageAttrs
30//------------------------------------------------------------------------ 30//------------------------------------------------------------------------
31 31
32PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { 32PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
33 Object obj1; 33 Object obj1;
34 fouble w, h; 34 fouble w, h;
35 35
36 // get old/default values 36 // get old/default values
37 if (attrs) { 37 if (attrs) {
38 mediaBox = attrs->mediaBox; 38 mediaBox = attrs->mediaBox;
39 cropBox = attrs->cropBox; 39 cropBox = attrs->cropBox;
40 haveCropBox = attrs->haveCropBox; 40 haveCropBox = attrs->haveCropBox;
41 rotate = attrs->rotate; 41 rotate = attrs->rotate;
42 attrs->resources.copy(&resources); 42 attrs->resources.copy(&resources);
43 } else { 43 } else {
44 // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary 44 // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
45 // but some (non-compliant) PDF files don't specify a MediaBox 45 // but some (non-compliant) PDF files don't specify a MediaBox
46 mediaBox.x1 = 0; 46 mediaBox.x1 = 0;
47 mediaBox.y1 = 0; 47 mediaBox.y1 = 0;
48 mediaBox.x2 = 612; 48 mediaBox.x2 = 612;
49 mediaBox.y2 = 792; 49 mediaBox.y2 = 792;
50 cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; 50 cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
51 haveCropBox = gFalse; 51 haveCropBox = gFalse;
52 rotate = 0; 52 rotate = 0;
53 resources.initNull(); 53 resources.initNull();
54 } 54 }
55 55
56 // media box 56 // media box
57 readBox(dict, "MediaBox", &mediaBox); 57 readBox(dict, "MediaBox", &mediaBox);
58 58
59 // crop box 59 // crop box
60 cropBox = mediaBox; 60 cropBox = mediaBox;
61 haveCropBox = readBox(dict, "CropBox", &cropBox); 61 haveCropBox = readBox(dict, "CropBox", &cropBox);
62 62
63 // if the MediaBox is excessively larger than the CropBox, 63 // if the MediaBox is excessively larger than the CropBox,
64 // just use the CropBox 64 // just use the CropBox
65 limitToCropBox = gFalse; 65 limitToCropBox = gFalse;
66 if (haveCropBox) { 66 if (haveCropBox) {
67 w = 0.25 * (cropBox.x2 - cropBox.x1); 67 w = 0.25 * (cropBox.x2 - cropBox.x1);
68 h = 0.25 * (cropBox.y2 - cropBox.y1); 68 h = 0.25 * (cropBox.y2 - cropBox.y1);
69 if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w || 69 if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
70 (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) { 70 (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
71 limitToCropBox = gTrue; 71 limitToCropBox = gTrue;
72 } 72 }
73 } 73 }
74 74
75 // other boxes 75 // other boxes
76 bleedBox = cropBox; 76 bleedBox = cropBox;
77 readBox(dict, "BleedBox", &bleedBox); 77 readBox(dict, "BleedBox", &bleedBox);
78 trimBox = cropBox; 78 trimBox = cropBox;
79 readBox(dict, "TrimBox", &trimBox); 79 readBox(dict, "TrimBox", &trimBox);
80 artBox = cropBox; 80 artBox = cropBox;
81 readBox(dict, "ArtBox", &artBox); 81 readBox(dict, "ArtBox", &artBox);
82 82
83 // rotate 83 // rotate
84 dict->lookup("Rotate", &obj1); 84 dict->lookup("Rotate", &obj1);
85 if (obj1.isInt()) { 85 if (obj1.isInt()) {
86 rotate = obj1.getInt(); 86 rotate = obj1.getInt();
87 } 87 }
88 obj1.free(); 88 obj1.free();
89 while (rotate < 0) { 89 while (rotate < 0) {
90 rotate += 360; 90 rotate += 360;
91 } 91 }
92 while (rotate >= 360) { 92 while (rotate >= 360) {
93 rotate -= 360; 93 rotate -= 360;
94 } 94 }
95 95
96 // misc attributes 96 // misc attributes
97 dict->lookup("LastModified", &lastModified); 97 dict->lookup("LastModified", &lastModified);
98 dict->lookup("BoxColorInfo", &boxColorInfo); 98 dict->lookup("BoxColorInfo", &boxColorInfo);
99 dict->lookup("Group", &group); 99 dict->lookup("Group", &group);
100 dict->lookup("Metadata", &metadata); 100 dict->lookup("Metadata", &metadata);
101 dict->lookup("PieceInfo", &pieceInfo); 101 dict->lookup("PieceInfo", &pieceInfo);
102 dict->lookup("SeparationInfo", &separationInfo); 102 dict->lookup("SeparationInfo", &separationInfo);
103 103
104 // resource dictionary 104 // resource dictionary
105 dict->lookup("Resources", &obj1); 105 dict->lookup("Resources", &obj1);
106 if (obj1.isDict()) { 106 if (obj1.isDict()) {
107 resources.free(); 107 resources.free();
108 obj1.copy(&resources); 108 obj1.copy(&resources);
109 } 109 }
110 obj1.free(); 110 obj1.free();
111} 111}
112 112
113PageAttrs::~PageAttrs() { 113PageAttrs::~PageAttrs() {
114 lastModified.free(); 114 lastModified.free();
115 boxColorInfo.free(); 115 boxColorInfo.free();
116 group.free(); 116 group.free();
117 metadata.free(); 117 metadata.free();
118 pieceInfo.free(); 118 pieceInfo.free();
119 separationInfo.free(); 119 separationInfo.free();
120 resources.free(); 120 resources.free();
121} 121}
122 122
123GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) { 123GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
124 PDFRectangle tmp; 124 PDFRectangle tmp;
125 Object obj1, obj2; 125 Object obj1, obj2;
126 GBool ok; 126 GBool ok;
127 127
128 dict->lookup(key, &obj1); 128 dict->lookup(key, &obj1);
129 if (obj1.isArray() && obj1.arrayGetLength() == 4) { 129 if (obj1.isArray() && obj1.arrayGetLength() == 4) {
130 ok = gTrue; 130 ok = gTrue;
131 obj1.arrayGet(0, &obj2); 131 obj1.arrayGet(0, &obj2);
132 if (obj2.isNum()) { 132 if (obj2.isNum()) {
133 tmp.x1 = obj2.getNum(); 133 tmp.x1 = obj2.getNum();
134 } else { 134 } else {
135 ok = gFalse; 135 ok = gFalse;
136 } 136 }
137 obj2.free(); 137 obj2.free();
138 obj1.arrayGet(1, &obj2); 138 obj1.arrayGet(1, &obj2);
139 if (obj2.isNum()) { 139 if (obj2.isNum()) {
140 tmp.y1 = obj2.getNum(); 140 tmp.y1 = obj2.getNum();
141 } else { 141 } else {
142 ok = gFalse; 142 ok = gFalse;
143 } 143 }
144 obj2.free(); 144 obj2.free();
145 obj1.arrayGet(2, &obj2); 145 obj1.arrayGet(2, &obj2);
146 if (obj2.isNum()) { 146 if (obj2.isNum()) {
147 tmp.x2 = obj2.getNum(); 147 tmp.x2 = obj2.getNum();
148 } else { 148 } else {
149 ok = gFalse; 149 ok = gFalse;
150 } 150 }
151 obj2.free(); 151 obj2.free();
152 obj1.arrayGet(3, &obj2); 152 obj1.arrayGet(3, &obj2);
153 if (obj2.isNum()) { 153 if (obj2.isNum()) {
154 tmp.y2 = obj2.getNum(); 154 tmp.y2 = obj2.getNum();
155 } else { 155 } else {
156 ok = gFalse; 156 ok = gFalse;
157 } 157 }
158 obj2.free(); 158 obj2.free();
159 if (ok) { 159 if (ok) {
160 *box = tmp; 160 *box = tmp;
161 } 161 }
162 } else { 162 } else {
163 ok = gFalse; 163 ok = gFalse;
164 } 164 }
165 obj1.free(); 165 obj1.free();
166 return ok; 166 return ok;
167} 167}
168 168
169//------------------------------------------------------------------------ 169//------------------------------------------------------------------------
170// Page 170// Page
171//------------------------------------------------------------------------ 171//------------------------------------------------------------------------
172 172
173Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, 173Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
174 GBool printCommandsA) { 174 GBool printCommandsA) {
175 175
176 ok = gTrue; 176 ok = gTrue;
177 xref = xrefA; 177 xref = xrefA;
178 num = numA; 178 num = numA;
179 printCommands = printCommandsA; 179 printCommands = printCommandsA;
180 180
181 // get attributes 181 // get attributes
182 attrs = attrsA; 182 attrs = attrsA;
183 183
184 // annotations 184 // annotations
185 pageDict->lookupNF("Annots", &annots); 185 pageDict->lookupNF("Annots", &annots);
186 if (!(annots.isRef() || annots.isArray() || annots.isNull())) { 186 if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
187 error(-1, "Page annotations object (page %d) is wrong type (%s)", 187 error(-1, "Page annotations object (page %d) is wrong type (%s)",
188 num, annots.getTypeName()); 188 num, annots.getTypeName());
189 annots.free(); 189 annots.free();
190 goto err2; 190 goto err2;
191 } 191 }
192 192
193 // contents 193 // contents
194 pageDict->lookupNF("Contents", &contents); 194 pageDict->lookupNF("Contents", &contents);
195 if (!(contents.isRef() || contents.isArray() || 195 if (!(contents.isRef() || contents.isArray() ||
196 contents.isNull())) { 196 contents.isNull())) {
197 error(-1, "Page contents object (page %d) is wrong type (%s)", 197 error(-1, "Page contents object (page %d) is wrong type (%s)",
198 num, contents.getTypeName()); 198 num, contents.getTypeName());
199 contents.free(); 199 contents.free();
200 goto err1; 200 goto err1;
201 } 201 }
202 202
203 return; 203 return;
204 204
205 err2: 205 err2:
206 annots.initNull(); 206 annots.initNull();
207 err1: 207 err1:
208 contents.initNull(); 208 contents.initNull();
209 ok = gFalse; 209 ok = gFalse;
210} 210}
211 211
212Page::~Page() { 212Page::~Page() {
213 delete attrs; 213 delete attrs;
214 annots.free(); 214 annots.free();
215 contents.free(); 215 contents.free();
216} 216}
217 217
218void Page::display(OutputDev *out, fouble dpi, int rotate, 218void Page::display(OutputDev *out, fouble dpi, int rotate,
219 Links *links, Catalog *catalog) { 219 Links *links, Catalog *catalog) {
220#ifndef PDF_PARSER_ONLY 220#ifndef PDF_PARSER_ONLY
221 PDFRectangle *box, *cropBox; 221 PDFRectangle *box, *cropBox;
222 Gfx *gfx; 222 Gfx *gfx;
223 Object obj; 223 Object obj;
224 Link *link; 224 Link *link;
225 int i; 225 int i;
226 Annots *annotList; 226 Annots *annotList;
227 227
228 box = getBox(); 228 box = getBox();
229 cropBox = getCropBox(); 229 cropBox = getCropBox();
230 230
231 if (printCommands) { 231 if (printCommands) {
232 printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", 232 printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
233 box->x1, box->y1, box->x2, box->y2); 233 static_cast<double>(box->x1), static_cast<double>(box->y1), static_cast<double>(box->x2), static_cast<double>(box->y2));
234 if (isCropped()) { 234 if (isCropped()) {
235 printf("***** CropBox = ll:%g,%g ur:%g,%g\n", 235 printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
236 cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); 236 static_cast<double>(cropBox->x1), static_cast<double>(cropBox->y1), static_cast<double>(cropBox->x2), static_cast<double>(cropBox->y2));
237 } 237 }
238 printf("***** Rotate = %d\n", attrs->getRotate()); 238 printf("***** Rotate = %d\n", attrs->getRotate());
239 } 239 }
240 240
241 rotate += getRotate(); 241 rotate += getRotate();
242 if (rotate >= 360) { 242 if (rotate >= 360) {
243 rotate -= 360; 243 rotate -= 360;
244 } else if (rotate < 0) { 244 } else if (rotate < 0) {
245 rotate += 360; 245 rotate += 360;
246 } 246 }
247 gfx = new Gfx(xref, out, num, attrs->getResourceDict(), 247 gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
248 dpi, box, isCropped(), cropBox, rotate, printCommands); 248 dpi, box, isCropped(), cropBox, rotate, printCommands);
249 contents.fetch(xref, &obj); 249 contents.fetch(xref, &obj);
250 if (!obj.isNull()) { 250 if (!obj.isNull()) {
251 gfx->display(&obj); 251 gfx->display(&obj);
252 } 252 }
253 obj.free(); 253 obj.free();
254 254
255 // draw links 255 // draw links
256 if (links) { 256 if (links) {
257 for (i = 0; i < links->getNumLinks(); ++i) { 257 for (i = 0; i < links->getNumLinks(); ++i) {
258 link = links->getLink(i); 258 link = links->getLink(i);
259 out->drawLink(link, catalog); 259 out->drawLink(link, catalog);
260 } 260 }
261 out->dump(); 261 out->dump();
262 } 262 }
263 263
264 // draw non-link annotations 264 // draw non-link annotations
265 //~ need to reset CTM ??? 265 //~ need to reset CTM ???
266 annotList = new Annots(xref, annots.fetch(xref, &obj)); 266 annotList = new Annots(xref, annots.fetch(xref, &obj));
267 obj.free(); 267 obj.free();
268 if (annotList->getNumAnnots() > 0) { 268 if (annotList->getNumAnnots() > 0) {
269 if (printCommands) { 269 if (printCommands) {
270 printf("***** Annotations\n"); 270 printf("***** Annotations\n");
271 } 271 }
272 for (i = 0; i < annotList->getNumAnnots(); ++i) { 272 for (i = 0; i < annotList->getNumAnnots(); ++i) {
273 annotList->getAnnot(i)->draw(gfx); 273 annotList->getAnnot(i)->draw(gfx);
274 } 274 }
275 out->dump(); 275 out->dump();
276 } 276 }
277 delete annotList; 277 delete annotList;
278 278
279 delete gfx; 279 delete gfx;
280#endif 280#endif
281} 281}